Merge
diff --git a/.hgtags b/.hgtags
index ea4f9ad..29390ba 100644
--- a/.hgtags
+++ b/.hgtags
@@ -1,3 +1,8 @@
+42a00b9a965366eeb9727297e0356c63ea090f50 jdk8u20-b26
+baed82f70a27d1a1f7ac6fc84e0c07bfbb560b1d jdk8u20-b23
+2360e3d587d68ae8c643dc052004e4f372a6c33f jdk8u40-b01
+c0131ac648a8a481e339e1d08409521ae5742a65 jdk8u40-b02
+cc778b4c400aa37fd4980eed05bdda2be1d4e9ad jdk8u40-b03
 6d80bca57a4d91b15e814f466143ceeb915e7b37 jdk8u5-b04
 e694221608d0f593542e92b30e897e6e0cdba2d5 jdk8u11-b00
 612c1079f821b5ec23fa0a398573cf4e62c98c88 jdk8u5-b05
diff --git a/.hgtags-top-repo b/.hgtags-top-repo
index 2b4ff20..8fcb666 100644
--- a/.hgtags-top-repo
+++ b/.hgtags-top-repo
@@ -313,3 +313,8 @@
 b14daf2459c5430dfe5d435483d6f424cff09584 jdk8u20-b23
 1710841b0229403f4af85eac8b68ea5065a26c81 jdk8u20-b24
 1710841b0229403f4af85eac8b68ea5065a26c81 jdk8u20-b25
+d1a7ea2c3e1091e0df1285963328a96f475f240d jdk8u20-b26
+0dccc4aca1859b1ff7dca9db214f7f38c4ddbbce jdk8u40-b00
+f8736a40a35df0c8055c8a94b96e5381b381ad33 jdk8u40-b01
+b6a148730f2b14193c308bc9c866c36ee6c08ed3 jdk8u40-b02
+a0224ac4135108efdbcf316c7c4b02f8a93c35fe jdk8u40-b03
diff --git a/Makefile b/Makefile
index cd5f66b..7fe922b 100644
--- a/Makefile
+++ b/Makefile
@@ -66,7 +66,7 @@
     # First, find out the valid targets
     # Run the makefile with an arbitrary SPEC using -p -q (quiet dry-run and dump rules) to find
     # available PHONY targets. Use this list as valid targets to pass on to the repeated calls.
-    all_phony_targets=$(filter-out $(global_targets) bundles bundles-only final-images-only, $(strip $(shell \
+    all_phony_targets=$(filter-out $(global_targets), $(strip $(shell \
         cd $(root_dir) && $(MAKE) -p -q FRC SPEC=$(firstword $(SPEC)) | \
         grep ^.PHONY: | head -n 1 | cut -d " " -f 2-)))
 
@@ -79,10 +79,6 @@
   endif
 endif
 
-# Include this after a potential spec file has been included so that the bundles target
-# has access to the spec variables.
-include $(root_dir)/make/Jprt.gmk
-
 # Here are "global" targets, i.e. targets that can be executed without specifying a single configuration.
 # If you addd more global targets, please update the variable global_targets in MakeHelpers.
 
diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh
index 0da1410..4adfbfe 100644
--- a/common/autoconf/generated-configure.sh
+++ b/common/autoconf/generated-configure.sh
@@ -3868,7 +3868,7 @@
 #CUSTOM_AUTOCONF_INCLUDE
 
 # Do not change or remove the following line, it is needed for consistency checks:
-DATE_WHEN_GENERATED=1397150809
+DATE_WHEN_GENERATED=1405022087
 
 ###############################################################################
 #
@@ -7926,7 +7926,7 @@
   fi
 
   # Replace the commas with AND for use in the build directory name.
-  ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/'`
+  ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'`
   COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/kernel,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'`
   if test "x$COUNT_VARIANTS" != "x,1"; then
     BUILDING_MULTIPLE_JVM_VARIANTS=yes
diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4
index 00c2003..095fa79 100644
--- a/common/autoconf/jdk-options.m4
+++ b/common/autoconf/jdk-options.m4
@@ -134,7 +134,7 @@
   fi
 
   # Replace the commas with AND for use in the build directory name.
-  ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/'`
+  ANDED_JVM_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/^,//' -e 's/,$//' -e 's/,/AND/g'`
   COUNT_VARIANTS=`$ECHO "$JVM_VARIANTS" | $SED -e 's/server,/1/' -e 's/client,/1/' -e 's/minimal1,/1/' -e 's/kernel,/1/' -e 's/zero,/1/' -e 's/zeroshark,/1/' -e 's/core,/1/'`
   if test "x$COUNT_VARIANTS" != "x,1"; then
     BUILDING_MULTIPLE_JVM_VARIANTS=yes
diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh
index 2282c32..13e9142 100644
--- a/common/bin/hgforest.sh
+++ b/common/bin/hgforest.sh
@@ -1,7 +1,6 @@
 #!/bin/sh
-
 #
-# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2009, 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
@@ -23,165 +22,375 @@
 # questions.
 #
 
-# Shell script for a fast parallel forest command
-command="$1"
-pull_extra_base="$2"
+# Shell script for a fast parallel forest/trees command
 
-if [ "" = "$command" ] ; then
-  echo No command to hg supplied!
-  exit 1
+usage() {
+      echo "usage: $0 [-h|--help] [-q|--quiet] [-v|--verbose] [-s|--sequential] [--] <command> [commands...]" > ${status_output}
+      echo "Environment variables which modify behaviour:"
+      echo "   HGFOREST_QUIET      : (boolean) If 'true' then standard output is redirected to /dev/null"
+      echo "   HGFOREST_VERBOSE    : (boolean) If 'true' then Mercurial asked to produce verbose output"
+      echo "   HGFOREST_SEQUENTIAL : (boolean) If 'true' then repos are processed sequentially. Disables concurrency"
+      echo "   HGFOREST_GLOBALOPTS : (string, must begin with space) Additional Mercurial global options"
+      echo "   HGFOREST_REDIRECT   : (file path) Redirect standard output to specified file"
+      echo "   HGFOREST_FIFOS      : (boolean) Default behaviour for FIFO detection. Does not override FIFOs disabled"
+      echo "   HGFOREST_CONCURRENCY: (positive integer) Number of repos to process concurrently"
+      echo "   HGFOREST_DEBUG      : (boolean) If 'true' then temp files are retained"
+      exit 1
+}
+
+global_opts="${HGFOREST_GLOBALOPTS:-}"
+status_output="${HGFOREST_REDIRECT:-/dev/stdout}"
+qflag="${HGFOREST_QUIET:-false}"
+vflag="${HGFOREST_VERBOSE:-false}"
+sflag="${HGFOREST_SEQUENTIAL:-false}"
+while [ $# -gt 0 ]
+do
+  case $1 in
+    -h | --help )
+      usage
+      ;;
+
+    -q | --quiet )
+      qflag="true"
+      ;;
+
+    -v | --verbose )
+      vflag="true"
+      ;;
+
+    -s | --sequential )
+      sflag="true"
+      ;;
+
+    '--' ) # no more options
+      shift; break
+      ;;
+
+    -*)  # bad option
+      usage
+      ;;
+
+     * )  # non option
+      break
+      ;;
+  esac
+  shift
+done
+
+# silence standard output?
+if [ ${qflag} = "true" ] ; then
+  global_opts="${global_opts} -q"
+  status_output="/dev/null"
 fi
 
+# verbose output?
+if [ ${vflag} = "true" ] ; then
+  global_opts="${global_opts} -v"
+fi
+
+# Make sure we have a command.
+if [ $# -lt 1 -o -z "${1:-}" ] ; then
+  echo "ERROR: No command to hg supplied!"
+  usage
+fi
+
+command="$1"; shift
+command_args="${@:-}"
+
 # Clean out the temporary directory that stores the pid files.
 tmp=/tmp/forest.$$
 rm -f -r ${tmp}
 mkdir -p ${tmp}
 
+
+if [ "${HGFOREST_DEBUG:-false}" = "true" ] ; then
+  echo "DEBUG: temp files are in: ${tmp}"
+fi
+
+# Check if we can use fifos for monitoring sub-process completion.
+echo "1" > ${tmp}/read
+while_subshell=1
+while read line; do
+  while_subshell=0
+  break;
+done < ${tmp}/read
+rm ${tmp}/read
+
+on_windows=`uname -s | egrep -ic -e 'cygwin|msys'`
+
+if [ ${while_subshell} = "1" -o ${on_windows} = "1" ]; then
+  # cygwin has (2014-04-18) broken (single writer only) FIFOs
+  # msys has (2014-04-18) no FIFOs.
+  # older shells create a sub-shell for redirect to while
+  have_fifos="false"
+else
+  have_fifos="${HGFOREST_FIFOS:-true}"
+fi
+
 safe_interrupt () {
   if [ -d ${tmp} ]; then
     if [ "`ls ${tmp}/*.pid`" != "" ]; then
-      echo "Waiting for processes ( `cat ${tmp}/*.pid | tr '\n' ' '`) to terminate nicely!"
+      echo "Waiting for processes ( `cat ${tmp}/.*.pid ${tmp}/*.pid 2> /dev/null | tr '\n' ' '`) to terminate nicely!" > ${status_output}
       sleep 1
       # Pipe stderr to dev/null to silence kill, that complains when trying to kill
       # a subprocess that has already exited.
       kill -TERM `cat ${tmp}/*.pid | tr '\n' ' '` 2> /dev/null
       wait
-      echo Interrupt complete!
+      echo "Interrupt complete!" > ${status_output}
     fi
+    rm -f -r ${tmp}
   fi
-  rm -f -r ${tmp}
-  exit 1
+  exit 130
 }
 
 nice_exit () {
   if [ -d ${tmp} ]; then
-    if [ "`ls ${tmp}`" != "" ]; then
+    if [ "`ls -A ${tmp} 2> /dev/null`" != "" ]; then
       wait
     fi
+    if [ "${HGFOREST_DEBUG:-false}" != "true" ] ; then
+      rm -f -r ${tmp}
+    fi
   fi
-  rm -f -r ${tmp}
 }
 
 trap 'safe_interrupt' INT QUIT
 trap 'nice_exit' EXIT
 
+subrepos="corba jaxp jaxws langtools jdk hotspot nashorn"
+subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs"
+
 # Only look in specific locations for possible forests (avoids long searches)
 pull_default=""
 repos=""
 repos_extra=""
-if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
-  subrepos="corba jaxp jaxws langtools jdk hotspot nashorn"
-  if [ -f .hg/hgrc ] ; then
-    pull_default=`hg paths default`
-    if [ "${pull_default}" = "" ] ; then
-      echo "ERROR: Need initial clone with 'hg paths default' defined"
-      exit 1
-    fi
-  fi
-  if [ "${pull_default}" = "" ] ; then
-    echo "ERROR: Need initial repository to use this script"
+if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then
+  # we must be a clone
+  if [ ! -f .hg/hgrc ] ; then
+    echo "ERROR: Need initial repository to use this script" > ${status_output}
     exit 1
   fi
+
+  # the clone must know where it came from (have a default pull path).
+  pull_default=`hg paths default`
+  if [ "${pull_default}" = "" ] ; then
+    echo "ERROR: Need initial clone with 'hg paths default' defined" > ${status_output}
+    exit 1
+  fi
+
+  # determine which sub repos need to be cloned.
   for i in ${subrepos} ; do
     if [ ! -f ${i}/.hg/hgrc ] ; then
       repos="${repos} ${i}"
     fi
   done
-  if [ "${pull_extra_base}" != "" ] ; then
-    subrepos_extra="jdk/src/closed jdk/make/closed jdk/test/closed hotspot/make/closed hotspot/src/closed hotspot/test/closed deploy install sponsors pubs"
-    pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
-    pull_extra="${pull_extra_base}/${pull_default_tail}"
+
+  pull_default_tail=`echo ${pull_default} | sed -e 's@^.*://[^/]*/\(.*\)@\1@'`
+
+  if [ -n "${command_args}" ] ; then
+    # if there is an "extra sources" path then reparent "extra" repos to that path
+    if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then
+      echo "ERROR: Need initial clone from non-local source" > ${status_output}
+      exit 1
+    fi
+    pull_extra="${command_args}/${pull_default_tail}"
+
+    # determine which extra subrepos need to be cloned.
     for i in ${subrepos_extra} ; do
       if [ ! -f ${i}/.hg/hgrc ] ; then
         repos_extra="${repos_extra} ${i}"
       fi
     done
+  else
+    if [ "x${pull_default}" = "x${pull_default_tail}" ] ; then
+      # local source repo. Clone the "extra" subrepos that exist there.
+      for i in ${subrepos_extra} ; do
+        if [ -f ${pull_default}/${i}/.hg/hgrc -a ! -f ${i}/.hg/hgrc ] ; then
+          # sub-repo there in source but not here
+          repos_extra="${repos_extra} ${i}"
+        fi
+      done
+    fi
   fi
-  at_a_time=2
+
   # Any repos to deal with?
   if [ "${repos}" = "" -a "${repos_extra}" = "" ] ; then
+    echo "No repositories to process." > ${status_output}
     exit
   fi
+
+  # Repos to process concurrently. Clone does better with low concurrency.
+  at_a_time="${HGFOREST_CONCURRENCY:-2}"
 else
-  hgdirs=`ls -d ./.hg ./*/.hg ./*/*/.hg ./*/*/*/.hg ./*/*/*/*/.hg 2>/dev/null`
-  # Derive repository names from the .hg directory locations
-  for i in ${hgdirs} ; do
-    repos="${repos} `echo ${i} | sed -e 's@/.hg$@@'`"
+  # Process command for all of the present repos
+  for i in . ${subrepos} ${subrepos_extra} ; do
+    if [ -d ${i}/.hg ] ; then
+      repos="${repos} ${i}"
+    fi
   done
+
+  # Any repos to deal with?
+  if [ "${repos}" = "" ] ; then
+    echo "No repositories to process." > ${status_output}
+    exit
+  fi
+
+  # any of the repos locked?
+  locked=""
   for i in ${repos} ; do
     if [ -h ${i}/.hg/store/lock -o -f ${i}/.hg/store/lock ] ; then
       locked="${i} ${locked}"
     fi
   done
-  at_a_time=8
-  # Any repos to deal with?
-  if [ "${repos}" = "" ] ; then
-    echo "No repositories to process."
-    exit
-  fi
   if [ "${locked}" != "" ] ; then
-    echo "These repositories are locked: ${locked}"
-    exit
+    echo "ERROR: These repositories are locked: ${locked}" > ${status_output}
+    exit 1
   fi
+
+  # Repos to process concurrently.
+  at_a_time="${HGFOREST_CONCURRENCY:-8}"
 fi
 
 # Echo out what repositories we do a command on.
-echo "# Repositories: ${repos} ${repos_extra}"
-echo
+echo "# Repositories: ${repos} ${repos_extra}" > ${status_output}
 
-# Run the supplied command on all repos in parallel.
-n=0
-for i in ${repos} ${repos_extra} ; do
-  n=`expr ${n} '+' 1`
-  repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
-  reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
-  pull_base="${pull_default}"
-  for j in $repos_extra ; do
-      if [ "$i" = "$j" ] ; then
-          pull_base="${pull_extra}"
-      fi
-  done
+if [ "${command}" = "serve" ] ; then
+  # "serve" is run for all the repos as one command.
   (
     (
-      if [ "${command}" = "clone" -o "${command}" = "fclone" ] ; then
-        pull_newrepo="`echo ${pull_base}/${i} | sed -e 's@\([^:]/\)//*@\1@g'`"
-        echo hg clone ${pull_newrepo} ${i}
-        path="`dirname ${i}`"
-        if [ "${path}" != "." ] ; then
-          times=0
-          while [ ! -d "${path}" ]   ## nested repo, ensure containing dir exists
-          do
-            times=`expr ${times} '+' 1`
-            if [ `expr ${times} '%' 10` -eq 0 ] ; then
-              echo ${path} still not created, waiting...
-            fi
-            sleep 5
-          done
-        fi
-        (PYTHONUNBUFFERED=true hg clone ${pull_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
-      else
-        echo "cd ${i} && hg $*"
-        cd ${i} && (PYTHONUNBUFFERED=true hg "$@"; echo "$?" > ${tmp}/${repopidfile}.pid.rc )&
-      fi
-      echo $! > ${tmp}/${repopidfile}.pid
-    ) 2>&1 | sed -e "s@^@${reponame}:   @") &
+      cwd=`pwd`
+      serving=`basename ${cwd}`
+      (
+        echo "[web]"
+        echo "description = ${serving}"
+        echo "allow_push = *"
+        echo "push_ssl = False"
 
-  if [ `expr ${n} '%' ${at_a_time}` -eq 0 ] ; then
-    sleep 2
-    echo Waiting 5 secs before spawning next background command.
-    sleep 3
+        echo "[paths]"
+        for i in ${repos} ; do
+          if [ "${i}" != "." ] ; then
+            echo "/${serving}/${i} = ${i}"
+          else
+            echo "/${serving} = ${cwd}"
+          fi
+        done
+      ) > ${tmp}/serve.web-conf
+
+      echo "serving root repo ${serving}" > ${status_output}
+
+      echo "hg${global_opts} serve" > ${status_output}
+      (PYTHONUNBUFFERED=true hg${global_opts} serve -A ${status_output} -E ${status_output} --pid-file ${tmp}/serve.pid --web-conf ${tmp}/serve.web-conf; echo "$?" > ${tmp}/serve.pid.rc ) 2>&1 &
+    ) 2>&1 | sed -e "s@^@serve:   @" > ${status_output}
+  ) &
+else
+  # Run the supplied command on all repos in parallel.
+
+  # n is the number of subprocess started or which might still be running.
+  n=0
+  if [ ${have_fifos} = "true" ]; then
+    # if we have fifos use them to detect command completion.
+    mkfifo ${tmp}/fifo
+    exec 3<>${tmp}/fifo
   fi
-done
-# Wait for all hg commands to complete
+
+  # iterate over all of the subrepos.
+  for i in ${repos} ${repos_extra} ; do
+    n=`expr ${n} '+' 1`
+    repopidfile=`echo ${i} | sed -e 's@./@@' -e 's@/@_@g'`
+    reponame=`echo ${i} | sed -e :a -e 's/^.\{1,20\}$/ &/;ta'`
+    pull_base="${pull_default}"
+
+    # regular repo or "extra" repo?
+    for j in ${repos_extra} ; do
+      if [ "${i}" = "${j}" ] ; then
+        # it's an "extra"
+        pull_base="${pull_extra}"
+      fi
+    done
+
+    # remove trailing slash
+    pull_base="`echo ${pull_base} | sed -e 's@[/]*$@@'`"
+
+    # execute the command on the subrepo
+    (
+      (
+        if [ "${command}" = "clone" -o "${command}" = "fclone" -o "${command}" = "tclone" ] ; then
+          # some form of clone
+          clone_newrepo="${pull_base}/${i}"
+          parent_path="`dirname ${i}`"
+          if [ "${parent_path}" != "." ] ; then
+            times=0
+            while [ ! -d "${parent_path}" ] ; do  ## nested repo, ensure containing dir exists
+              if [ "${sflag}" = "true" ] ; then
+                # Missing parent is fatal during sequential operation.
+                echo "ERROR: Missing parent path: ${parent_path}" > ${status_output}
+                exit 1
+              fi
+              times=`expr ${times} '+' 1`
+              if [ `expr ${times} '%' 10` -eq 0 ] ; then
+                echo "${parent_path} still not created, waiting..." > ${status_output}
+              fi
+              sleep 5
+            done
+          fi
+          # run the clone command.
+          echo "hg${global_opts} clone ${clone_newrepo} ${i}" > ${status_output}
+          (PYTHONUNBUFFERED=true hg${global_opts} clone ${clone_newrepo} ${i}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
+        else
+          # run the command.
+          echo "cd ${i} && hg${global_opts} ${command} ${command_args}" > ${status_output}
+          cd ${i} && (PYTHONUNBUFFERED=true hg${global_opts} ${command} ${command_args}; echo "$?" > ${tmp}/${repopidfile}.pid.rc ) 2>&1 &
+        fi
+
+        echo $! > ${tmp}/${repopidfile}.pid
+      ) 2>&1 | sed -e "s@^@${reponame}:   @" > ${status_output}
+      # tell the fifo waiter that this subprocess is done.
+      if [ ${have_fifos} = "true" ]; then
+        echo "${i}" >&3
+      fi
+    ) &
+
+    if [ "${sflag}" = "true" ] ; then
+      # complete this task before starting another.
+      wait
+    else
+      if [ "${have_fifos}" = "true" ]; then
+        # check on count of running subprocesses and possibly wait for completion
+        if [ ${n} -ge ${at_a_time} ] ; then
+          # read will block until there are completed subprocesses
+          while read repo_done; do
+            n=`expr ${n} '-' 1`
+            if [ ${n} -lt ${at_a_time} ] ; then
+              # we should start more subprocesses
+              break;
+            fi
+          done <&3
+        fi
+      else
+        # Compare completions to starts
+        completed="`(ls -a1 ${tmp}/*.pid.rc 2> /dev/null | wc -l) || echo 0`"
+        while [ `expr ${n} '-' ${completed}` -ge ${at_a_time} ] ; do
+          # sleep a short time to give time for something to complete
+          sleep 1
+          completed="`(ls -a1 ${tmp}/*.pid.rc 2> /dev/null | wc -l) || echo 0`"
+        done
+      fi
+    fi
+  done
+fi
+
+# Wait for all subprocesses to complete
 wait
 
 # Terminate with exit 0 only if all subprocesses were successful
 ec=0
 if [ -d ${tmp} ]; then
-  for rc in ${tmp}/*.pid.rc ; do
+  rcfiles="`(ls -a ${tmp}/*.pid.rc 2> /dev/null) || echo ''`"
+  for rc in ${rcfiles} ; do
     exit_code=`cat ${rc} | tr -d ' \n\r'`
     if [ "${exit_code}" != "0" ] ; then
-      echo "WARNING: ${rc} exited abnormally."
+      repo="`echo ${rc} | sed -e 's@^'${tmp}'@@' -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`"
+      echo "WARNING: ${repo} exited abnormally (${exit_code})" > ${status_output}
       ec=1
     fi
   done
diff --git a/corba/.hgtags b/corba/.hgtags
index 25ed5d3..c3891ff 100644
--- a/corba/.hgtags
+++ b/corba/.hgtags
@@ -311,3 +311,8 @@
 919405d7316dfcbddee5ad8dd08905916df88e04 jdk8u20-b23
 34c930eaa6b591621afde05ca2e24571c91cdc9b jdk8u20-b24
 34c930eaa6b591621afde05ca2e24571c91cdc9b jdk8u20-b25
+37bde23c96f66912c44b1b893c08d4ad4cff5f4e jdk8u20-b26
+7d1e0f0b63f1d66c77924d8b2a1accdf8f7480db jdk8u40-b00
+c5d9822a3c18cd9e274dfe99e91c33e02bd8f8f4 jdk8u40-b01
+504b4455570e14b7fc0a837a09c6401c603516d9 jdk8u40-b02
+91cd0ecdbe08eadf09ee89e64bf45360da8f2413 jdk8u40-b03
diff --git a/corba/src/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java b/corba/src/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java
index 1748397..6908cad 100644
--- a/corba/src/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java
+++ b/corba/src/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -35,7 +35,8 @@
 import java.io.OutputStream;
 import java.io.ObjectOutputStream;
 import java.io.ObjectOutput;
-import java.util.Hashtable;
+import java.util.Map;
+import java.util.HashMap;
 
 import org.omg.CORBA.INTERNAL;
 
@@ -49,7 +50,7 @@
      */
     private class HookPutFields extends ObjectOutputStream.PutField
     {
-        private Hashtable fields = new Hashtable();
+        private Map<String,Object> fields = new HashMap<>();
 
         /**
          * Put the value of the named boolean field into the persistent field.
@@ -140,7 +141,6 @@
     public OutputStreamHook()
         throws java.io.IOException {
         super();
-
     }
 
     public void defaultWriteObject() throws IOException {
diff --git a/get_source.sh b/get_source.sh
index f83a376..5e874d1 100644
--- a/get_source.sh
+++ b/get_source.sh
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 #
-# Copyright (c) 2010, 2012, 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
@@ -25,9 +25,76 @@
 # questions.
 #
 
-# Get clones of all nested repositories
-sh ./common/bin/hgforest.sh clone "$@" || exit 1
+to_stderr() {
+    echo "$@" >&2
+}
+
+error() {
+    to_stderr "ERROR: $1"
+    exit ${2:-126}
+}
+
+warning() {
+    to_stderr "WARNING: $1"
+}
+
+version_field() {
+  # rev is typically omitted for minor and major releases
+  field=`echo ${1}.0 | cut -f ${2} -d .`
+  if expr 1 + $field >/dev/null 2> /dev/null; then
+    echo $field
+  else
+    echo -1
+  fi
+}
+
+# Version check
+
+# required
+reqdmajor=1
+reqdminor=4
+reqdrev=0
+
+# requested
+rqstmajor=2
+rqstminor=6
+rqstrev=3
+
+
+# installed
+hgwhere="`command -v hg`"
+if [ "x$hgwhere" = "x" ]; then
+  error "Could not locate Mercurial command"
+fi
+
+hgversion="`hg --version 2> /dev/null | sed -n -e 's@^Mercurial Distributed SCM (version \([^+]*\).*)\$@\1@p'`"
+if [ "x${hgversion}" = "x" ] ; then
+  error "Could not determine Mercurial version of $hgwhere"
+fi
+
+hgmajor="`version_field $hgversion 1`"
+hgminor="`version_field $hgversion 2`"
+hgrev="`version_field $hgversion 3`"
+
+if [ $hgmajor -eq -1 -o $hgminor -eq -1 -o $hgrev -eq -1 ] ; then
+  error "Could not determine Mercurial version of $hgwhere from \"$hgversion\""
+fi
+
+
+# Require
+if [ $hgmajor -lt $reqdmajor -o \( $hgmajor -eq $reqdmajor -a $hgminor -lt $reqdminor \) -o \( $hgmajor -eq $reqdmajor -a $hgminor -eq $reqdminor -a $hgrev -lt $reqdrev \) ] ; then
+  error "Mercurial version $reqdmajor.$reqdminor.$reqdrev or later is required. $hgwhere is version $hgversion"
+fi
+
+
+# Request
+if [ $hgmajor -lt $rqstmajor -o \( $hgmajor -eq $rqstmajor -a $hgminor -lt $rqstminor \) -o \( $hgmajor -eq $rqstmajor -a $hgminor -eq $rqstminor -a $hgrev -lt $rqstrev \) ] ; then
+  warning "Mercurial version $rqstmajor.$rqstminor.$rqstrev or later is recommended. $hgwhere is version $hgversion"
+fi
+
+
+# Get clones of all absent nested repositories (harmless if already exist)
+sh ./common/bin/hgforest.sh clone "$@" || exit $?
 
 # Update all existing repositories to the latest sources
 sh ./common/bin/hgforest.sh pull -u
-
diff --git a/hotspot/.hgtags b/hotspot/.hgtags
index 9e915f0..1beef64 100644
--- a/hotspot/.hgtags
+++ b/hotspot/.hgtags
@@ -500,3 +500,16 @@
 42ddd0bbcb6630fe463ec9bc1893c838d5edff1b jdk8u20-b24
 00cf2b6f51b9560b01030e8f4c28c466f0b21fe3 hs25.20-b23
 19408d5fd31c25ce60c43dd33e92b96e8df4a4ea jdk8u20-b25
+eaa4074a7e3975cd33ec55e6b584586e2ac681bd jdk8u20-b26
+4828415ebbf11e205dcc08e97ad5ae7dd03522f9 jdk8u40-b00
+d952af8cf67dd1e7ab5fec9a299c6c6dafd1863e hs25.40-b01
+f0afba33c928ddaa2d5f003b90d683c143f78ea3 hs25.40-b02
+e2976043eac37c8036f6a6dfa454787f64fa3f56 hs25.40-b03
+cb95655ef06fece507bbc2792474411ab2e899ab hs25.40-b04
+dc06b830ea95ed953cac02e9e67a75ab682edb97 jdk8u40-b01
+897333c7e5874625bd26d09fdaf242196024e9c2 hs25.40-b05
+f52cb91647590fe4a12af295a8a87e2cb761b044 jdk8u40-b02
+fbc31318922c31488c0464ccd864d2cd1d9e21a7 hs25.40-b06
+38539608359a6dfc5740abb66f878af643757c3b jdk8u40-b03
+c3990b8c710e4c1996b5cd579681645d9f0408c1 hs25.40-b07
+3f1b3f2dd1cb224747a11a6788e58b5cb7683d57 hs25.40-b08
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java
index eea5e4b..9ba1d2b 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1CollectedHeap.java
@@ -45,8 +45,8 @@
 public class G1CollectedHeap extends SharedHeap {
     // HeapRegionSeq _seq;
     static private long hrsFieldOffset;
-    // MemRegion _g1_committed;
-    static private long g1CommittedFieldOffset;
+    // MemRegion _g1_reserved;
+    static private long g1ReservedFieldOffset;
     // size_t _summary_bytes_used;
     static private CIntegerField summaryBytesUsedField;
     // G1MonitoringSupport* _g1mm;
@@ -68,7 +68,6 @@
         Type type = db.lookupType("G1CollectedHeap");
 
         hrsFieldOffset = type.getField("_hrs").getOffset();
-        g1CommittedFieldOffset = type.getField("_g1_committed").getOffset();
         summaryBytesUsedField = type.getCIntegerField("_summary_bytes_used");
         g1mmField = type.getAddressField("_g1mm");
         oldSetFieldOffset = type.getField("_old_set").getOffset();
@@ -76,9 +75,7 @@
     }
 
     public long capacity() {
-        Address g1CommittedAddr = addr.addOffsetTo(g1CommittedFieldOffset);
-        MemRegion g1Committed = new MemRegion(g1CommittedAddr);
-        return g1Committed.byteSize();
+        return hrs().capacity();
     }
 
     public long used() {
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java
index cfbea40..e8bbaaa 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/G1HeapRegionTable.java
@@ -93,19 +93,35 @@
     private class HeapRegionIterator implements Iterator<HeapRegion> {
         private long index;
         private long length;
+        private HeapRegion next;
+
+        public HeapRegion positionToNext() {
+          HeapRegion result = next;
+          while (index < length && at(index) == null) {
+            index++;
+          }
+          if (index < length) {
+            next = at(index);
+            index++; // restart search at next element
+          } else {
+            next = null;
+          }
+          return result;
+        }
 
         @Override
-        public boolean hasNext() { return index < length; }
+        public boolean hasNext() { return next != null;     }
 
         @Override
-        public HeapRegion next() { return at(index++);    }
+        public HeapRegion next() { return positionToNext(); }
 
         @Override
-        public void remove()     { /* not supported */    }
+        public void remove()     { /* not supported */      }
 
-        HeapRegionIterator(long committedLength) {
+        HeapRegionIterator(long totalLength) {
             index = 0;
-            length = committedLength;
+            length = totalLength;
+            positionToNext();
         }
     }
 
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java
index 4aa7620..8d92497 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegion.java
@@ -24,23 +24,26 @@
 
 package sun.jvm.hotspot.gc_implementation.g1;
 
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Observable;
 import java.util.Observer;
-
 import sun.jvm.hotspot.debugger.Address;
-import sun.jvm.hotspot.memory.ContiguousSpace;
+import sun.jvm.hotspot.memory.CompactibleSpace;
+import sun.jvm.hotspot.memory.MemRegion;
 import sun.jvm.hotspot.runtime.VM;
+import sun.jvm.hotspot.types.AddressField;
 import sun.jvm.hotspot.types.CIntegerField;
 import sun.jvm.hotspot.types.Type;
 import sun.jvm.hotspot.types.TypeDataBase;
 
 // Mirror class for HeapRegion. Currently we don't actually include
-// any of its fields but only iterate over it (which we get "for free"
-// as HeapRegion ultimately inherits from ContiguousSpace).
+// any of its fields but only iterate over it.
 
-public class HeapRegion extends ContiguousSpace {
+public class HeapRegion extends CompactibleSpace {
     // static int GrainBytes;
     static private CIntegerField grainBytesField;
+    static private AddressField topField;
 
     static {
         VM.registerVMInitializedObserver(new Observer() {
@@ -54,6 +57,8 @@
         Type type = db.lookupType("HeapRegion");
 
         grainBytesField = type.getCIntegerField("GrainBytes");
+        topField = type.getAddressField("_top");
+
     }
 
     static public long grainBytes() {
@@ -63,4 +68,25 @@
     public HeapRegion(Address addr) {
         super(addr);
     }
+
+    public Address top() {
+        return topField.getValue(addr);
+    }
+
+    @Override
+    public List getLiveRegions() {
+        List res = new ArrayList();
+        res.add(new MemRegion(bottom(), top()));
+        return res;
+    }
+
+    @Override
+    public long used() {
+        return top().minus(bottom());
+    }
+
+    @Override
+    public long free() {
+        return end().minus(top());
+    }
 }
diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java
index 190bf56..8d011ed 100644
--- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java
+++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/gc_implementation/g1/HeapRegionSeq.java
@@ -43,7 +43,7 @@
     // G1HeapRegionTable _regions
     static private long regionsFieldOffset;
     // uint _committed_length
-    static private CIntegerField committedLengthField;
+    static private CIntegerField numCommittedField;
 
     static {
         VM.registerVMInitializedObserver(new Observer() {
@@ -57,7 +57,7 @@
         Type type = db.lookupType("HeapRegionSeq");
 
         regionsFieldOffset = type.getField("_regions").getOffset();
-        committedLengthField = type.getCIntegerField("_committed_length");
+        numCommittedField = type.getCIntegerField("_num_committed");
     }
 
     private G1HeapRegionTable regions() {
@@ -66,16 +66,20 @@
                                                              regionsAddr);
     }
 
+    public long capacity() {
+        return length() * HeapRegion.grainBytes();
+    }
+
     public long length() {
         return regions().length();
     }
 
     public long committedLength() {
-        return committedLengthField.getValue(addr);
+        return numCommittedField.getValue(addr);
     }
 
     public Iterator<HeapRegion> heapRegionIterator() {
-        return regions().heapRegionIterator(committedLength());
+        return regions().heapRegionIterator(length());
     }
 
     public HeapRegionSeq(Address addr) {
diff --git a/hotspot/make/bsd/makefiles/vm.make b/hotspot/make/bsd/makefiles/vm.make
index 3e8ea76..93640d8 100644
--- a/hotspot/make/bsd/makefiles/vm.make
+++ b/hotspot/make/bsd/makefiles/vm.make
@@ -243,10 +243,10 @@
 
 vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES))
 
-mapfile : $(MAPFILE) vm.def
+mapfile : $(MAPFILE) vm.def mapfile_ext
 	rm -f $@
 	awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE")	\
-                 { system ("cat vm.def"); }		\
+                 { system ("cat mapfile_ext"); system ("cat vm.def"); } \
                else					\
                  { print $$0 }				\
              }' > $@ < $(MAPFILE)
@@ -258,6 +258,13 @@
 vm.def: $(Res_Files) $(Obj_Files)
 	sh $(GAMMADIR)/make/bsd/makefiles/build_vm_def.sh *.o > $@
 
+mapfile_ext:
+	rm -f $@
+	touch $@
+	if [ -f $(HS_ALT_MAKE)/bsd/makefiles/mapfile-ext ]; then \
+	  cat $(HS_ALT_MAKE)/bsd/makefiles/mapfile-ext > $@; \
+	fi
+
 STATIC_CXX = false
 
 ifeq ($(LINK_INTO),AOUT)
diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make
index dcaa3a1..9139ec3 100644
--- a/hotspot/make/excludeSrc.make
+++ b/hotspot/make/excludeSrc.make
@@ -77,30 +77,40 @@
       CXXFLAGS += -DINCLUDE_ALL_GCS=0
       CFLAGS += -DINCLUDE_ALL_GCS=0
 
-      Src_Files_EXCLUDE += \
-	cmsAdaptiveSizePolicy.cpp cmsCollectorPolicy.cpp \
-	cmsGCAdaptivePolicyCounters.cpp cmsLockVerifier.cpp compactibleFreeListSpace.cpp \
-	concurrentMarkSweepGeneration.cpp concurrentMarkSweepThread.cpp \
-	freeChunk.cpp adaptiveFreeList.cpp promotionInfo.cpp vmCMSOperations.cpp \
-	collectionSetChooser.cpp concurrentG1Refine.cpp concurrentG1RefineThread.cpp \
-	concurrentMark.cpp concurrentMarkThread.cpp dirtyCardQueue.cpp g1AllocRegion.cpp \
-	g1BlockOffsetTable.cpp g1CardCounts.cpp g1CollectedHeap.cpp g1CollectorPolicy.cpp \
-	g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \
-	g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp g1OopClosures.cpp \
-	g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1StringDedup.cpp g1StringDedupStat.cpp \
-	g1StringDedupTable.cpp g1StringDedupThread.cpp g1StringDedupQueue.cpp g1_globals.cpp heapRegion.cpp \
-	g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \
-	ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp g1CodeCacheRemSet.cpp \
-	adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \
-	cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \
-	parallelScavengeHeap.cpp parMarkBitMap.cpp pcTasks.cpp psAdaptiveSizePolicy.cpp \
-	psCompactionManager.cpp psGCAdaptivePolicyCounters.cpp psGenerationCounters.cpp \
-	psMarkSweep.cpp psMarkSweepDecorator.cpp psMemoryPool.cpp psOldGen.cpp \
-	psParallelCompact.cpp psPromotionLAB.cpp psPromotionManager.cpp psScavenge.cpp \
-	psTasks.cpp psVirtualspace.cpp psYoungGen.cpp vmPSOperations.cpp asParNewGeneration.cpp \
-	parCardTableModRefBS.cpp parGCAllocBuffer.cpp parNewGeneration.cpp mutableSpace.cpp \
-	gSpaceCounters.cpp allocationStats.cpp spaceCounters.cpp gcAdaptivePolicyCounters.cpp \
-	mutableNUMASpace.cpp immutableSpace.cpp yieldingWorkGroup.cpp hSpaceCounters.cpp
+      gc_impl := $(GAMMADIR)/src/share/vm/gc_implementation
+      gc_exclude :=							\
+	$(notdir $(wildcard $(gc_impl)/concurrentMarkSweep/*.cpp))	\
+	$(notdir $(wildcard $(gc_impl)/g1/*.cpp))			\
+	$(notdir $(wildcard $(gc_impl)/parallelScavenge/*.cpp))		\
+	$(notdir $(wildcard $(gc_impl)/parNew/*.cpp))
+      Src_Files_EXCLUDE += $(gc_exclude)
+
+      # Exclude everything in $(gc_impl)/shared except the files listed
+      # in $(gc_shared_keep).
+      gc_shared_all := $(notdir $(wildcard $(gc_impl)/shared/*.cpp))
+      gc_shared_keep :=							\
+	adaptiveSizePolicy.cpp						\
+	ageTable.cpp							\
+	collectorCounters.cpp						\
+	cSpaceCounters.cpp						\
+	gcPolicyCounters.cpp						\
+	gcStats.cpp							\
+	gcTimer.cpp							\
+	gcTrace.cpp							\
+	gcTraceSend.cpp							\
+	gcTraceTime.cpp							\
+	gcUtil.cpp							\
+	generationCounters.cpp						\
+	markSweep.cpp							\
+	objectCountEventSender.cpp					\
+	spaceDecorator.cpp						\
+	vmGCOperations.cpp
+      Src_Files_EXCLUDE += $(filter-out $(gc_shared_keep),$(gc_shared_all))
+
+      # src/share/vm/services
+      Src_Files_EXCLUDE +=						\
+	g1MemoryPool.cpp						\
+	psMemoryPool.cpp
 endif
 
 ifeq ($(INCLUDE_NMT), false)
@@ -108,8 +118,8 @@
       CFLAGS += -DINCLUDE_NMT=0
 
       Src_Files_EXCLUDE += \
-	 memBaseline.cpp memPtr.cpp memRecorder.cpp memReporter.cpp memSnapshot.cpp memTrackWorker.cpp \
-	 memTracker.cpp nmtDCmd.cpp
+	 memBaseline.cpp memReporter.cpp mallocTracker.cpp virtualMemoryTracker.cpp nmtCommon.cpp \
+	 memTracker.cpp nmtDCmd.cpp mallocSiteTable.cpp
 endif
 
 -include $(HS_ALT_MAKE)/excludeSrc.make
diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version
index f84dc74..7dbc0b3 100644
--- a/hotspot/make/hotspot_version
+++ b/hotspot/make/hotspot_version
@@ -34,8 +34,8 @@
 HOTSPOT_VM_COPYRIGHT=Copyright 2014
 
 HS_MAJOR_VER=25
-HS_MINOR_VER=20
-HS_BUILD_NUMBER=23
+HS_MINOR_VER=40
+HS_BUILD_NUMBER=08
 
 JDK_MAJOR_VER=1
 JDK_MINOR_VER=8
diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties
index f93f9f2..da2269c 100644
--- a/hotspot/make/jprt.properties
+++ b/hotspot/make/jprt.properties
@@ -33,7 +33,7 @@
 
 # This tells jprt what default release we want to build
 
-jprt.hotspot.default.release=jdk8u20
+jprt.hotspot.default.release=jdk8u40
 
 jprt.tools.default.release=${jprt.submit.option.release?${jprt.submit.option.release}:${jprt.hotspot.default.release}}
 
@@ -47,65 +47,65 @@
 #       sparc etc.
 
 # Define the Solaris platforms we want for the various releases
-jprt.my.solaris.sparcv9.jdk8u20=solaris_sparcv9_5.10
+jprt.my.solaris.sparcv9.jdk8u40=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9.jdk7=solaris_sparcv9_5.10
 jprt.my.solaris.sparcv9.jdk7u8=${jprt.my.solaris.sparcv9.jdk7}
 jprt.my.solaris.sparcv9=${jprt.my.solaris.sparcv9.${jprt.tools.default.release}}
 
-jprt.my.solaris.x64.jdk8u20=solaris_x64_5.10
+jprt.my.solaris.x64.jdk8u40=solaris_x64_5.10
 jprt.my.solaris.x64.jdk7=solaris_x64_5.10
 jprt.my.solaris.x64.jdk7u8=${jprt.my.solaris.x64.jdk7}
 jprt.my.solaris.x64=${jprt.my.solaris.x64.${jprt.tools.default.release}}
 
-jprt.my.linux.i586.jdk8u20=linux_i586_2.6
+jprt.my.linux.i586.jdk8u40=linux_i586_2.6
 jprt.my.linux.i586.jdk7=linux_i586_2.6
 jprt.my.linux.i586.jdk7u8=${jprt.my.linux.i586.jdk7}
 jprt.my.linux.i586=${jprt.my.linux.i586.${jprt.tools.default.release}}
 
-jprt.my.linux.x64.jdk8u20=linux_x64_2.6
+jprt.my.linux.x64.jdk8u40=linux_x64_2.6
 jprt.my.linux.x64.jdk7=linux_x64_2.6
 jprt.my.linux.x64.jdk7u8=${jprt.my.linux.x64.jdk7}
 jprt.my.linux.x64=${jprt.my.linux.x64.${jprt.tools.default.release}}
 
-jprt.my.linux.ppc.jdk8u20=linux_ppc_2.6
+jprt.my.linux.ppc.jdk8u40=linux_ppc_2.6
 jprt.my.linux.ppc.jdk7=linux_ppc_2.6
 jprt.my.linux.ppc.jdk7u8=${jprt.my.linux.ppc.jdk7}
 jprt.my.linux.ppc=${jprt.my.linux.ppc.${jprt.tools.default.release}}
 
-jprt.my.linux.ppcv2.jdk8u20=linux_ppcv2_2.6
+jprt.my.linux.ppcv2.jdk8u40=linux_ppcv2_2.6
 jprt.my.linux.ppcv2.jdk7=linux_ppcv2_2.6
 jprt.my.linux.ppcv2.jdk7u8=${jprt.my.linux.ppcv2.jdk7}
 jprt.my.linux.ppcv2=${jprt.my.linux.ppcv2.${jprt.tools.default.release}}
 
-jprt.my.linux.armvfpsflt.jdk8u20=linux_armvfpsflt_2.6
+jprt.my.linux.armvfpsflt.jdk8u40=linux_armvfpsflt_2.6
 jprt.my.linux.armvfpsflt=${jprt.my.linux.armvfpsflt.${jprt.tools.default.release}}
 
-jprt.my.linux.armvfphflt.jdk8u20=linux_armvfphflt_2.6
+jprt.my.linux.armvfphflt.jdk8u40=linux_armvfphflt_2.6
 jprt.my.linux.armvfphflt=${jprt.my.linux.armvfphflt.${jprt.tools.default.release}}
 
 # The ARM GP vfp-sflt build is not currently supported
-#jprt.my.linux.armvs.jdk8u20=linux_armvs_2.6
+#jprt.my.linux.armvs.jdk8u40=linux_armvs_2.6
 #jprt.my.linux.armvs=${jprt.my.linux.armvs.${jprt.tools.default.release}}
 
-jprt.my.linux.armvh.jdk8u20=linux_armvh_2.6
+jprt.my.linux.armvh.jdk8u40=linux_armvh_2.6
 jprt.my.linux.armvh=${jprt.my.linux.armvh.${jprt.tools.default.release}}
 
-jprt.my.linux.armsflt.jdk8u20=linux_armsflt_2.6
+jprt.my.linux.armsflt.jdk8u40=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7=linux_armsflt_2.6
 jprt.my.linux.armsflt.jdk7u8=${jprt.my.linux.armsflt.jdk7}
 jprt.my.linux.armsflt=${jprt.my.linux.armsflt.${jprt.tools.default.release}}
 
-jprt.my.macosx.x64.jdk8u20=macosx_x64_10.7
+jprt.my.macosx.x64.jdk8u40=macosx_x64_10.7
 jprt.my.macosx.x64.jdk7=macosx_x64_10.7
 jprt.my.macosx.x64.jdk7u8=${jprt.my.macosx.x64.jdk7}
 jprt.my.macosx.x64=${jprt.my.macosx.x64.${jprt.tools.default.release}}
 
-jprt.my.windows.i586.jdk8u20=windows_i586_6.1
+jprt.my.windows.i586.jdk8u40=windows_i586_6.1
 jprt.my.windows.i586.jdk7=windows_i586_6.1
 jprt.my.windows.i586.jdk7u8=${jprt.my.windows.i586.jdk7}
 jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}}
 
-jprt.my.windows.x64.jdk8u20=windows_x64_6.1
+jprt.my.windows.x64.jdk8u40=windows_x64_6.1
 jprt.my.windows.x64.jdk7=windows_x64_6.1
 jprt.my.windows.x64.jdk7u8=${jprt.my.windows.x64.jdk7}
 jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}}
@@ -137,7 +137,7 @@
 jprt.build.targets.all=${jprt.build.targets.standard}, \
     ${jprt.build.targets.embedded}, ${jprt.build.targets.open}
 
-jprt.build.targets.jdk8u20=${jprt.build.targets.all}
+jprt.build.targets.jdk8u40=${jprt.build.targets.all}
 jprt.build.targets.jdk7=${jprt.build.targets.all}
 jprt.build.targets.jdk7u8=${jprt.build.targets.all}
 jprt.build.targets=${jprt.build.targets.${jprt.tools.default.release}}
@@ -343,7 +343,7 @@
   ${jprt.my.windows.i586.test.targets}, \
   ${jprt.my.windows.x64.test.targets}
 
-jprt.test.targets.jdk8u20=${jprt.test.targets.standard}
+jprt.test.targets.jdk8u40=${jprt.test.targets.standard}
 jprt.test.targets.jdk7=${jprt.test.targets.standard}
 jprt.test.targets.jdk7u8=${jprt.test.targets.jdk7}
 jprt.test.targets=${jprt.test.targets.${jprt.tools.default.release}}
@@ -393,7 +393,7 @@
 jprt.make.rule.test.targets.embedded = \
   ${jprt.make.rule.test.targets.standard.client}
 
-jprt.make.rule.test.targets.jdk8u20=${jprt.make.rule.test.targets.standard}
+jprt.make.rule.test.targets.jdk8u40=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets.jdk7=${jprt.make.rule.test.targets.standard}
 jprt.make.rule.test.targets.jdk7u8=${jprt.make.rule.test.targets.jdk7}
 jprt.make.rule.test.targets=${jprt.make.rule.test.targets.${jprt.tools.default.release}}
diff --git a/hotspot/make/linux/makefiles/vm.make b/hotspot/make/linux/makefiles/vm.make
index 7df141f..eebf68f 100644
--- a/hotspot/make/linux/makefiles/vm.make
+++ b/hotspot/make/linux/makefiles/vm.make
@@ -233,10 +233,10 @@
 
 vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES))
 
-mapfile : $(MAPFILE) vm.def
+mapfile : $(MAPFILE) vm.def mapfile_ext
 	rm -f $@
 	awk '{ if ($$0 ~ "INSERT VTABLE SYMBOLS HERE")	\
-                 { system ("cat vm.def"); }		\
+                 { system ("cat mapfile_ext"); system ("cat vm.def"); } \
                else					\
                  { print $$0 }				\
              }' > $@ < $(MAPFILE)
@@ -248,6 +248,13 @@
 vm.def: $(Res_Files) $(Obj_Files)
 	sh $(GAMMADIR)/make/linux/makefiles/build_vm_def.sh *.o > $@
 
+mapfile_ext:
+	rm -f $@
+	touch $@
+	if [ -f $(HS_ALT_MAKE)/linux/makefiles/mapfile-ext ]; then \
+	  cat $(HS_ALT_MAKE)/linux/makefiles/mapfile-ext > $@; \
+	fi
+
 ifeq ($(JVM_VARIANT_ZEROSHARK), true)
   STATIC_CXX = false
 else
diff --git a/hotspot/make/solaris/Makefile b/hotspot/make/solaris/Makefile
index 7ae2be4..8d786f7 100644
--- a/hotspot/make/solaris/Makefile
+++ b/hotspot/make/solaris/Makefile
@@ -159,6 +159,7 @@
 BUILDTREE_VARS    = GAMMADIR=$(GAMMADIR) OS_FAMILY=$(OSNAME) ARCH=$(SRCARCH) BUILDARCH=$(BUILDARCH) LIBARCH=$(LIBARCH)
 BUILDTREE_VARS   += HOTSPOT_RELEASE_VERSION=$(HOTSPOT_RELEASE_VERSION) HOTSPOT_BUILD_VERSION=$(HOTSPOT_BUILD_VERSION) JRE_RELEASE_VERSION=$(JRE_RELEASE_VERSION)
 BUILDTREE_VARS   += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS) OBJCOPY=$(OBJCOPY) STRIP_POLICY=$(STRIP_POLICY) ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES) ZIPEXE=$(ZIPEXE)
+BUILDTREE_VARS   += HS_ALT_MAKE=$(HS_ALT_MAKE)
 
 BUILDTREE         = $(MAKE) -f $(BUILDTREE_MAKE) $(BUILDTREE_VARS)
 
diff --git a/hotspot/make/solaris/makefiles/buildtree.make b/hotspot/make/solaris/makefiles/buildtree.make
index ca602a8..4b68a7c 100644
--- a/hotspot/make/solaris/makefiles/buildtree.make
+++ b/hotspot/make/solaris/makefiles/buildtree.make
@@ -258,6 +258,8 @@
 	    echo && echo "ZIP_DEBUGINFO_FILES = $(ZIP_DEBUGINFO_FILES)"; \
 	[ -n "$(ZIPEXE)" ] && \
 	    echo && echo "ZIPEXE = $(ZIPEXE)"; \
+	[ -n "$(HS_ALT_MAKE)" ] && \
+	    echo && echo "HS_ALT_MAKE = $(HS_ALT_MAKE)"; \
 	[ -n "$(HOTSPOT_EXTRA_SYSDEFS)" ] && \
 	    echo && \
 	    echo "HOTSPOT_EXTRA_SYSDEFS\$$(HOTSPOT_EXTRA_SYSDEFS) = $(HOTSPOT_EXTRA_SYSDEFS)" && \
diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make
index b3939fb..5ebc7a3 100644
--- a/hotspot/make/solaris/makefiles/vm.make
+++ b/hotspot/make/solaris/makefiles/vm.make
@@ -247,11 +247,12 @@
 
 vm_version.o: $(filter-out vm_version.o,$(JVM_OBJ_FILES))
 
-mapfile : $(MAPFILE) $(MAPFILE_DTRACE_OPT) vm.def
+mapfile : $(MAPFILE) $(MAPFILE_DTRACE_OPT) vm.def mapfile_ext
 	rm -f $@
 	cat $(MAPFILE) $(MAPFILE_DTRACE_OPT) \
 	    | $(NAWK) '{                                         \
 	              if ($$0 ~ "INSERT VTABLE SYMBOLS HERE") {  \
+	                  system ("cat mapfile_ext");            \
 	                  system ("cat vm.def");                 \
 	              } else {                                   \
 	                  print $$0;                             \
@@ -265,6 +266,13 @@
 vm.def: $(Obj_Files)
 	sh $(GAMMADIR)/make/solaris/makefiles/build_vm_def.sh *.o > $@
 
+mapfile_ext:
+	rm -f $@
+	touch $@
+	if [ -f $(HS_ALT_MAKE)/solaris/makefiles/mapfile-ext ]; then \
+	  cat $(HS_ALT_MAKE)/solaris/makefiles/mapfile-ext > $@; \
+	fi
+
 ifeq ($(LINK_INTO),AOUT)
   LIBJVM.o                 =
   LIBJVM_MAPFILE           =
diff --git a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
index b24b3c4..ab10074 100644
--- a/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
+++ b/hotspot/src/cpu/ppc/vm/compiledIC_ppc.cpp
@@ -50,34 +50,6 @@
   return is_icholder_entry(call->destination());
 }
 
-//-----------------------------------------------------------------------------
-// High-level access to an inline cache. Guaranteed to be MT-safe.
-
-CompiledIC::CompiledIC(nmethod* nm, NativeCall* call)
-  : _ic_call(call)
-{
-  address ic_call = call->instruction_address();
-
-  assert(ic_call != NULL, "ic_call address must be set");
-  assert(nm != NULL, "must pass nmethod");
-  assert(nm->contains(ic_call), "must be in nmethod");
-
-  // Search for the ic_call at the given address.
-  RelocIterator iter(nm, ic_call, ic_call+1);
-  bool ret = iter.next();
-  assert(ret == true, "relocInfo must exist at this address");
-  assert(iter.addr() == ic_call, "must find ic_call");
-  if (iter.type() == relocInfo::virtual_call_type) {
-    virtual_call_Relocation* r = iter.virtual_call_reloc();
-    _is_optimized = false;
-    _value = nativeMovConstReg_at(r->cached_value());
-  } else {
-    assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
-    _is_optimized = true;
-    _value = NULL;
-  }
-}
-
 // ----------------------------------------------------------------------------
 
 // A PPC CompiledStaticCall looks like this:
diff --git a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
index db7ff9e..dd83b09 100644
--- a/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/assembler_sparc.hpp
@@ -123,6 +123,7 @@
     fpop2_op3    = 0x35,
     impdep1_op3  = 0x36,
     aes3_op3     = 0x36,
+    sha_op3      = 0x36,
     alignaddr_op3  = 0x36,
     faligndata_op3 = 0x36,
     flog3_op3    = 0x36,
@@ -223,7 +224,11 @@
     mwtos_opf          = 0x119,
 
     aes_kexpand0_opf   = 0x130,
-    aes_kexpand2_opf   = 0x131
+    aes_kexpand2_opf   = 0x131,
+
+    sha1_opf           = 0x141,
+    sha256_opf         = 0x142,
+    sha512_opf         = 0x143
   };
 
   enum op5s {
@@ -595,6 +600,11 @@
   // AES crypto instructions supported only on certain processors
   static void aes_only() { assert( VM_Version::has_aes(), "This instruction only works on SPARC with AES instructions support"); }
 
+  // SHA crypto instructions supported only on certain processors
+  static void sha1_only()   { assert( VM_Version::has_sha1(),   "This instruction only works on SPARC with SHA1"); }
+  static void sha256_only() { assert( VM_Version::has_sha256(), "This instruction only works on SPARC with SHA256"); }
+  static void sha512_only() { assert( VM_Version::has_sha512(), "This instruction only works on SPARC with SHA512"); }
+
   // instruction only in VIS1
   static void vis1_only() { assert( VM_Version::has_vis1(), "This instruction only works on SPARC with VIS1"); }
 
@@ -1179,7 +1189,6 @@
                                                u_field(3, 29, 25) | immed(true) | simm(simm13a, 13)); }
   inline void wrfprs( Register d) { v9_only(); emit_int32( op(arith_op) | rs1(d) | op3(wrreg_op3) | u_field(6, 29, 25)); }
 
-
   //  VIS1 instructions
 
   void alignaddr( Register s1, Register s2, Register d ) { vis1_only(); emit_int32( op(arith_op) | rd(d) | op3(alignaddr_op3) | rs1(s1) | opf(alignaddr_opf) | rs2(s2)); }
@@ -1203,6 +1212,12 @@
   void movwtos( Register s, FloatRegister d ) { vis3_only();  emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::S) | op3(mftoi_op3) | opf(mwtos_opf) | rs2(s)); }
   void movxtod( Register s, FloatRegister d ) { vis3_only();  emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(mftoi_op3) | opf(mxtod_opf) | rs2(s)); }
 
+  // Crypto SHA instructions
+
+  void sha1()   { sha1_only();    emit_int32( op(arith_op) | op3(sha_op3) | opf(sha1_opf)); }
+  void sha256() { sha256_only();  emit_int32( op(arith_op) | op3(sha_op3) | opf(sha256_opf)); }
+  void sha512() { sha512_only();  emit_int32( op(arith_op) | op3(sha_op3) | opf(sha512_opf)); }
+
   // Creation
   Assembler(CodeBuffer* code) : AbstractAssembler(code) {
 #ifdef CHECK_DELAY
diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
index 945b7b0..73b61af 100644
--- a/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/c1_LIRGenerator_sparc.cpp
@@ -872,21 +872,19 @@
 
 
 void LIRGenerator::do_NewInstance(NewInstance* x) {
+  print_if_not_loaded(x);
+
   // This instruction can be deoptimized in the slow path : use
   // O0 as result register.
   const LIR_Opr reg = result_register_for(x->type());
-#ifndef PRODUCT
-  if (PrintNotLoaded && !x->klass()->is_loaded()) {
-    tty->print_cr("   ###class not loaded at new bci %d", x->printable_bci());
-  }
-#endif
+
   CodeEmitInfo* info = state_for(x, x->state());
   LIR_Opr tmp1 = FrameMap::G1_oop_opr;
   LIR_Opr tmp2 = FrameMap::G3_oop_opr;
   LIR_Opr tmp3 = FrameMap::G4_oop_opr;
   LIR_Opr tmp4 = FrameMap::O1_oop_opr;
   LIR_Opr klass_reg = FrameMap::G5_metadata_opr;
-  new_instance(reg, x->klass(), tmp1, tmp2, tmp3, tmp4, klass_reg, info);
+  new_instance(reg, x->klass(), x->is_unresolved(), tmp1, tmp2, tmp3, tmp4, klass_reg, info);
   LIR_Opr result = rlock_result(x);
   __ move(reg, result);
 }
diff --git a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
index 7913311..dee64df 100644
--- a/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/compiledIC_sparc.cpp
@@ -50,34 +50,6 @@
   return is_icholder_entry(call->destination());
 }
 
-//-----------------------------------------------------------------------------
-// High-level access to an inline cache. Guaranteed to be MT-safe.
-
-CompiledIC::CompiledIC(nmethod* nm, NativeCall* call)
-  : _ic_call(call)
-{
-  address ic_call = call->instruction_address();
-
-  assert(ic_call != NULL, "ic_call address must be set");
-  assert(nm != NULL, "must pass nmethod");
-  assert(nm->contains(ic_call), "must be in nmethod");
-
-  // Search for the ic_call at the given address.
-  RelocIterator iter(nm, ic_call, ic_call+1);
-  bool ret = iter.next();
-  assert(ret == true, "relocInfo must exist at this address");
-  assert(iter.addr() == ic_call, "must find ic_call");
-  if (iter.type() == relocInfo::virtual_call_type) {
-    virtual_call_Relocation* r = iter.virtual_call_reloc();
-    _is_optimized = false;
-    _value = nativeMovConstReg_at(r->cached_value());
-  } else {
-    assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
-    _is_optimized = true;
-    _value = NULL;
-  }
-}
-
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad
index 23026ea..701c161 100644
--- a/hotspot/src/cpu/sparc/vm/sparc.ad
+++ b/hotspot/src/cpu/sparc/vm/sparc.ad
@@ -6184,7 +6184,11 @@
   ins_cost(DEFAULT_COST * 3/2);
   format %{ "SET    $con,$dst\t! non-oop ptr" %}
   ins_encode %{
-    __ set($con$$constant, $dst$$Register);
+    if (_opnds[1]->constant_reloc() == relocInfo::metadata_type) {
+      __ set_metadata_constant((Metadata*)$con$$constant, $dst$$Register);
+    } else {
+      __ set($con$$constant, $dst$$Register);
+    }
   %}
   ins_pipe(loadConP);
 %}
diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp
index 231d1f7..e4cc113 100644
--- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp
@@ -4575,6 +4575,219 @@
     return start;
   }
 
+  address generate_sha1_implCompress(bool multi_block, const char *name) {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", name);
+    address start = __ pc();
+
+    Label L_sha1_loop, L_sha1_unaligned_input, L_sha1_unaligned_input_loop;
+    int i;
+
+    Register buf   = O0; // byte[] source+offset
+    Register state = O1; // int[]  SHA.state
+    Register ofs   = O2; // int    offset
+    Register limit = O3; // int    limit
+
+    // load state into F0-F4
+    for (i = 0; i < 5; i++) {
+      __ ldf(FloatRegisterImpl::S, state, i*4, as_FloatRegister(i));
+    }
+
+    __ andcc(buf, 7, G0);
+    __ br(Assembler::notZero, false, Assembler::pn, L_sha1_unaligned_input);
+    __ delayed()->nop();
+
+    __ BIND(L_sha1_loop);
+    // load buf into F8-F22
+    for (i = 0; i < 8; i++) {
+      __ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
+    }
+    __ sha1();
+    if (multi_block) {
+      __ add(ofs, 64, ofs);
+      __ add(buf, 64, buf);
+      __ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha1_loop);
+      __ mov(ofs, O0); // to be returned
+    }
+
+    // store F0-F4 into state and return
+    for (i = 0; i < 4; i++) {
+      __ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
+    }
+    __ retl();
+    __ delayed()->stf(FloatRegisterImpl::S, F4, state, 0x10);
+
+    __ BIND(L_sha1_unaligned_input);
+    __ alignaddr(buf, G0, buf);
+
+    __ BIND(L_sha1_unaligned_input_loop);
+    // load buf into F8-F22
+    for (i = 0; i < 9; i++) {
+      __ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
+    }
+    for (i = 0; i < 8; i++) {
+      __ faligndata(as_FloatRegister(i*2 + 8), as_FloatRegister(i*2 + 10), as_FloatRegister(i*2 + 8));
+    }
+    __ sha1();
+    if (multi_block) {
+      __ add(ofs, 64, ofs);
+      __ add(buf, 64, buf);
+      __ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha1_unaligned_input_loop);
+      __ mov(ofs, O0); // to be returned
+    }
+
+    // store F0-F4 into state and return
+    for (i = 0; i < 4; i++) {
+      __ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
+    }
+    __ retl();
+    __ delayed()->stf(FloatRegisterImpl::S, F4, state, 0x10);
+
+    return start;
+  }
+
+  address generate_sha256_implCompress(bool multi_block, const char *name) {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", name);
+    address start = __ pc();
+
+    Label L_sha256_loop, L_sha256_unaligned_input, L_sha256_unaligned_input_loop;
+    int i;
+
+    Register buf   = O0; // byte[] source+offset
+    Register state = O1; // int[]  SHA2.state
+    Register ofs   = O2; // int    offset
+    Register limit = O3; // int    limit
+
+    // load state into F0-F7
+    for (i = 0; i < 8; i++) {
+      __ ldf(FloatRegisterImpl::S, state, i*4, as_FloatRegister(i));
+    }
+
+    __ andcc(buf, 7, G0);
+    __ br(Assembler::notZero, false, Assembler::pn, L_sha256_unaligned_input);
+    __ delayed()->nop();
+
+    __ BIND(L_sha256_loop);
+    // load buf into F8-F22
+    for (i = 0; i < 8; i++) {
+      __ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
+    }
+    __ sha256();
+    if (multi_block) {
+      __ add(ofs, 64, ofs);
+      __ add(buf, 64, buf);
+      __ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha256_loop);
+      __ mov(ofs, O0); // to be returned
+    }
+
+    // store F0-F7 into state and return
+    for (i = 0; i < 7; i++) {
+      __ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
+    }
+    __ retl();
+    __ delayed()->stf(FloatRegisterImpl::S, F7, state, 0x1c);
+
+    __ BIND(L_sha256_unaligned_input);
+    __ alignaddr(buf, G0, buf);
+
+    __ BIND(L_sha256_unaligned_input_loop);
+    // load buf into F8-F22
+    for (i = 0; i < 9; i++) {
+      __ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 8));
+    }
+    for (i = 0; i < 8; i++) {
+      __ faligndata(as_FloatRegister(i*2 + 8), as_FloatRegister(i*2 + 10), as_FloatRegister(i*2 + 8));
+    }
+    __ sha256();
+    if (multi_block) {
+      __ add(ofs, 64, ofs);
+      __ add(buf, 64, buf);
+      __ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha256_unaligned_input_loop);
+      __ mov(ofs, O0); // to be returned
+    }
+
+    // store F0-F7 into state and return
+    for (i = 0; i < 7; i++) {
+      __ stf(FloatRegisterImpl::S, as_FloatRegister(i), state, i*4);
+    }
+    __ retl();
+    __ delayed()->stf(FloatRegisterImpl::S, F7, state, 0x1c);
+
+    return start;
+  }
+
+  address generate_sha512_implCompress(bool multi_block, const char *name) {
+    __ align(CodeEntryAlignment);
+    StubCodeMark mark(this, "StubRoutines", name);
+    address start = __ pc();
+
+    Label L_sha512_loop, L_sha512_unaligned_input, L_sha512_unaligned_input_loop;
+    int i;
+
+    Register buf   = O0; // byte[] source+offset
+    Register state = O1; // long[] SHA5.state
+    Register ofs   = O2; // int    offset
+    Register limit = O3; // int    limit
+
+    // load state into F0-F14
+    for (i = 0; i < 8; i++) {
+      __ ldf(FloatRegisterImpl::D, state, i*8, as_FloatRegister(i*2));
+    }
+
+    __ andcc(buf, 7, G0);
+    __ br(Assembler::notZero, false, Assembler::pn, L_sha512_unaligned_input);
+    __ delayed()->nop();
+
+    __ BIND(L_sha512_loop);
+    // load buf into F16-F46
+    for (i = 0; i < 16; i++) {
+      __ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 16));
+    }
+    __ sha512();
+    if (multi_block) {
+      __ add(ofs, 128, ofs);
+      __ add(buf, 128, buf);
+      __ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha512_loop);
+      __ mov(ofs, O0); // to be returned
+    }
+
+    // store F0-F14 into state and return
+    for (i = 0; i < 7; i++) {
+      __ stf(FloatRegisterImpl::D, as_FloatRegister(i*2), state, i*8);
+    }
+    __ retl();
+    __ delayed()->stf(FloatRegisterImpl::D, F14, state, 0x38);
+
+    __ BIND(L_sha512_unaligned_input);
+    __ alignaddr(buf, G0, buf);
+
+    __ BIND(L_sha512_unaligned_input_loop);
+    // load buf into F16-F46
+    for (i = 0; i < 17; i++) {
+      __ ldf(FloatRegisterImpl::D, buf, i*8, as_FloatRegister(i*2 + 16));
+    }
+    for (i = 0; i < 16; i++) {
+      __ faligndata(as_FloatRegister(i*2 + 16), as_FloatRegister(i*2 + 18), as_FloatRegister(i*2 + 16));
+    }
+    __ sha512();
+    if (multi_block) {
+      __ add(ofs, 128, ofs);
+      __ add(buf, 128, buf);
+      __ cmp_and_brx_short(ofs, limit, Assembler::lessEqual, Assembler::pt, L_sha512_unaligned_input_loop);
+      __ mov(ofs, O0); // to be returned
+    }
+
+    // store F0-F14 into state and return
+    for (i = 0; i < 7; i++) {
+      __ stf(FloatRegisterImpl::D, as_FloatRegister(i*2), state, i*8);
+    }
+    __ retl();
+    __ delayed()->stf(FloatRegisterImpl::D, F14, state, 0x38);
+
+    return start;
+  }
+
   void generate_initial() {
     // Generates all stubs and initializes the entry points
 
@@ -4647,6 +4860,20 @@
       StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt();
       StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt_Parallel();
     }
+
+    // generate SHA1/SHA256/SHA512 intrinsics code
+    if (UseSHA1Intrinsics) {
+      StubRoutines::_sha1_implCompress     = generate_sha1_implCompress(false,   "sha1_implCompress");
+      StubRoutines::_sha1_implCompressMB   = generate_sha1_implCompress(true,    "sha1_implCompressMB");
+    }
+    if (UseSHA256Intrinsics) {
+      StubRoutines::_sha256_implCompress   = generate_sha256_implCompress(false, "sha256_implCompress");
+      StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true,  "sha256_implCompressMB");
+    }
+    if (UseSHA512Intrinsics) {
+      StubRoutines::_sha512_implCompress   = generate_sha512_implCompress(false, "sha512_implCompress");
+      StubRoutines::_sha512_implCompressMB = generate_sha512_implCompress(true,  "sha512_implCompressMB");
+    }
   }
 
 
diff --git a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp
index 880a026..f3b30e8 100644
--- a/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/stubRoutines_sparc.hpp
@@ -41,7 +41,7 @@
 enum /* platform_dependent_constants */ {
   // %%%%%%%% May be able to shrink this a lot
   code_size1 = 20000,           // simply increase if too small (assembler will crash if too small)
-  code_size2 = 22000            // simply increase if too small (assembler will crash if too small)
+  code_size2 = 23000            // simply increase if too small (assembler will crash if too small)
 };
 
 class Sparc {
diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
index 1943705..841068b 100644
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp
@@ -234,7 +234,7 @@
   assert((OptoLoopAlignment % relocInfo::addr_unit()) == 0, "alignment is not a multiple of NOP size");
 
   char buf[512];
-  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+  jio_snprintf(buf, sizeof(buf), "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
                (has_v9() ? ", v9" : (has_v8() ? ", v8" : "")),
                (has_hardware_popc() ? ", popc" : ""),
                (has_vis1() ? ", vis1" : ""),
@@ -243,6 +243,9 @@
                (has_blk_init() ? ", blk_init" : ""),
                (has_cbcond() ? ", cbcond" : ""),
                (has_aes() ? ", aes" : ""),
+               (has_sha1() ? ", sha1" : ""),
+               (has_sha256() ? ", sha256" : ""),
+               (has_sha512() ? ", sha512" : ""),
                (is_ultra3() ? ", ultra3" : ""),
                (is_sun4v() ? ", sun4v" : ""),
                (is_niagara_plus() ? ", niagara_plus" : (is_niagara() ? ", niagara" : "")),
@@ -301,6 +304,58 @@
     }
   }
 
+  // SHA1, SHA256, and SHA512 instructions were added to SPARC T-series at different times
+  if (has_sha1() || has_sha256() || has_sha512()) {
+    if (UseVIS > 0) { // SHA intrinsics use VIS1 instructions
+      if (FLAG_IS_DEFAULT(UseSHA)) {
+        FLAG_SET_DEFAULT(UseSHA, true);
+      }
+    } else {
+      if (UseSHA) {
+        warning("SPARC SHA intrinsics require VIS1 instruction support. Intrinsics will be disabled.");
+        FLAG_SET_DEFAULT(UseSHA, false);
+      }
+    }
+  } else if (UseSHA) {
+    warning("SHA instructions are not available on this CPU");
+    FLAG_SET_DEFAULT(UseSHA, false);
+  }
+
+  if (!UseSHA) {
+    FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+    FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
+    FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
+  } else {
+    if (has_sha1()) {
+      if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) {
+        FLAG_SET_DEFAULT(UseSHA1Intrinsics, true);
+      }
+    } else if (UseSHA1Intrinsics) {
+      warning("SHA1 instruction is not available on this CPU.");
+      FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+    }
+    if (has_sha256()) {
+      if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) {
+        FLAG_SET_DEFAULT(UseSHA256Intrinsics, true);
+      }
+    } else if (UseSHA256Intrinsics) {
+      warning("SHA256 instruction (for SHA-224 and SHA-256) is not available on this CPU.");
+      FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
+    }
+
+    if (has_sha512()) {
+      if (FLAG_IS_DEFAULT(UseSHA512Intrinsics)) {
+        FLAG_SET_DEFAULT(UseSHA512Intrinsics, true);
+      }
+    } else if (UseSHA512Intrinsics) {
+      warning("SHA512 instruction (for SHA-384 and SHA-512) is not available on this CPU.");
+      FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
+    }
+    if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) {
+      FLAG_SET_DEFAULT(UseSHA, false);
+    }
+  }
+
   if (FLAG_IS_DEFAULT(ContendedPaddingWidth) &&
     (cache_line_size > ContendedPaddingWidth))
     ContendedPaddingWidth = cache_line_size;
diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
index eafb485..b20f8a6 100644
--- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
+++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -50,7 +50,10 @@
     T_family             = 16,
     T1_model             = 17,
     sparc5_instructions  = 18,
-    aes_instructions     = 19
+    aes_instructions     = 19,
+    sha1_instruction     = 20,
+    sha256_instruction   = 21,
+    sha512_instruction   = 22
   };
 
   enum Feature_Flag_Set {
@@ -77,6 +80,9 @@
     T1_model_m              = 1 << T1_model,
     sparc5_instructions_m   = 1 << sparc5_instructions,
     aes_instructions_m      = 1 << aes_instructions,
+    sha1_instruction_m      = 1 << sha1_instruction,
+    sha256_instruction_m    = 1 << sha256_instruction,
+    sha512_instruction_m    = 1 << sha512_instruction,
 
     generic_v8_m        = v8_instructions_m | hardware_mul32_m | hardware_div32_m | hardware_fsmuld_m,
     generic_v9_m        = generic_v8_m | v9_instructions_m,
@@ -129,6 +135,9 @@
   static bool has_cbcond()              { return (_features & cbcond_instructions_m) != 0; }
   static bool has_sparc5_instr()        { return (_features & sparc5_instructions_m) != 0; }
   static bool has_aes()                 { return (_features & aes_instructions_m) != 0; }
+  static bool has_sha1()                { return (_features & sha1_instruction_m) != 0; }
+  static bool has_sha256()              { return (_features & sha256_instruction_m) != 0; }
+  static bool has_sha512()              { return (_features & sha512_instruction_m) != 0; }
 
   static bool supports_compare_and_exchange()
                                         { return has_v9(); }
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
index 64b8ce7..3421927 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp
@@ -3854,6 +3854,15 @@
 }
 
 // Carry-Less Multiplication Quadword
+void Assembler::pclmulqdq(XMMRegister dst, XMMRegister src, int mask) {
+  assert(VM_Version::supports_clmul(), "");
+  int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A);
+  emit_int8(0x44);
+  emit_int8((unsigned char)(0xC0 | encode));
+  emit_int8((unsigned char)mask);
+}
+
+// Carry-Less Multiplication Quadword
 void Assembler::vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask) {
   assert(VM_Version::supports_avx() && VM_Version::supports_clmul(), "");
   bool vector256 = false;
diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
index 12bc14e..8edf31c 100644
--- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp
@@ -1837,6 +1837,7 @@
   void vpbroadcastd(XMMRegister dst, XMMRegister src);
 
   // Carry-Less Multiplication Quadword
+  void pclmulqdq(XMMRegister dst, XMMRegister src, int mask);
   void vpclmulqdq(XMMRegister dst, XMMRegister nds, XMMRegister src, int mask);
 
   // AVX instruction which is used to clear upper 128 bits of YMM registers and
diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
index b4e8223..1ee690e 100644
--- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp
@@ -1085,14 +1085,11 @@
 
 
 void LIRGenerator::do_NewInstance(NewInstance* x) {
-#ifndef PRODUCT
-  if (PrintNotLoaded && !x->klass()->is_loaded()) {
-    tty->print_cr("   ###class not loaded at new bci %d", x->printable_bci());
-  }
-#endif
+  print_if_not_loaded(x);
+
   CodeEmitInfo* info = state_for(x, x->state());
   LIR_Opr reg = result_register_for(x->type());
-  new_instance(reg, x->klass(),
+  new_instance(reg, x->klass(), x->is_unresolved(),
                        FrameMap::rcx_oop_opr,
                        FrameMap::rdi_oop_opr,
                        FrameMap::rsi_oop_opr,
diff --git a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
index 26d56b8..9537ef9 100644
--- a/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/compiledIC_x86.cpp
@@ -47,34 +47,6 @@
   return is_icholder_entry(call->destination());
 }
 
-//-----------------------------------------------------------------------------
-// High-level access to an inline cache. Guaranteed to be MT-safe.
-
-CompiledIC::CompiledIC(nmethod* nm, NativeCall* call)
-  : _ic_call(call)
-{
-  address ic_call = call->instruction_address();
-
-  assert(ic_call != NULL, "ic_call address must be set");
-  assert(nm != NULL, "must pass nmethod");
-  assert(nm->contains(ic_call), "must be in nmethod");
-
-  // Search for the ic_call at the given address.
-  RelocIterator iter(nm, ic_call, ic_call+1);
-  bool ret = iter.next();
-  assert(ret == true, "relocInfo must exist at this address");
-  assert(iter.addr() == ic_call, "must find ic_call");
-  if (iter.type() == relocInfo::virtual_call_type) {
-    virtual_call_Relocation* r = iter.virtual_call_reloc();
-    _is_optimized = false;
-    _value = nativeMovConstReg_at(r->cached_value());
-  } else {
-    assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
-    _is_optimized = true;
-    _value = NULL;
-  }
-}
-
 // ----------------------------------------------------------------------------
 
 #define __ _masm.
diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp
index 83441ca..5b34293 100644
--- a/hotspot/src/cpu/x86/vm/globals_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp
@@ -130,16 +130,16 @@
           "Use fast-string operation for zeroing: rep stosb")               \
                                                                             \
   /* Use Restricted Transactional Memory for lock eliding */                \
-  experimental(bool, UseRTMLocking, false,                                  \
+  product(bool, UseRTMLocking, false,                                       \
           "Enable RTM lock eliding for inflated locks in compiled code")    \
                                                                             \
   experimental(bool, UseRTMForStackLocks, false,                            \
           "Enable RTM lock eliding for stack locks in compiled code")       \
                                                                             \
-  experimental(bool, UseRTMDeopt, false,                                    \
+  product(bool, UseRTMDeopt, false,                                         \
           "Perform deopt and recompilation based on RTM abort ratio")       \
                                                                             \
-  experimental(uintx, RTMRetryCount, 5,                                     \
+  product(uintx, RTMRetryCount, 5,                                          \
           "Number of RTM retries on lock abort or busy")                    \
                                                                             \
   experimental(intx, RTMSpinLoopCount, 100,                                 \
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
index 5b32412..7216c19 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp
@@ -7316,17 +7316,34 @@
  * Fold 128-bit data chunk
  */
 void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, Register buf, int offset) {
-  vpclmulhdq(xtmp, xK, xcrc); // [123:64]
-  vpclmulldq(xcrc, xK, xcrc); // [63:0]
-  vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */);
-  pxor(xcrc, xtmp);
+  if (UseAVX > 0) {
+    vpclmulhdq(xtmp, xK, xcrc); // [123:64]
+    vpclmulldq(xcrc, xK, xcrc); // [63:0]
+    vpxor(xcrc, xcrc, Address(buf, offset), false /* vector256 */);
+    pxor(xcrc, xtmp);
+  } else {
+    movdqa(xtmp, xcrc);
+    pclmulhdq(xtmp, xK);   // [123:64]
+    pclmulldq(xcrc, xK);   // [63:0]
+    pxor(xcrc, xtmp);
+    movdqu(xtmp, Address(buf, offset));
+    pxor(xcrc, xtmp);
+  }
 }
 
 void MacroAssembler::fold_128bit_crc32(XMMRegister xcrc, XMMRegister xK, XMMRegister xtmp, XMMRegister xbuf) {
-  vpclmulhdq(xtmp, xK, xcrc);
-  vpclmulldq(xcrc, xK, xcrc);
-  pxor(xcrc, xbuf);
-  pxor(xcrc, xtmp);
+  if (UseAVX > 0) {
+    vpclmulhdq(xtmp, xK, xcrc);
+    vpclmulldq(xcrc, xK, xcrc);
+    pxor(xcrc, xbuf);
+    pxor(xcrc, xtmp);
+  } else {
+    movdqa(xtmp, xcrc);
+    pclmulhdq(xtmp, xK);
+    pclmulldq(xcrc, xK);
+    pxor(xcrc, xbuf);
+    pxor(xcrc, xtmp);
+  }
 }
 
 /**
@@ -7444,9 +7461,17 @@
   // Fold 128 bits in xmm1 down into 32 bits in crc register.
   BIND(L_fold_128b);
   movdqu(xmm0, ExternalAddress(StubRoutines::x86::crc_by128_masks_addr()));
-  vpclmulqdq(xmm2, xmm0, xmm1, 0x1);
-  vpand(xmm3, xmm0, xmm2, false /* vector256 */);
-  vpclmulqdq(xmm0, xmm0, xmm3, 0x1);
+  if (UseAVX > 0) {
+    vpclmulqdq(xmm2, xmm0, xmm1, 0x1);
+    vpand(xmm3, xmm0, xmm2, false /* vector256 */);
+    vpclmulqdq(xmm0, xmm0, xmm3, 0x1);
+  } else {
+    movdqa(xmm2, xmm0);
+    pclmulqdq(xmm2, xmm1, 0x1);
+    movdqa(xmm3, xmm0);
+    pand(xmm3, xmm2);
+    pclmulqdq(xmm0, xmm3, 0x1);
+  }
   psrldq(xmm1, 8);
   psrldq(xmm2, 4);
   pxor(xmm0, xmm1);
diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
index 3d88026..3b3073e 100644
--- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
+++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp
@@ -966,6 +966,16 @@
   void mulss(XMMRegister dst, Address src)        { Assembler::mulss(dst, src); }
   void mulss(XMMRegister dst, AddressLiteral src);
 
+  // Carry-Less Multiplication Quadword
+  void pclmulldq(XMMRegister dst, XMMRegister src) {
+    // 0x00 - multiply lower 64 bits [0:63]
+    Assembler::pclmulqdq(dst, src, 0x00);
+  }
+  void pclmulhdq(XMMRegister dst, XMMRegister src) {
+    // 0x11 - multiply upper 64 bits [64:127]
+    Assembler::pclmulqdq(dst, src, 0x11);
+  }
+
   void sqrtsd(XMMRegister dst, XMMRegister src)    { Assembler::sqrtsd(dst, src); }
   void sqrtsd(XMMRegister dst, Address src)        { Assembler::sqrtsd(dst, src); }
   void sqrtsd(XMMRegister dst, AddressLiteral src);
diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
index e09dba3..8cb93b2 100644
--- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
+++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp
@@ -568,7 +568,7 @@
     FLAG_SET_DEFAULT(UseCLMUL, false);
   }
 
-  if (UseCLMUL && (UseAVX > 0) && (UseSSE > 2)) {
+  if (UseCLMUL && (UseSSE > 2)) {
     if (FLAG_IS_DEFAULT(UseCRC32Intrinsics)) {
       UseCRC32Intrinsics = true;
     }
@@ -590,6 +590,17 @@
     FLAG_SET_DEFAULT(UseAESIntrinsics, false);
   }
 
+  if (UseSHA) {
+    warning("SHA instructions are not available on this CPU");
+    FLAG_SET_DEFAULT(UseSHA, false);
+  }
+  if (UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics) {
+    warning("SHA intrinsics are not available on this CPU");
+    FLAG_SET_DEFAULT(UseSHA1Intrinsics, false);
+    FLAG_SET_DEFAULT(UseSHA256Intrinsics, false);
+    FLAG_SET_DEFAULT(UseSHA512Intrinsics, false);
+  }
+
   // Adjust RTM (Restricted Transactional Memory) flags
   if (!supports_rtm() && UseRTMLocking) {
     // Can't continue because UseRTMLocking affects UseBiasedLocking flag
@@ -803,6 +814,21 @@
         }
       }
     }
+    if ((cpu_family() == 0x06) &&
+        ((extended_cpu_model() == 0x36) || // Centerton
+         (extended_cpu_model() == 0x37) || // Silvermont
+         (extended_cpu_model() == 0x4D))) {
+#ifdef COMPILER2
+      if (FLAG_IS_DEFAULT(OptoScheduling)) {
+        OptoScheduling = true;
+      }
+#endif
+      if (supports_sse4_2()) { // Silvermont
+        if (FLAG_IS_DEFAULT(UseUnalignedLoadStores)) {
+          UseUnalignedLoadStores = true; // use movdqu on newest Intel cpus
+        }
+      }
+    }
   }
 
   // Use count leading zeros count instruction if available.
@@ -890,23 +916,25 @@
   AllocatePrefetchDistance = allocate_prefetch_distance();
   AllocatePrefetchStyle    = allocate_prefetch_style();
 
-  if( is_intel() && cpu_family() == 6 && supports_sse3() ) {
-    if( AllocatePrefetchStyle == 2 ) { // watermark prefetching on Core
+  if (is_intel() && cpu_family() == 6 && supports_sse3()) {
+    if (AllocatePrefetchStyle == 2) { // watermark prefetching on Core
 #ifdef _LP64
       AllocatePrefetchDistance = 384;
 #else
       AllocatePrefetchDistance = 320;
 #endif
     }
-    if( supports_sse4_2() && supports_ht() ) { // Nehalem based cpus
+    if (supports_sse4_2() && supports_ht()) { // Nehalem based cpus
       AllocatePrefetchDistance = 192;
       AllocatePrefetchLines = 4;
+    }
 #ifdef COMPILER2
-      if (AggressiveOpts && FLAG_IS_DEFAULT(UseFPUForSpilling)) {
+    if (supports_sse4_2()) {
+      if (FLAG_IS_DEFAULT(UseFPUForSpilling)) {
         FLAG_SET_DEFAULT(UseFPUForSpilling, true);
       }
-#endif
     }
+#endif
   }
   assert(AllocatePrefetchDistance % AllocatePrefetchStepSize == 0, "invalid value");
 
diff --git a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp
index 6fa39ea..143dc31 100644
--- a/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/compiledIC_zero.cpp
@@ -58,34 +58,6 @@
   return is_icholder_entry(call->destination());
 }
 
-//-----------------------------------------------------------------------------
-// High-level access to an inline cache. Guaranteed to be MT-safe.
-
-CompiledIC::CompiledIC(nmethod* nm, NativeCall* call)
-  : _ic_call(call)
-{
-  address ic_call = call->instruction_address();
-
-  assert(ic_call != NULL, "ic_call address must be set");
-  assert(nm != NULL, "must pass nmethod");
-  assert(nm->contains(ic_call), "must be in nmethod");
-
-  // Search for the ic_call at the given address.
-  RelocIterator iter(nm, ic_call, ic_call+1);
-  bool ret = iter.next();
-  assert(ret == true, "relocInfo must exist at this address");
-  assert(iter.addr() == ic_call, "must find ic_call");
-  if (iter.type() == relocInfo::virtual_call_type) {
-    virtual_call_Relocation* r = iter.virtual_call_reloc();
-    _is_optimized = false;
-    _value = nativeMovConstReg_at(r->cached_value());
-  } else {
-    assert(iter.type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
-    _is_optimized = true;
-    _value = NULL;
-  }
-}
-
 // ----------------------------------------------------------------------------
 
 void CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
index 8ac274b..9272724 100644
--- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
+++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp
@@ -40,6 +40,7 @@
 #include "runtime/deoptimization.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/synchronizer.hpp"
diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp
index 3f6675b..314b806 100644
--- a/hotspot/src/os/aix/vm/os_aix.cpp
+++ b/hotspot/src/os/aix/vm/os_aix.cpp
@@ -55,6 +55,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
diff --git a/hotspot/src/os/aix/vm/os_aix.inline.hpp b/hotspot/src/os/aix/vm/os_aix.inline.hpp
index ff9c7a7..a97c94c 100644
--- a/hotspot/src/os/aix/vm/os_aix.inline.hpp
+++ b/hotspot/src/os/aix/vm/os_aix.inline.hpp
@@ -26,12 +26,9 @@
 #ifndef OS_AIX_VM_OS_AIX_INLINE_HPP
 #define OS_AIX_VM_OS_AIX_INLINE_HPP
 
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
-#ifdef TARGET_OS_ARCH_aix_ppc
-# include "atomic_aix_ppc.inline.hpp"
-# include "orderAccess_aix_ppc.inline.hpp"
-#endif
 
 // System includes
 
diff --git a/hotspot/src/os/aix/vm/thread_aix.inline.hpp b/hotspot/src/os/aix/vm/thread_aix.inline.hpp
index 2712024..0462351 100644
--- a/hotspot/src/os/aix/vm/thread_aix.inline.hpp
+++ b/hotspot/src/os/aix/vm/thread_aix.inline.hpp
@@ -26,15 +26,9 @@
 #ifndef OS_AIX_VM_THREAD_AIX_INLINE_HPP
 #define OS_AIX_VM_THREAD_AIX_INLINE_HPP
 
-#include "runtime/atomic.hpp"
-#include "runtime/prefetch.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadLocalStorage.hpp"
 
-#include "atomic_aix_ppc.inline.hpp"
-#include "orderAccess_aix_ppc.inline.hpp"
-#include "prefetch_aix_ppc.inline.hpp"
-
 // Contains inlined functions for class Thread and ThreadLocalStorage
 
 inline void ThreadLocalStorage::pd_invalidate_all() {} // nothing to do
diff --git a/hotspot/src/os/bsd/dtrace/libjvm_db.c b/hotspot/src/os/bsd/dtrace/libjvm_db.c
index c51441e..169a0e9 100644
--- a/hotspot/src/os/bsd/dtrace/libjvm_db.c
+++ b/hotspot/src/os/bsd/dtrace/libjvm_db.c
@@ -260,6 +260,9 @@
   uint64_t base;
   int err;
 
+  /* Clear *vmp now in case we jump to fail: */
+  memset(vmp, 0, sizeof(VMStructEntry));
+
   err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
   CHECK_FAIL(err);
   err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp
index 46826ac..e1c53c5 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.cpp
@@ -48,6 +48,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -2433,23 +2434,25 @@
   }
 
   // The memory is committed
-  MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);
 
   return addr;
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
-  // detaching the SHM segment will also delete it, see reserve_memory_special()
-  int rslt = shmdt(base);
-  if (rslt == 0) {
-    tkr.record((address)base, bytes);
-    return true;
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+    // detaching the SHM segment will also delete it, see reserve_memory_special()
+    int rslt = shmdt(base);
+    if (rslt == 0) {
+      tkr.record((address)base, bytes);
+      return true;
+    } else {
+      return false;
+    }
   } else {
-    tkr.discard();
-    return false;
+    return shmdt(base) == 0;
   }
-
 }
 
 size_t os::large_page_size() {
diff --git a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
index cf84533..10b3994 100644
--- a/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
+++ b/hotspot/src/os/bsd/vm/os_bsd.inline.hpp
@@ -26,15 +26,9 @@
 #define OS_BSD_VM_OS_BSD_INLINE_HPP
 
 #include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 
-#ifdef TARGET_OS_ARCH_bsd_x86
-# include "orderAccess_bsd_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_zero
-# include "orderAccess_bsd_zero.inline.hpp"
-#endif
-
 // System includes
 
 #include <unistd.h>
diff --git a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
index e812a76..2737fe3 100644
--- a/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
+++ b/hotspot/src/os/bsd/vm/perfMemory_bsd.cpp
@@ -753,7 +753,7 @@
   (void)::memset((void*) mapAddress, 0, size);
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
 
   return mapAddress;
 }
@@ -918,7 +918,7 @@
   }
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
 
   *addr = mapAddress;
   *sizep = size;
diff --git a/hotspot/src/os/bsd/vm/thread_bsd.inline.hpp b/hotspot/src/os/bsd/vm/thread_bsd.inline.hpp
index ba8baaf..86f125d 100644
--- a/hotspot/src/os/bsd/vm/thread_bsd.inline.hpp
+++ b/hotspot/src/os/bsd/vm/thread_bsd.inline.hpp
@@ -29,20 +29,8 @@
 #error "This file should only be included from thread.inline.hpp"
 #endif
 
-#include "runtime/atomic.hpp"
-#include "runtime/prefetch.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadLocalStorage.hpp"
-#ifdef TARGET_OS_ARCH_bsd_x86
-# include "atomic_bsd_x86.inline.hpp"
-# include "orderAccess_bsd_x86.inline.hpp"
-# include "prefetch_bsd_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_zero
-# include "atomic_bsd_zero.inline.hpp"
-# include "orderAccess_bsd_zero.inline.hpp"
-# include "prefetch_bsd_zero.inline.hpp"
-#endif
 
 // Contains inlined functions for class Thread and ThreadLocalStorage
 
diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp
index c30aac5..b7e357c 100644
--- a/hotspot/src/os/linux/vm/os_linux.cpp
+++ b/hotspot/src/os/linux/vm/os_linux.cpp
@@ -49,6 +49,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -3500,9 +3501,12 @@
 
   assert(is_ptr_aligned(start, alignment), "Must be");
 
-  // os::reserve_memory_special will record this memory area.
-  // Need to release it here to prevent overlapping reservations.
-  MemTracker::record_virtual_memory_release((address)start, bytes);
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    // os::reserve_memory_special will record this memory area.
+    // Need to release it here to prevent overlapping reservations.
+    Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+    tkr.record((address)start, bytes);
+  }
 
   char* end = start + bytes;
 
@@ -3597,7 +3601,7 @@
     }
 
     // The memory is committed
-    MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, mtNone, CALLER_PC);
+    MemTracker::record_virtual_memory_reserve_and_commit((address)addr, bytes, CALLER_PC);
   }
 
   return addr;
@@ -3613,24 +3617,30 @@
 }
 
 bool os::release_memory_special(char* base, size_t bytes) {
-  assert(UseLargePages, "only for large pages");
-
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
-
   bool res;
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+    res = os::Linux::release_memory_special_impl(base, bytes);
+    if (res) {
+      tkr.record((address)base, bytes);
+    }
+
+  } else {
+    res = os::Linux::release_memory_special_impl(base, bytes);
+  }
+  return res;
+}
+
+bool os::Linux::release_memory_special_impl(char* base, size_t bytes) {
+  assert(UseLargePages, "only for large pages");
+  bool res;
+
   if (UseSHM) {
     res = os::Linux::release_memory_special_shm(base, bytes);
   } else {
     assert(UseHugeTLBFS, "must be");
     res = os::Linux::release_memory_special_huge_tlbfs(base, bytes);
   }
-
-  if (res) {
-    tkr.record((address)base, bytes);
-  } else {
-    tkr.discard();
-  }
-
   return res;
 }
 
diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp
index 829852f..e72cca1 100644
--- a/hotspot/src/os/linux/vm/os_linux.hpp
+++ b/hotspot/src/os/linux/vm/os_linux.hpp
@@ -108,6 +108,7 @@
   static char* reserve_memory_special_huge_tlbfs_only(size_t bytes, char* req_addr, bool exec);
   static char* reserve_memory_special_huge_tlbfs_mixed(size_t bytes, size_t alignment, char* req_addr, bool exec);
 
+  static bool release_memory_special_impl(char* base, size_t bytes);
   static bool release_memory_special_shm(char* base, size_t bytes);
   static bool release_memory_special_huge_tlbfs(char* base, size_t bytes);
 
diff --git a/hotspot/src/os/linux/vm/os_linux.inline.hpp b/hotspot/src/os/linux/vm/os_linux.inline.hpp
index 1afae5cc..10d56d8 100644
--- a/hotspot/src/os/linux/vm/os_linux.inline.hpp
+++ b/hotspot/src/os/linux/vm/os_linux.inline.hpp
@@ -26,24 +26,9 @@
 #define OS_LINUX_VM_OS_LINUX_INLINE_HPP
 
 #include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 
-#ifdef TARGET_OS_ARCH_linux_x86
-# include "orderAccess_linux_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_sparc
-# include "orderAccess_linux_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_zero
-# include "orderAccess_linux_zero.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_arm
-# include "orderAccess_linux_arm.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_ppc
-# include "orderAccess_linux_ppc.inline.hpp"
-#endif
-
 // System includes
 
 #include <unistd.h>
diff --git a/hotspot/src/os/linux/vm/perfMemory_linux.cpp b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
index 9708734..2eef5da 100644
--- a/hotspot/src/os/linux/vm/perfMemory_linux.cpp
+++ b/hotspot/src/os/linux/vm/perfMemory_linux.cpp
@@ -753,7 +753,7 @@
   (void)::memset((void*) mapAddress, 0, size);
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
 
   return mapAddress;
 }
@@ -924,7 +924,7 @@
   }
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size, CURRENT_PC, mtInternal);
 
   *addr = mapAddress;
   *sizep = size;
diff --git a/hotspot/src/os/linux/vm/thread_linux.inline.hpp b/hotspot/src/os/linux/vm/thread_linux.inline.hpp
index f5c9e9c..b58dc07 100644
--- a/hotspot/src/os/linux/vm/thread_linux.inline.hpp
+++ b/hotspot/src/os/linux/vm/thread_linux.inline.hpp
@@ -29,35 +29,8 @@
 #error "This file should only be included from thread.inline.hpp"
 #endif
 
-#include "runtime/atomic.hpp"
-#include "runtime/prefetch.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadLocalStorage.hpp"
-#ifdef TARGET_OS_ARCH_linux_x86
-# include "atomic_linux_x86.inline.hpp"
-# include "orderAccess_linux_x86.inline.hpp"
-# include "prefetch_linux_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_sparc
-# include "atomic_linux_sparc.inline.hpp"
-# include "orderAccess_linux_sparc.inline.hpp"
-# include "prefetch_linux_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_zero
-# include "atomic_linux_zero.inline.hpp"
-# include "orderAccess_linux_zero.inline.hpp"
-# include "prefetch_linux_zero.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_arm
-# include "atomic_linux_arm.inline.hpp"
-# include "orderAccess_linux_arm.inline.hpp"
-# include "prefetch_linux_arm.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_ppc
-# include "atomic_linux_ppc.inline.hpp"
-# include "orderAccess_linux_ppc.inline.hpp"
-# include "prefetch_linux_ppc.inline.hpp"
-#endif
 
 // Contains inlined functions for class Thread and ThreadLocalStorage
 
diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp
index 4696c4c..3035aa0 100644
--- a/hotspot/src/os/posix/vm/os_posix.cpp
+++ b/hotspot/src/os/posix/vm/os_posix.cpp
@@ -74,21 +74,41 @@
   VMError::report_coredump_status(buffer, success);
 }
 
-address os::get_caller_pc(int n) {
+int os::get_native_stack(address* stack, int frames, int toSkip) {
 #ifdef _NMT_NOINLINE_
-  n ++;
+  toSkip++;
 #endif
+
+  int frame_idx = 0;
+  int num_of_frames;  // number of frames captured
   frame fr = os::current_frame();
-  while (n > 0 && fr.pc() &&
-    !os::is_first_C_frame(&fr) && fr.sender_pc()) {
-    fr = os::get_sender_for_C_frame(&fr);
-    n --;
+  while (fr.pc() && frame_idx < frames) {
+    if (toSkip > 0) {
+      toSkip --;
+    } else {
+      stack[frame_idx ++] = fr.pc();
+    }
+    if (fr.fp() == NULL || os::is_first_C_frame(&fr)
+        ||fr.sender_pc() == NULL || fr.cb() != NULL) break;
+
+    if (fr.sender_pc() && !os::is_first_C_frame(&fr)) {
+      fr = os::get_sender_for_C_frame(&fr);
+    } else {
+      break;
+    }
   }
-  if (n == 0) {
-    return fr.pc();
-  } else {
-    return NULL;
+  num_of_frames = frame_idx;
+  for (; frame_idx < frames; frame_idx ++) {
+    stack[frame_idx] = NULL;
   }
+
+  return num_of_frames;
+}
+
+
+bool os::unsetenv(const char* name) {
+  assert(name != NULL, "Null pointer");
+  return (::unsetenv(name) == 0);
 }
 
 int os::get_last_error() {
diff --git a/hotspot/src/os/solaris/dtrace/libjvm_db.c b/hotspot/src/os/solaris/dtrace/libjvm_db.c
index b15c187..a383014 100644
--- a/hotspot/src/os/solaris/dtrace/libjvm_db.c
+++ b/hotspot/src/os/solaris/dtrace/libjvm_db.c
@@ -260,6 +260,9 @@
   uint64_t base;
   int err;
 
+  /* Clear *vmp now in case we jump to fail: */
+  memset(vmp, 0, sizeof(VMStructEntry));
+
   err = ps_pglobal_lookup(J->P, LIBJVM_SO, "gHotSpotVMStructs", &sym_addr);
   CHECK_FAIL(err);
   err = read_pointer(J, sym_addr, &gHotSpotVMStructs);
diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp
index 5fa85b6..c74dc70 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.cpp
@@ -48,6 +48,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
diff --git a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
index 4155c0f..921fcf7 100644
--- a/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
+++ b/hotspot/src/os/solaris/vm/os_solaris.inline.hpp
@@ -26,15 +26,9 @@
 #define OS_SOLARIS_VM_OS_SOLARIS_INLINE_HPP
 
 #include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 
-#ifdef TARGET_OS_ARCH_solaris_x86
-# include "orderAccess_solaris_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_sparc
-# include "orderAccess_solaris_sparc.inline.hpp"
-#endif
-
 // System includes
 #include <sys/param.h>
 #include <dlfcn.h>
diff --git a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp
index 1fa3001..2d279af 100644
--- a/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp
+++ b/hotspot/src/os/solaris/vm/perfMemory_solaris.cpp
@@ -770,7 +770,8 @@
   (void)::memset((void*) mapAddress, 0, size);
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,
+    size, CURRENT_PC, mtInternal);
 
   return mapAddress;
 }
@@ -941,7 +942,8 @@
   }
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,
+    size, CURRENT_PC, mtInternal);
 
   *addr = mapAddress;
   *sizep = size;
diff --git a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp
index a76ddeb..d7d6d37 100644
--- a/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp
+++ b/hotspot/src/os/solaris/vm/thread_solaris.inline.hpp
@@ -29,20 +29,9 @@
 #error "This file should only be included from thread.inline.hpp"
 #endif
 
-#include "runtime/atomic.hpp"
-#include "runtime/prefetch.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadLocalStorage.hpp"
-#ifdef TARGET_OS_ARCH_solaris_x86
-# include "atomic_solaris_x86.inline.hpp"
-# include "orderAccess_solaris_x86.inline.hpp"
-# include "prefetch_solaris_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_sparc
-# include "atomic_solaris_sparc.inline.hpp"
-# include "orderAccess_solaris_sparc.inline.hpp"
-# include "prefetch_solaris_sparc.inline.hpp"
-#endif
 
 // Thread::current is "hot" it's called > 128K times in the 1st 500 msecs of
 // startup.
diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp
index 2c0126c..b15136b 100644
--- a/hotspot/src/os/windows/vm/os_windows.cpp
+++ b/hotspot/src/os/windows/vm/os_windows.cpp
@@ -51,6 +51,7 @@
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/perfMemory.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -130,6 +131,7 @@
     case DLL_PROCESS_DETACH:
       if(ForceTimeHighResolution)
         timeEndPeriod(1L);
+
       break;
     default:
       break;
@@ -152,6 +154,10 @@
  return result > 0 && result < len;
 }
 
+bool os::unsetenv(const char* name) {
+  assert(name != NULL, "Null pointer");
+  return (SetEnvironmentVariable(name, NULL) == TRUE);
+}
 
 // No setuid programs under Windows.
 bool os::have_special_privileges() {
@@ -310,15 +316,17 @@
  * So far, this method is only used by Native Memory Tracking, which is
  * only supported on Windows XP or later.
  */
-address os::get_caller_pc(int n) {
+
+int os::get_native_stack(address* stack, int frames, int toSkip) {
 #ifdef _NMT_NOINLINE_
-  n ++;
+  toSkip ++;
 #endif
-  address pc;
-  if (os::Kernel32Dll::RtlCaptureStackBackTrace(n + 1, 1, (PVOID*)&pc, NULL) == 1) {
-    return pc;
+  int captured = Kernel32Dll::RtlCaptureStackBackTrace(toSkip + 1, frames,
+    (PVOID*)stack, NULL);
+  for (int index = captured; index < frames; index ++) {
+    stack[index] = NULL;
   }
-  return NULL;
+  return captured;
 }
 
 
@@ -2903,7 +2911,7 @@
                                 PAGE_READWRITE);
   // If reservation failed, return NULL
   if (p_buf == NULL) return NULL;
-  MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, mtNone, CALLER_PC);
+  MemTracker::record_virtual_memory_reserve((address)p_buf, size_of_reserve, CALLER_PC);
   os::release_memory(p_buf, bytes + chunk_size);
 
   // we still need to round up to a page boundary (in case we are using large pages)
@@ -2969,7 +2977,7 @@
         // need to create a dummy 'reserve' record to match
         // the release.
         MemTracker::record_virtual_memory_reserve((address)p_buf,
-          bytes_to_release, mtNone, CALLER_PC);
+          bytes_to_release, CALLER_PC);
         os::release_memory(p_buf, bytes_to_release);
       }
 #ifdef ASSERT
@@ -2988,11 +2996,10 @@
   }
   // Although the memory is allocated individually, it is returned as one.
   // NMT records it as one block.
-  address pc = CALLER_PC;
   if ((flags & MEM_COMMIT) != 0) {
-    MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, mtNone, pc);
+    MemTracker::record_virtual_memory_reserve_and_commit((address)p_buf, bytes, CALLER_PC);
   } else {
-    MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, mtNone, pc);
+    MemTracker::record_virtual_memory_reserve((address)p_buf, bytes, CALLER_PC);
   }
 
   // made it this far, success
@@ -3190,8 +3197,7 @@
     DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES;
     char * res = (char *)VirtualAlloc(addr, bytes, flag, prot);
     if (res != NULL) {
-      address pc = CALLER_PC;
-      MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, mtNone, pc);
+      MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, CALLER_PC);
     }
 
     return res;
diff --git a/hotspot/src/os/windows/vm/os_windows.inline.hpp b/hotspot/src/os/windows/vm/os_windows.inline.hpp
index a824b84..30ce468 100644
--- a/hotspot/src/os/windows/vm/os_windows.inline.hpp
+++ b/hotspot/src/os/windows/vm/os_windows.inline.hpp
@@ -26,12 +26,9 @@
 #define OS_WINDOWS_VM_OS_WINDOWS_INLINE_HPP
 
 #include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 
-#ifdef TARGET_OS_ARCH_windows_x86
-# include "orderAccess_windows_x86.inline.hpp"
-#endif
-
 inline const char* os::file_separator()                { return "\\"; }
 inline const char* os::line_separator()                { return "\r\n"; }
 inline const char* os::path_separator()                { return ";"; }
diff --git a/hotspot/src/os/windows/vm/perfMemory_windows.cpp b/hotspot/src/os/windows/vm/perfMemory_windows.cpp
index 1bf2729..b32fd9a 100644
--- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp
+++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -1498,7 +1498,8 @@
   (void)memset(mapAddress, '\0', size);
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress,
+    size, CURRENT_PC, mtInternal);
 
   return (char*) mapAddress;
 }
@@ -1680,7 +1681,8 @@
   }
 
   // it does not go through os api, the operation has to record from here
-  MemTracker::record_virtual_memory_reserve((address)mapAddress, size, mtInternal, CURRENT_PC);
+  MemTracker::record_virtual_memory_reserve_and_commit((address)mapAddress, size,
+    CURRENT_PC, mtInternal);
 
 
   *addrp = (char*)mapAddress;
@@ -1834,10 +1836,14 @@
     return;
   }
 
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
-  remove_file_mapping(addr);
-  // it does not go through os api, the operation has to record from here
-  tkr.record((address)addr, bytes);
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    // it does not go through os api, the operation has to record from here
+    Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+    remove_file_mapping(addr);
+    tkr.record((address)addr, bytes);
+  } else {
+    remove_file_mapping(addr);
+  }
 }
 
 char* PerfMemory::backing_store_filename() {
diff --git a/hotspot/src/os/windows/vm/thread_windows.inline.hpp b/hotspot/src/os/windows/vm/thread_windows.inline.hpp
index d73fabf..95dd17c 100644
--- a/hotspot/src/os/windows/vm/thread_windows.inline.hpp
+++ b/hotspot/src/os/windows/vm/thread_windows.inline.hpp
@@ -29,15 +29,8 @@
 #error "This file should only be included from thread.inline.hpp"
 #endif
 
-#include "runtime/atomic.hpp"
-#include "runtime/prefetch.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/threadLocalStorage.hpp"
-#ifdef TARGET_OS_ARCH_windows_x86
-# include "atomic_windows_x86.inline.hpp"
-# include "orderAccess_windows_x86.inline.hpp"
-# include "prefetch_windows_x86.inline.hpp"
-#endif
 
 // Contains inlined functions for class Thread and ThreadLocalStorage
 
diff --git a/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp b/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp
index 86ade82..744bb7c 100644
--- a/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp
+++ b/hotspot/src/os_cpu/aix_ppc/vm/atomic_aix_ppc.inline.hpp
@@ -26,7 +26,6 @@
 #ifndef OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP
 #define OS_CPU_AIX_OJDKPPC_VM_ATOMIC_AIX_PPC_INLINE_HPP
 
-#include "orderAccess_aix_ppc.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_ppc.hpp"
diff --git a/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp b/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp
index 07b212b..c8fcf1f 100644
--- a/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp
+++ b/hotspot/src/os_cpu/linux_ppc/vm/atomic_linux_ppc.inline.hpp
@@ -26,7 +26,6 @@
 #ifndef OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP
 #define OS_CPU_LINUX_PPC_VM_ATOMIC_LINUX_PPC_INLINE_HPP
 
-#include "orderAccess_linux_ppc.inline.hpp"
 #include "runtime/atomic.hpp"
 #include "runtime/os.hpp"
 #include "vm_version_ppc.hpp"
diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
index f8f23122..f8165a1 100644
--- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
+++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp
@@ -118,7 +118,7 @@
       *ret_sp = os::Linux::ucontext_get_sp(uc);
     }
     if (ret_fp) {
-      *ret_fp = os::Linux::ucontext_get_fp(uc);
+      *ret_fp = (intptr_t*)NULL;
     }
   } else {
     // construct empty ExtendedPC for return value checking
@@ -136,18 +136,15 @@
 
 frame os::fetch_frame_from_context(void* ucVoid) {
   intptr_t* sp;
-  intptr_t* fp;
-  ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, &fp);
-  return frame(sp, fp, epc.pc());
+  ExtendedPC epc = fetch_frame_from_context(ucVoid, &sp, NULL);
+  return frame(sp, frame::unpatchable, epc.pc());
 }
 
 frame os::get_sender_for_C_frame(frame* fr) {
-  return frame(fr->sender_sp(), fr->link(), fr->sender_pc());
+  return frame(fr->sender_sp(), frame::unpatchable, fr->sender_pc());
 }
 
 frame os::current_frame() {
-  fprintf(stderr, "current_frame()");
-
   intptr_t* sp = StubRoutines::Sparc::flush_callers_register_windows_func()();
   frame myframe(sp, frame::unpatchable,
                 CAST_FROM_FN_PTR(address, os::current_frame));
diff --git a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp
index c3d244d..4af6c52 100644
--- a/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp
+++ b/hotspot/src/os_cpu/linux_sparc/vm/vm_version_linux_sparc.cpp
@@ -55,7 +55,7 @@
 
   if (detect_niagara()) {
     NOT_PRODUCT(if (PrintMiscellaneous && Verbose) tty->print_cr("Detected Linux on Niagara");)
-    features = niagara1_m;
+    features = niagara1_m | T_family_m;
   }
 
   return features;
diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
index b6639c9..028e33f 100644
--- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
+++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 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
@@ -137,6 +137,21 @@
 #endif
     if (av & AV_SPARC_AES)       features |= aes_instructions_m;
 
+#ifndef AV_SPARC_SHA1
+#define AV_SPARC_SHA1   0x00400000  /* sha1 instruction supported */
+#endif
+    if (av & AV_SPARC_SHA1)         features |= sha1_instruction_m;
+
+#ifndef AV_SPARC_SHA256
+#define AV_SPARC_SHA256 0x00800000  /* sha256 instruction supported */
+#endif
+    if (av & AV_SPARC_SHA256)       features |= sha256_instruction_m;
+
+#ifndef AV_SPARC_SHA512
+#define AV_SPARC_SHA512 0x01000000  /* sha512 instruction supported */
+#endif
+    if (av & AV_SPARC_SHA512)       features |= sha512_instruction_m;
+
   } else {
     // getisax(2) failed, use the old legacy code.
 #ifndef PRODUCT
diff --git a/hotspot/src/share/vm/asm/codeBuffer.cpp b/hotspot/src/share/vm/asm/codeBuffer.cpp
index f05b502..24a3bbd 100644
--- a/hotspot/src/share/vm/asm/codeBuffer.cpp
+++ b/hotspot/src/share/vm/asm/codeBuffer.cpp
@@ -268,7 +268,7 @@
 
 GrowableArray<int>* CodeBuffer::create_patch_overflow() {
   if (_overflow_arena == NULL) {
-    _overflow_arena = new (mtCode) Arena();
+    _overflow_arena = new (mtCode) Arena(mtCode);
   }
   return new (_overflow_arena) GrowableArray<int>(_overflow_arena, 8, 0, 0);
 }
diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp
index 3aeb265..8fd7bec 100644
--- a/hotspot/src/share/vm/c1/c1_Compiler.cpp
+++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp
@@ -47,7 +47,7 @@
 
 void Compiler::init_c1_runtime() {
   BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
-  Arena* arena = new (mtCompiler) Arena();
+  Arena* arena = new (mtCompiler) Arena(mtCompiler);
   Runtime1::initialize(buffer_blob);
   FrameMap::initialize();
   // initialize data structures
diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
index 6d9daf5..3198ae8 100644
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
@@ -2061,7 +2061,7 @@
   bool will_link;
   ciKlass* klass = stream()->get_klass(will_link);
   assert(klass->is_instance_klass(), "must be an instance klass");
-  NewInstance* new_instance = new NewInstance(klass->as_instance_klass(), state_before);
+  NewInstance* new_instance = new NewInstance(klass->as_instance_klass(), state_before, stream()->is_unresolved_klass());
   _memory->new_instance(new_instance);
   apush(append_split(new_instance));
 }
diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp
index 19490bb..3121088 100644
--- a/hotspot/src/share/vm/c1/c1_Instruction.hpp
+++ b/hotspot/src/share/vm/c1/c1_Instruction.hpp
@@ -1291,16 +1291,18 @@
 LEAF(NewInstance, StateSplit)
  private:
   ciInstanceKlass* _klass;
+  bool _is_unresolved;
 
  public:
   // creation
-  NewInstance(ciInstanceKlass* klass, ValueStack* state_before)
+  NewInstance(ciInstanceKlass* klass, ValueStack* state_before, bool is_unresolved)
   : StateSplit(instanceType, state_before)
-  , _klass(klass)
+  , _klass(klass), _is_unresolved(is_unresolved)
   {}
 
   // accessors
   ciInstanceKlass* klass() const                 { return _klass; }
+  bool is_unresolved() const                     { return _is_unresolved; }
 
   virtual bool needs_exception_state() const     { return false; }
 
diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
index 7bcd4cc..890ccb7 100644
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp
@@ -466,8 +466,11 @@
 }
 
 
-void LIRGenerator::klass2reg_with_patching(LIR_Opr r, ciMetadata* obj, CodeEmitInfo* info) {
-  if (!obj->is_loaded() || PatchALot) {
+void LIRGenerator::klass2reg_with_patching(LIR_Opr r, ciMetadata* obj, CodeEmitInfo* info, bool need_resolve) {
+  /* C2 relies on constant pool entries being resolved (ciTypeFlow), so if TieredCompilation
+   * is active and the class hasn't yet been resolved we need to emit a patch that resolves
+   * the class. */
+  if ((TieredCompilation && need_resolve) || !obj->is_loaded() || PatchALot) {
     assert(info != NULL, "info must be set if class is not loaded");
     __ klass2reg_patch(NULL, r, info);
   } else {
@@ -660,9 +663,18 @@
   __ unlock_object(hdr, object, lock, scratch, slow_path);
 }
 
+#ifndef PRODUCT
+void LIRGenerator::print_if_not_loaded(const NewInstance* new_instance) {
+  if (PrintNotLoaded && !new_instance->klass()->is_loaded()) {
+    tty->print_cr("   ###class not loaded at new bci %d", new_instance->printable_bci());
+  } else if (PrintNotLoaded && (TieredCompilation && new_instance->is_unresolved())) {
+    tty->print_cr("   ###class not resolved at new bci %d", new_instance->printable_bci());
+  }
+}
+#endif
 
-void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, LIR_Opr scratch1, LIR_Opr scratch2, LIR_Opr scratch3, LIR_Opr scratch4, LIR_Opr klass_reg, CodeEmitInfo* info) {
-  klass2reg_with_patching(klass_reg, klass, info);
+void LIRGenerator::new_instance(LIR_Opr dst, ciInstanceKlass* klass, bool is_unresolved, LIR_Opr scratch1, LIR_Opr scratch2, LIR_Opr scratch3, LIR_Opr scratch4, LIR_Opr klass_reg, CodeEmitInfo* info) {
+  klass2reg_with_patching(klass_reg, klass, info, is_unresolved);
   // If klass is not loaded we do not know if the klass has finalizers:
   if (UseFastNewInstance && klass->is_loaded()
       && !Klass::layout_helper_needs_slow_path(klass->layout_helper())) {
diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
index 90b278f..69d9a0e 100644
--- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
+++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp
@@ -169,6 +169,8 @@
     return this;
   }
 
+  void print_if_not_loaded(const NewInstance* new_instance) PRODUCT_RETURN;
+
 #ifdef ASSERT
   LIR_List* lir(const char * file, int line) const {
     _lir->set_file_and_line(file, line);
@@ -307,7 +309,7 @@
 
   void store_stack_parameter (LIR_Opr opr, ByteSize offset_from_sp_in_bytes);
 
-  void klass2reg_with_patching(LIR_Opr r, ciMetadata* obj, CodeEmitInfo* info);
+  void klass2reg_with_patching(LIR_Opr r, ciMetadata* obj, CodeEmitInfo* info, bool need_resolve = false);
 
   // this loads the length and compares against the index
   void array_range_check          (LIR_Opr array, LIR_Opr index, CodeEmitInfo* null_check_info, CodeEmitInfo* range_check_info);
@@ -325,7 +327,7 @@
   void monitor_enter (LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_Opr scratch, int monitor_no, CodeEmitInfo* info_for_exception, CodeEmitInfo* info);
   void monitor_exit  (LIR_Opr object, LIR_Opr lock, LIR_Opr hdr, LIR_Opr scratch, int monitor_no);
 
-  void new_instance    (LIR_Opr  dst, ciInstanceKlass* klass, LIR_Opr  scratch1, LIR_Opr  scratch2, LIR_Opr  scratch3,  LIR_Opr scratch4, LIR_Opr  klass_reg, CodeEmitInfo* info);
+  void new_instance    (LIR_Opr  dst, ciInstanceKlass* klass, bool is_unresolved, LIR_Opr  scratch1, LIR_Opr  scratch2, LIR_Opr  scratch3,  LIR_Opr scratch4, LIR_Opr  klass_reg, CodeEmitInfo* info);
 
   // machine dependent
   void cmp_mem_int(LIR_Condition condition, LIR_Opr base, int disp, int c, CodeEmitInfo* info);
diff --git a/hotspot/src/share/vm/c1/c1_LinearScan.cpp b/hotspot/src/share/vm/c1/c1_LinearScan.cpp
index 91bef59..abee3ac 100644
--- a/hotspot/src/share/vm/c1/c1_LinearScan.cpp
+++ b/hotspot/src/share/vm/c1/c1_LinearScan.cpp
@@ -1628,25 +1628,22 @@
   Interval* precolored_cpu_intervals, *not_precolored_cpu_intervals;
   Interval* precolored_fpu_intervals, *not_precolored_fpu_intervals;
 
-  create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals, is_precolored_cpu_interval, is_virtual_cpu_interval);
-  if (has_fpu_registers()) {
-    create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
-#ifdef ASSERT
-  } else {
-    // fpu register allocation is omitted because no virtual fpu registers are present
-    // just check this again...
-    create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals, is_precolored_fpu_interval, is_virtual_fpu_interval);
-    assert(not_precolored_fpu_intervals == Interval::end(), "missed an uncolored fpu interval");
-#endif
-  }
-
   // allocate cpu registers
+  create_unhandled_lists(&precolored_cpu_intervals, &not_precolored_cpu_intervals,
+                         is_precolored_cpu_interval, is_virtual_cpu_interval);
+
+  // allocate fpu registers
+  create_unhandled_lists(&precolored_fpu_intervals, &not_precolored_fpu_intervals,
+                         is_precolored_fpu_interval, is_virtual_fpu_interval);
+
+  // the fpu interval allocation cannot be moved down below with the fpu section as
+  // the cpu_lsw.walk() changes interval positions.
+
   LinearScanWalker cpu_lsw(this, precolored_cpu_intervals, not_precolored_cpu_intervals);
   cpu_lsw.walk();
   cpu_lsw.finish_allocation();
 
   if (has_fpu_registers()) {
-    // allocate fpu registers
     LinearScanWalker fpu_lsw(this, precolored_fpu_intervals, not_precolored_fpu_intervals);
     fpu_lsw.walk();
     fpu_lsw.finish_allocation();
diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp
index b6a93c8..386e773 100644
--- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp
+++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp
@@ -1018,6 +1018,7 @@
               n_copy->set_data((intx) (load_klass()));
             } else {
               assert(mirror() != NULL, "klass not set");
+              // Don't need a G1 pre-barrier here since we assert above that data isn't an oop.
               n_copy->set_data(cast_from_oop<intx>(mirror()));
             }
 
diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp
index 81f26b4..00e6d09 100644
--- a/hotspot/src/share/vm/ci/ciEnv.cpp
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp
@@ -51,6 +51,7 @@
 #include "runtime/init.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/sharedRuntime.hpp"
+#include "runtime/thread.inline.hpp"
 #include "utilities/dtrace.hpp"
 #include "utilities/macros.hpp"
 #ifdef COMPILER1
@@ -85,7 +86,8 @@
 
 // ------------------------------------------------------------------
 // ciEnv::ciEnv
-ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter) {
+ciEnv::ciEnv(CompileTask* task, int system_dictionary_modification_counter)
+  : _ciEnv_arena(mtCompiler) {
   VM_ENTRY_MARK;
 
   // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc.
@@ -138,7 +140,7 @@
   _the_min_jint_string = NULL;
 }
 
-ciEnv::ciEnv(Arena* arena) {
+ciEnv::ciEnv(Arena* arena) : _ciEnv_arena(mtCompiler) {
   ASSERT_IN_VM;
 
   // Set up ciEnv::current immediately, for the sake of ciObjectFactory, etc.
diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp
index 8980d9a..30ec2d7 100644
--- a/hotspot/src/share/vm/ci/ciEnv.hpp
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp
@@ -184,6 +184,10 @@
     }
   }
 
+  void ensure_metadata_alive(ciMetadata* m) {
+    _factory->ensure_metadata_alive(m);
+  }
+
   ciInstance* get_instance(oop o) {
     if (o == NULL) return NULL;
     return get_object(o)->as_instance();
diff --git a/hotspot/src/share/vm/ci/ciKlass.hpp b/hotspot/src/share/vm/ci/ciKlass.hpp
index 8e6574b..4fb9911 100644
--- a/hotspot/src/share/vm/ci/ciKlass.hpp
+++ b/hotspot/src/share/vm/ci/ciKlass.hpp
@@ -43,6 +43,7 @@
   friend class ciMethod;
   friend class ciMethodData;
   friend class ciObjArrayKlass;
+  friend class ciReceiverTypeData;
 
 private:
   ciSymbol* _name;
diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp
index 1b604ba..c57ec15 100644
--- a/hotspot/src/share/vm/ci/ciMethodData.cpp
+++ b/hotspot/src/share/vm/ci/ciMethodData.cpp
@@ -170,6 +170,7 @@
     Klass* k = data->as_ReceiverTypeData()->receiver(row);
     if (k != NULL) {
       ciKlass* klass = CURRENT_ENV->get_klass(k);
+      CURRENT_ENV->ensure_metadata_alive(klass);
       set_receiver(row, klass);
     }
   }
@@ -191,6 +192,7 @@
 void ciSpeculativeTrapData::translate_from(const ProfileData* data) {
   Method* m = data->as_SpeculativeTrapData()->method();
   ciMethod* ci_m = CURRENT_ENV->get_method(m);
+  CURRENT_ENV->ensure_metadata_alive(ci_m);
   set_method(ci_m);
 }
 
diff --git a/hotspot/src/share/vm/ci/ciMethodData.hpp b/hotspot/src/share/vm/ci/ciMethodData.hpp
index b1809a1..41a66c1 100644
--- a/hotspot/src/share/vm/ci/ciMethodData.hpp
+++ b/hotspot/src/share/vm/ci/ciMethodData.hpp
@@ -70,6 +70,7 @@
     Klass* v = TypeEntries::valid_klass(k);
     if (v != NULL) {
       ciKlass* klass = CURRENT_ENV->get_klass(v);
+      CURRENT_ENV->ensure_metadata_alive(klass);
       return with_status(klass, k);
     }
     return with_status(NULL, k);
diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp
index d257e8a..aaa607f 100644
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 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
@@ -46,6 +46,9 @@
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
 #include "runtime/fieldType.hpp"
+#if INCLUDE_ALL_GCS
+# include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#endif
 
 // ciObjectFactory
 //
@@ -109,7 +112,7 @@
   // This Arena is long lived and exists in the resource mark of the
   // compiler thread that initializes the initial ciObjectFactory which
   // creates the shared ciObjects that all later ciObjectFactories use.
-  Arena* arena = new (mtCompiler) Arena();
+  Arena* arena = new (mtCompiler) Arena(mtCompiler);
   ciEnv initial(arena);
   ciEnv* env = ciEnv::current();
   env->_factory->init_shared_objects();
@@ -374,6 +377,37 @@
   return NULL;
 }
 
+// ------------------------------------------------------------------
+// ciObjectFactory::ensure_metadata_alive
+//
+// Ensure that the metadata wrapped by the ciMetadata is kept alive by GC.
+// This is primarily useful for metadata which is considered as weak roots
+// by the GC but need to be strong roots if reachable from a current compilation.
+//
+void ciObjectFactory::ensure_metadata_alive(ciMetadata* m) {
+  ASSERT_IN_VM; // We're handling raw oops here.
+
+#if INCLUDE_ALL_GCS
+  if (!UseG1GC) {
+    return;
+  }
+  Klass* metadata_owner_klass;
+  if (m->is_klass()) {
+    metadata_owner_klass = m->as_klass()->get_Klass();
+  } else if (m->is_method()) {
+    metadata_owner_klass = m->as_method()->get_Method()->constants()->pool_holder();
+  } else {
+    fatal("Not implemented for other types of metadata");
+  }
+
+  oop metadata_holder = metadata_owner_klass->klass_holder();
+  if (metadata_holder != NULL) {
+    G1SATBCardTableModRefBS::enqueue(metadata_holder);
+  }
+
+#endif
+}
+
 //------------------------------------------------------------------
 // ciObjectFactory::get_unloaded_method
 //
diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.hpp b/hotspot/src/share/vm/ci/ciObjectFactory.hpp
index c1baca0..6c228e0 100644
--- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp
@@ -75,6 +75,8 @@
   ciObject* create_new_object(oop o);
   ciMetadata* create_new_object(Metadata* o);
 
+  void ensure_metadata_alive(ciMetadata* m);
+
   static bool is_equal(NonPermObject* p, oop key) {
     return p->object()->get_oop() == key;
   }
diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp
index c0d4143..35a0758 100644
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp
@@ -2780,7 +2780,7 @@
   ClassFileStream* cfs = stream();
   u1* current_start = cfs->current();
 
-  guarantee_property(attribute_byte_length > sizeof(u2),
+  guarantee_property(attribute_byte_length >= sizeof(u2),
                      "Invalid BootstrapMethods attribute length %u in class file %s",
                      attribute_byte_length,
                      CHECK);
@@ -2793,11 +2793,6 @@
                      "Short length on BootstrapMethods in class file %s",
                      CHECK);
 
-  guarantee_property(attribute_byte_length >= sizeof(u2),
-                     "Invalid BootstrapMethods attribute length %u in class file %s",
-                     attribute_byte_length,
-                     CHECK);
-
   // The attribute contains a counted array of counted tuples of shorts,
   // represending bootstrap specifiers:
   //    length*{bootstrap_method_index, argument_count*{argument_index}}
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.cpp b/hotspot/src/share/vm/classfile/classLoaderData.cpp
index 2c613bd..352fa71 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.cpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.cpp
@@ -73,7 +73,11 @@
 
 ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) :
   _class_loader(h_class_loader()),
-  _is_anonymous(is_anonymous), _keep_alive(is_anonymous), // initially
+  _is_anonymous(is_anonymous),
+  // An anonymous class loader data doesn't have anything to keep
+  // it from being unloaded during parsing of the anonymous class.
+  // The null-class-loader should always be kept alive.
+  _keep_alive(is_anonymous || h_class_loader.is_null()),
   _metaspace(NULL), _unloading(false), _klasses(NULL),
   _claimed(0), _jmethod_ids(NULL), _handles(NULL), _deallocate_list(NULL),
   _next(NULL), _dependencies(dependencies),
@@ -317,12 +321,45 @@
   }
 }
 
+#ifdef ASSERT
+class AllAliveClosure : public OopClosure {
+  BoolObjectClosure* _is_alive_closure;
+  bool _found_dead;
+ public:
+  AllAliveClosure(BoolObjectClosure* is_alive_closure) : _is_alive_closure(is_alive_closure), _found_dead(false) {}
+  template <typename T> void do_oop_work(T* p) {
+    T heap_oop = oopDesc::load_heap_oop(p);
+    if (!oopDesc::is_null(heap_oop)) {
+      oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
+      if (!_is_alive_closure->do_object_b(obj)) {
+        _found_dead = true;
+      }
+    }
+  }
+  void do_oop(oop* p)       { do_oop_work<oop>(p); }
+  void do_oop(narrowOop* p) { do_oop_work<narrowOop>(p); }
+  bool found_dead()         { return _found_dead; }
+};
+#endif
+
+oop ClassLoaderData::keep_alive_object() const {
+  assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
+  return is_anonymous() ? _klasses->java_mirror() : class_loader();
+}
+
 bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const {
-  bool alive =
-    is_anonymous() ?
-       is_alive_closure->do_object_b(_klasses->java_mirror()) :
-       class_loader() == NULL || is_alive_closure->do_object_b(class_loader());
-  assert(!alive || claimed(), "must be claimed");
+  bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
+      || is_alive_closure->do_object_b(keep_alive_object());
+
+#ifdef ASSERT
+  if (alive) {
+    AllAliveClosure all_alive_closure(is_alive_closure);
+    KlassToOopClosure klass_closure(&all_alive_closure);
+    const_cast<ClassLoaderData*>(this)->oops_do(&all_alive_closure, &klass_closure, false);
+    assert(!all_alive_closure.found_dead(), err_msg("Found dead oop in alive cld: " PTR_FORMAT, p2i(this)));
+  }
+#endif
+
   return alive;
 }
 
@@ -601,11 +638,36 @@
 
 void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
   if (ClassUnloading) {
-    ClassLoaderData::the_null_class_loader_data()->oops_do(f, klass_closure, must_claim);
-    // keep any special CLDs alive.
-    ClassLoaderDataGraph::keep_alive_oops_do(f, klass_closure, must_claim);
+    keep_alive_oops_do(f, klass_closure, must_claim);
   } else {
-    ClassLoaderDataGraph::oops_do(f, klass_closure, must_claim);
+    oops_do(f, klass_closure, must_claim);
+  }
+}
+
+void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
+  for (ClassLoaderData* cld = _head; cl != NULL && cld != NULL; cld = cld->next()) {
+    cl->do_cld(cld);
+  }
+}
+
+void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
+  for (ClassLoaderData* cld = _head;  cld != NULL; cld = cld->_next) {
+    CLDClosure* closure = cld->keep_alive() ? strong : weak;
+    if (closure != NULL) {
+      closure->do_cld(cld);
+    }
+  }
+}
+
+void ClassLoaderDataGraph::keep_alive_cld_do(CLDClosure* cl) {
+  roots_cld_do(cl, NULL);
+}
+
+void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
+  if (ClassUnloading) {
+    keep_alive_cld_do(cl);
+  } else {
+    cld_do(cl);
   }
 }
 
@@ -660,6 +722,16 @@
   return array;
 }
 
+bool ClassLoaderDataGraph::unload_list_contains(const void* x) {
+  assert(SafepointSynchronize::is_at_safepoint(), "only safe to call at safepoint");
+  for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) {
+    if (cld->metaspace_or_null() != NULL && cld->metaspace_or_null()->contains(x)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 #ifndef PRODUCT
 bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
   for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
@@ -689,7 +761,7 @@
   bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
   MetadataOnStackMark md_on_stack;
   while (data != NULL) {
-    if (data->keep_alive() || data->is_alive(is_alive_closure)) {
+    if (data->is_alive(is_alive_closure)) {
       if (has_redefined_a_class) {
         data->classes_do(InstanceKlass::purge_previous_versions);
       }
@@ -780,6 +852,60 @@
   return _rw_metaspace;
 }
 
+ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic()
+    : _next_klass(NULL) {
+  ClassLoaderData* cld = ClassLoaderDataGraph::_head;
+  Klass* klass = NULL;
+
+  // Find the first klass in the CLDG.
+  while (cld != NULL) {
+    klass = cld->_klasses;
+    if (klass != NULL) {
+      _next_klass = klass;
+      return;
+    }
+    cld = cld->next();
+  }
+}
+
+Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) {
+  Klass* next = klass->next_link();
+  if (next != NULL) {
+    return next;
+  }
+
+  // No more klasses in the current CLD. Time to find a new CLD.
+  ClassLoaderData* cld = klass->class_loader_data();
+  while (next == NULL) {
+    cld = cld->next();
+    if (cld == NULL) {
+      break;
+    }
+    next = cld->_klasses;
+  }
+
+  return next;
+}
+
+Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() {
+  Klass* head = (Klass*)_next_klass;
+
+  while (head != NULL) {
+    Klass* next = next_klass_in_cldg(head);
+
+    Klass* old_head = (Klass*)Atomic::cmpxchg_ptr(next, &_next_klass, head);
+
+    if (old_head == head) {
+      return head; // Won the CAS.
+    }
+
+    head = old_head;
+  }
+
+  // Nothing more for the iterator to hand out.
+  assert(head == NULL, err_msg("head is " PTR_FORMAT ", expected not null:", p2i(head)));
+  return NULL;
+}
 
 ClassLoaderDataGraphMetaspaceIterator::ClassLoaderDataGraphMetaspaceIterator() {
   _data = ClassLoaderDataGraph::_head;
diff --git a/hotspot/src/share/vm/classfile/classLoaderData.hpp b/hotspot/src/share/vm/classfile/classLoaderData.hpp
index bd8dcc0..edfdf99 100644
--- a/hotspot/src/share/vm/classfile/classLoaderData.hpp
+++ b/hotspot/src/share/vm/classfile/classLoaderData.hpp
@@ -31,7 +31,6 @@
 #include "memory/metaspaceCounters.hpp"
 #include "runtime/mutex.hpp"
 #include "utilities/growableArray.hpp"
-
 #if INCLUDE_TRACE
 # include "utilities/ticks.hpp"
 #endif
@@ -59,6 +58,7 @@
 class ClassLoaderDataGraph : public AllStatic {
   friend class ClassLoaderData;
   friend class ClassLoaderDataGraphMetaspaceIterator;
+  friend class ClassLoaderDataGraphKlassIteratorAtomic;
   friend class VMStructs;
  private:
   // All CLDs (except the null CLD) can be reached by walking _head->_next->...
@@ -75,9 +75,16 @@
   static ClassLoaderData* find_or_create(Handle class_loader, TRAPS);
   static void purge();
   static void clear_claimed_marks();
+  // oops do
   static void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim);
-  static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
   static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
+  static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
+  // cld do
+  static void cld_do(CLDClosure* cl);
+  static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
+  static void keep_alive_cld_do(CLDClosure* cl);
+  static void always_strong_cld_do(CLDClosure* cl);
+  // klass do
   static void classes_do(KlassClosure* klass_closure);
   static void classes_do(void f(Klass* const));
   static void loaded_classes_do(KlassClosure* klass_closure);
@@ -102,6 +109,7 @@
   static void dump() { dump_on(tty); }
   static void verify();
 
+  static bool unload_list_contains(const void* x);
 #ifndef PRODUCT
   static bool contains_loader_data(ClassLoaderData* loader_data);
 #endif
@@ -134,6 +142,7 @@
   };
 
   friend class ClassLoaderDataGraph;
+  friend class ClassLoaderDataGraphKlassIteratorAtomic;
   friend class ClassLoaderDataGraphMetaspaceIterator;
   friend class MetaDataFactory;
   friend class Method;
@@ -149,7 +158,7 @@
                            // classes in the class loader are allocated.
   Mutex* _metaspace_lock;  // Locks the metaspace for allocations and setup.
   bool _unloading;         // true if this class loader goes away
-  bool _keep_alive;        // if this CLD can be unloaded for anonymous loaders
+  bool _keep_alive;        // if this CLD is kept alive without a keep_alive_object().
   bool _is_anonymous;      // if this CLD is for an anonymous class
   volatile int _claimed;   // true if claimed, for example during GC traces.
                            // To avoid applying oop closure more than once.
@@ -195,7 +204,6 @@
 
   void unload();
   bool keep_alive() const       { return _keep_alive; }
-  bool is_alive(BoolObjectClosure* is_alive_closure) const;
   void classes_do(void f(Klass*));
   void loaded_classes_do(KlassClosure* klass_closure);
   void classes_do(void f(InstanceKlass*));
@@ -207,6 +215,9 @@
   MetaWord* allocate(size_t size);
 
  public:
+
+  bool is_alive(BoolObjectClosure* is_alive_closure) const;
+
   // Accessors
   Metaspace* metaspace_or_null() const     { return _metaspace; }
 
@@ -240,13 +251,16 @@
 
   oop class_loader() const      { return _class_loader; }
 
+  // The object the GC is using to keep this ClassLoaderData alive.
+  oop keep_alive_object() const;
+
   // Returns true if this class loader data is for a loader going away.
   bool is_unloading() const     {
     assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded");
     return _unloading;
   }
-  // Anonymous class loader data doesn't have anything to keep them from
-  // being unloaded during parsing the anonymous class.
+
+  // Used to make sure that this CLD is not unloaded.
   void set_keep_alive(bool value) { _keep_alive = value; }
 
   unsigned int identity_hash() {
@@ -287,6 +301,16 @@
   void initialize_shared_metaspaces();
 };
 
+// An iterator that distributes Klasses to parallel worker threads.
+class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj {
+  volatile Klass* _next_klass;
+ public:
+  ClassLoaderDataGraphKlassIteratorAtomic();
+  Klass* next_klass();
+ private:
+  static Klass* next_klass_in_cldg(Klass* klass);
+};
+
 class ClassLoaderDataGraphMetaspaceIterator : public StackObj {
   ClassLoaderData* _data;
  public:
diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp
index b7b4f35..3ac30ac 100644
--- a/hotspot/src/share/vm/classfile/dictionary.cpp
+++ b/hotspot/src/share/vm/classfile/dictionary.cpp
@@ -28,6 +28,7 @@
 #include "memory/iterator.hpp"
 #include "oops/oop.inline.hpp"
 #include "prims/jvmtiRedefineClassesTrace.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/hashtable.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
@@ -129,15 +130,13 @@
 }
 
 
-bool Dictionary::do_unloading() {
+void Dictionary::do_unloading() {
   assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
-  bool class_was_unloaded = false;
-  int  index = 0; // Defined here for portability! Do not move
 
   // Remove unloadable entries and classes from system dictionary
   // The placeholder array has been handled in always_strong_oops_do.
   DictionaryEntry* probe = NULL;
-  for (index = 0; index < table_size(); index++) {
+  for (int index = 0; index < table_size(); index++) {
     for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
       probe = *p;
       Klass* e = probe->klass();
@@ -157,16 +156,8 @@
         // Do we need to delete this system dictionary entry?
         if (loader_data->is_unloading()) {
           // If the loader is not live this entry should always be
-          // removed (will never be looked up again). Note that this is
-          // not the same as unloading the referred class.
-          if (k_def_class_loader_data == loader_data) {
-            // This is the defining entry, so the referred class is about
-            // to be unloaded.
-            class_was_unloaded = true;
-          }
-          // Also remove this system dictionary entry.
+          // removed (will never be looked up again).
           purge_entry = true;
-
         } else {
           // The loader in this entry is alive. If the klass is dead,
           // (determined by checking the defining class loader)
@@ -195,9 +186,28 @@
       p = probe->next_addr();
     }
   }
-  return class_was_unloaded;
 }
 
+void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
+  // Skip the strong roots probe marking if the closures are the same.
+  if (strong == weak) {
+    oops_do(strong);
+    return;
+  }
+
+  for (int index = 0; index < table_size(); index++) {
+    for (DictionaryEntry *probe = bucket(index);
+                          probe != NULL;
+                          probe = probe->next()) {
+      Klass* e = probe->klass();
+      ClassLoaderData* loader_data = probe->loader_data();
+      if (is_strongly_reachable(loader_data, e)) {
+        probe->set_strongly_reachable();
+      }
+    }
+  }
+  _pd_cache_table->roots_oops_do(strong, weak);
+}
 
 void Dictionary::always_strong_oops_do(OopClosure* blk) {
   // Follow all system classes and temporary placeholders in dictionary; only
@@ -489,6 +499,23 @@
   }
 }
 
+void ProtectionDomainCacheTable::roots_oops_do(OopClosure* strong, OopClosure* weak) {
+  for (int index = 0; index < table_size(); index++) {
+    for (ProtectionDomainCacheEntry* probe = bucket(index);
+                                     probe != NULL;
+                                     probe = probe->next()) {
+      if (probe->is_strongly_reachable()) {
+        probe->reset_strongly_reachable();
+        probe->oops_do(strong);
+      } else {
+        if (weak != NULL) {
+          probe->oops_do(weak);
+        }
+      }
+    }
+  }
+}
+
 uint ProtectionDomainCacheTable::bucket_size() {
   return sizeof(ProtectionDomainCacheEntry);
 }
diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp
index bc25c81..6c907c3 100644
--- a/hotspot/src/share/vm/classfile/dictionary.hpp
+++ b/hotspot/src/share/vm/classfile/dictionary.hpp
@@ -89,6 +89,7 @@
   // GC support
   void oops_do(OopClosure* f);
   void always_strong_oops_do(OopClosure* blk);
+  void roots_oops_do(OopClosure* strong, OopClosure* weak);
 
   void always_strong_classes_do(KlassClosure* closure);
 
@@ -107,9 +108,8 @@
     return (loader_data->is_the_null_class_loader_data() || !ClassUnloading);
   }
 
-  // Unload (that is, break root links to) all unmarked classes and
-  // loaders.  Returns "true" iff something was unloaded.
-  bool do_unloading();
+  // Unload (that is, break root links to) all unmarked classes and loaders.
+  void do_unloading();
 
   // Protection domains
   Klass* find(int index, unsigned int hash, Symbol* name,
@@ -218,6 +218,7 @@
   // GC support
   void oops_do(OopClosure* f);
   void always_strong_oops_do(OopClosure* f);
+  void roots_oops_do(OopClosure* strong, OopClosure* weak);
 
   static uint bucket_size();
 
diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp
index 4a84c5f..1d025ce 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.cpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.cpp
@@ -463,12 +463,11 @@
   return true;
 }
 
-void java_lang_String::print(Handle java_string, outputStream* st) {
-  oop          obj    = java_string();
-  assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string");
-  typeArrayOop value  = java_lang_String::value(obj);
-  int          offset = java_lang_String::offset(obj);
-  int          length = java_lang_String::length(obj);
+void java_lang_String::print(oop java_string, outputStream* st) {
+  assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
+  typeArrayOop value  = java_lang_String::value(java_string);
+  int          offset = java_lang_String::offset(java_string);
+  int          length = java_lang_String::length(java_string);
 
   int end = MIN2(length, 100);
   if (value == NULL) {
diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp
index 8b3bfc4..e566ec7 100644
--- a/hotspot/src/share/vm/classfile/javaClasses.hpp
+++ b/hotspot/src/share/vm/classfile/javaClasses.hpp
@@ -208,7 +208,7 @@
   }
 
   // Debugging
-  static void print(Handle java_string, outputStream* st);
+  static void print(oop java_string, outputStream* st);
   friend class JavaClasses;
 };
 
diff --git a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp
index 032c3e3..d21e19b 100644
--- a/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp
+++ b/hotspot/src/share/vm/classfile/metadataOnStackMark.cpp
@@ -47,8 +47,11 @@
   if (_marked_objects == NULL) {
     _marked_objects = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(1000, true);
   }
+
   Threads::metadata_do(Metadata::mark_on_stack);
-  CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
+  if (JvmtiExport::has_redefined_a_class()) {
+    CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
+  }
   CompileBroker::mark_on_stack();
   JvmtiCurrentBreakpoints::metadata_do(Metadata::mark_on_stack);
   ThreadService::metadata_do(Metadata::mark_on_stack);
diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.cpp b/hotspot/src/share/vm/classfile/stackMapFrame.cpp
index c3f6946..9cb1d30 100644
--- a/hotspot/src/share/vm/classfile/stackMapFrame.cpp
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -54,21 +54,6 @@
   return frame;
 }
 
-bool StackMapFrame::has_new_object() const {
-  int32_t i;
-  for (i = 0; i < _max_locals; i++) {
-    if (_locals[i].is_uninitialized()) {
-      return true;
-    }
-  }
-  for (i = 0; i < _stack_size; i++) {
-    if (_stack[i].is_uninitialized()) {
-      return true;
-    }
-  }
-  return false;
-}
-
 void StackMapFrame::initialize_object(
     VerificationType old_object, VerificationType new_object) {
   int32_t i;
diff --git a/hotspot/src/share/vm/classfile/stackMapFrame.hpp b/hotspot/src/share/vm/classfile/stackMapFrame.hpp
index 237acce..53582c1 100644
--- a/hotspot/src/share/vm/classfile/stackMapFrame.hpp
+++ b/hotspot/src/share/vm/classfile/stackMapFrame.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 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
@@ -155,10 +155,6 @@
     const methodHandle m, VerificationType thisKlass, TRAPS);
 
   // Search local variable type array and stack type array.
-  // Return true if an uninitialized object is found.
-  bool has_new_object() const;
-
-  // Search local variable type array and stack type array.
   // Set every element with type of old_object to new_object.
   void initialize_object(
     VerificationType old_object, VerificationType new_object);
diff --git a/hotspot/src/share/vm/classfile/stackMapTable.cpp b/hotspot/src/share/vm/classfile/stackMapTable.cpp
index feb5ae2..f74adbe 100644
--- a/hotspot/src/share/vm/classfile/stackMapTable.cpp
+++ b/hotspot/src/share/vm/classfile/stackMapTable.cpp
@@ -70,24 +70,26 @@
 
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target,
-    bool match, bool update, ErrorContext* ctx, TRAPS) const {
+    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
   int index = get_index_from_offset(target);
-  return match_stackmap(frame, target, index, match, update, ctx, THREAD);
+  return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD);
 }
 
 // Match and/or update current_frame to the frame in stackmap table with
 // specified offset and frame index. Return true if the two frames match.
+// handler is true if the frame in stackmap_table is for an exception handler.
 //
-// The values of match and update are:                  _match__update_
+// The values of match and update are:                  _match__update__handler
 //
-// checking a branch target/exception handler:           true   false
+// checking a branch target:                             true   false   false
+// checking an exception handler:                        true   false   true
 // linear bytecode verification following an
-// unconditional branch:                                 false  true
+// unconditional branch:                                 false  true    false
 // linear bytecode verification not following an
-// unconditional branch:                                 true   true
+// unconditional branch:                                 true   true    false
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target, int32_t frame_index,
-    bool match, bool update, ErrorContext* ctx, TRAPS) const {
+    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const {
   if (frame_index < 0 || frame_index >= _frame_count) {
     *ctx = ErrorContext::missing_stackmap(frame->offset());
     frame->verifier()->verify_error(
@@ -98,11 +100,9 @@
   StackMapFrame *stackmap_frame = _frame_array[frame_index];
   bool result = true;
   if (match) {
-    // when checking handler target, match == true && update == false
-    bool is_exception_handler = !update;
     // Has direct control flow from last instruction, need to match the two
     // frames.
-    result = frame->is_assignable_to(stackmap_frame, is_exception_handler,
+    result = frame->is_assignable_to(stackmap_frame, handler,
         ctx, CHECK_VERIFY_(frame->verifier(), result));
   }
   if (update) {
@@ -126,24 +126,10 @@
     StackMapFrame* frame, int32_t target, TRAPS) const {
   ErrorContext ctx;
   bool match = match_stackmap(
-    frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier()));
+    frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier()));
   if (!match || (target < 0 || target >= _code_length)) {
     frame->verifier()->verify_error(ctx,
         "Inconsistent stackmap frames at branch target %d", target);
-    return;
-  }
-  // check if uninitialized objects exist on backward branches
-  check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
-  frame->verifier()->update_furthest_jump(target);
-}
-
-void StackMapTable::check_new_object(
-    const StackMapFrame* frame, int32_t target, TRAPS) const {
-  if (frame->offset() > target && frame->has_new_object()) {
-    frame->verifier()->verify_error(
-        ErrorContext::bad_code(frame->offset()),
-        "Uninitialized object exists on backward branch %d", target);
-    return;
   }
 }
 
diff --git a/hotspot/src/share/vm/classfile/stackMapTable.hpp b/hotspot/src/share/vm/classfile/stackMapTable.hpp
index ee8b33f..5354a0b 100644
--- a/hotspot/src/share/vm/classfile/stackMapTable.hpp
+++ b/hotspot/src/share/vm/classfile/stackMapTable.hpp
@@ -74,12 +74,12 @@
   // specified offset. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset,
-    bool match, bool update, ErrorContext* ctx, TRAPS) const;
+    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
   // Match and/or update current_frame to the frame in stackmap table with
   // specified offset and frame index. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
-    bool match, bool update, ErrorContext* ctx, TRAPS) const;
+    bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const;
 
   // Check jump instructions. Make sure there are no uninitialized
   // instances on backward branch.
@@ -90,10 +90,6 @@
   // Returns the frame array index where the frame with offset is stored.
   int get_index_from_offset(int32_t offset) const;
 
-  // Make sure that there's no uninitialized object exist on backward branch.
-  void check_new_object(
-    const StackMapFrame* frame, int32_t target, TRAPS) const;
-
   void print_on(outputStream* str) const;
 };
 
diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp
index 748a82e..5bbe1e2 100644
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp
@@ -36,6 +36,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "utilities/hashtable.inline.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/g1StringDedup.hpp"
 #endif
 
@@ -73,9 +74,9 @@
 void SymbolTable::initialize_symbols(int arena_alloc_size) {
   // Initialize the arena for global symbols, size passed in depends on CDS.
   if (arena_alloc_size == 0) {
-    _arena = new (mtSymbol) Arena();
+    _arena = new (mtSymbol) Arena(mtSymbol);
   } else {
-    _arena = new (mtSymbol) Arena(arena_alloc_size);
+    _arena = new (mtSymbol) Arena(mtSymbol, arena_alloc_size);
   }
 }
 
@@ -704,11 +705,26 @@
   return lookup(chars, length);
 }
 
+// Tell the GC that this string was looked up in the StringTable.
+static void ensure_string_alive(oop string) {
+  // A lookup in the StringTable could return an object that was previously
+  // considered dead. The SATB part of G1 needs to get notified about this
+  // potential resurrection, otherwise the marking might not find the object.
+#if INCLUDE_ALL_GCS
+  if (UseG1GC && string != NULL) {
+    G1SATBCardTableModRefBS::enqueue(string);
+  }
+#endif
+}
 
 oop StringTable::lookup(jchar* name, int len) {
   unsigned int hash = hash_string(name, len);
   int index = the_table()->hash_to_index(hash);
-  return the_table()->lookup(index, name, len, hash);
+  oop string = the_table()->lookup(index, name, len, hash);
+
+  ensure_string_alive(string);
+
+  return string;
 }
 
 
@@ -719,7 +735,10 @@
   oop found_string = the_table()->lookup(index, name, len, hashValue);
 
   // Found
-  if (found_string != NULL) return found_string;
+  if (found_string != NULL) {
+    ensure_string_alive(found_string);
+    return found_string;
+  }
 
   debug_only(StableMemoryChecker smc(name, len * sizeof(name[0])));
   assert(!Universe::heap()->is_in_reserved(name),
@@ -744,11 +763,17 @@
 
   // Grab the StringTable_lock before getting the_table() because it could
   // change at safepoint.
-  MutexLocker ml(StringTable_lock, THREAD);
+  oop added_or_found;
+  {
+    MutexLocker ml(StringTable_lock, THREAD);
+    // Otherwise, add to symbol to table
+    added_or_found = the_table()->basic_add(index, string, name, len,
+                                  hashValue, CHECK_NULL);
+  }
 
-  // Otherwise, add to symbol to table
-  return the_table()->basic_add(index, string, name, len,
-                                hashValue, CHECK_NULL);
+  ensure_string_alive(added_or_found);
+
+  return added_or_found;
 }
 
 oop StringTable::intern(Symbol* symbol, TRAPS) {
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp
index 3b0cf3c..1f20960 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp
@@ -52,6 +52,7 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/signature.hpp"
 #include "services/classLoadingService.hpp"
 #include "services/threadService.hpp"
@@ -1612,13 +1613,7 @@
 // system dictionary and follows the remaining classes' contents.
 
 void SystemDictionary::always_strong_oops_do(OopClosure* blk) {
-  blk->do_oop(&_java_system_loader);
-  blk->do_oop(&_system_loader_lock_obj);
-
-  dictionary()->always_strong_oops_do(blk);
-
-  // Visit extra methods
-  invoke_method_table()->oops_do(blk);
+  roots_oops_do(blk, NULL);
 }
 
 void SystemDictionary::always_strong_classes_do(KlassClosure* closure) {
@@ -1667,10 +1662,9 @@
 // Note: anonymous classes are not in the SD.
 bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
   // First, mark for unload all ClassLoaderData referencing a dead class loader.
-  bool has_dead_loaders = ClassLoaderDataGraph::do_unloading(is_alive);
-  bool unloading_occurred = false;
-  if (has_dead_loaders) {
-    unloading_occurred = dictionary()->do_unloading();
+  bool unloading_occurred = ClassLoaderDataGraph::do_unloading(is_alive);
+  if (unloading_occurred) {
+    dictionary()->do_unloading();
     constraints()->purge_loader_constraints();
     resolution_errors()->purge_resolution_errors();
   }
@@ -1685,6 +1679,17 @@
   return unloading_occurred;
 }
 
+void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
+  strong->do_oop(&_java_system_loader);
+  strong->do_oop(&_system_loader_lock_obj);
+
+  // Adjust dictionary
+  dictionary()->roots_oops_do(strong, weak);
+
+  // Visit extra methods
+  invoke_method_table()->oops_do(strong);
+}
+
 void SystemDictionary::oops_do(OopClosure* f) {
   f->do_oop(&_java_system_loader);
   f->do_oop(&_system_loader_lock_obj);
diff --git a/hotspot/src/share/vm/classfile/systemDictionary.hpp b/hotspot/src/share/vm/classfile/systemDictionary.hpp
index 097a1e0..1b9c29e 100644
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp
@@ -335,6 +335,7 @@
 
   // Applies "f->do_oop" to all root oops in the system dictionary.
   static void oops_do(OopClosure* f);
+  static void roots_oops_do(OopClosure* strong, OopClosure* weak);
 
   // System loader lock
   static oop system_loader_lock()           { return _system_loader_lock_obj; }
diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp
index 1791127..a45ce20 100644
--- a/hotspot/src/share/vm/classfile/verifier.cpp
+++ b/hotspot/src/share/vm/classfile/verifier.cpp
@@ -43,7 +43,7 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/javaCalls.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 #ifdef TARGET_ARCH_x86
 # include "bytes_x86.hpp"
@@ -634,8 +634,6 @@
                                 // flow from current instruction to the next
                                 // instruction in sequence
 
-  set_furthest_jump(0);
-
   Bytecodes::Code opcode;
   while (!bcs.is_last_bytecode()) {
     // Check for recursive re-verification before each bytecode.
@@ -1794,7 +1792,7 @@
       // If matched, current_frame will be updated by this method.
       bool matches = stackmap_table->match_stackmap(
         current_frame, this_offset, stackmap_index,
-        !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0));
+        !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0));
       if (!matches) {
         // report type error
         verify_error(ctx, "Instruction type does not match stack map");
@@ -1841,7 +1839,7 @@
       }
       ErrorContext ctx;
       bool matches = stackmap_table->match_stackmap(
-        new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this));
+        new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this));
       if (!matches) {
         verify_error(ctx, "Stack map does not match the one at "
             "exception handler %d", handler_pc);
@@ -2233,6 +2231,181 @@
   }
 }
 
+// Look at the method's handlers.  If the bci is in the handler's try block
+// then check if the handler_pc is already on the stack.  If not, push it.
+void ClassVerifier::push_handlers(ExceptionTable* exhandlers,
+                                  GrowableArray<u4>* handler_stack,
+                                  u4 bci) {
+  int exlength = exhandlers->length();
+  for(int x = 0; x < exlength; x++) {
+    if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) {
+      handler_stack->append_if_missing(exhandlers->handler_pc(x));
+    }
+  }
+}
+
+// Return TRUE if all code paths starting with start_bc_offset end in
+// bytecode athrow or loop.
+bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) {
+  ResourceMark rm;
+  // Create bytecode stream.
+  RawBytecodeStream bcs(method());
+  u4 code_length = method()->code_size();
+  bcs.set_start(start_bc_offset);
+  u4 target;
+  // Create stack for storing bytecode start offsets for if* and *switch.
+  GrowableArray<u4>* bci_stack = new GrowableArray<u4>(30);
+  // Create stack for handlers for try blocks containing this handler.
+  GrowableArray<u4>* handler_stack = new GrowableArray<u4>(30);
+  // Create list of visited branch opcodes (goto* and if*).
+  GrowableArray<u4>* visited_branches = new GrowableArray<u4>(30);
+  ExceptionTable exhandlers(_method());
+
+  while (true) {
+    if (bcs.is_last_bytecode()) {
+      // if no more starting offsets to parse or if at the end of the
+      // method then return false.
+      if ((bci_stack->is_empty()) || ((u4)bcs.end_bci() == code_length))
+        return false;
+      // Pop a bytecode starting offset and scan from there.
+      bcs.set_start(bci_stack->pop());
+    }
+    Bytecodes::Code opcode = bcs.raw_next();
+    u4 bci = bcs.bci();
+
+    // If the bytecode is in a TRY block, push its handlers so they
+    // will get parsed.
+    push_handlers(&exhandlers, handler_stack, bci);
+
+    switch (opcode) {
+      case Bytecodes::_if_icmpeq:
+      case Bytecodes::_if_icmpne:
+      case Bytecodes::_if_icmplt:
+      case Bytecodes::_if_icmpge:
+      case Bytecodes::_if_icmpgt:
+      case Bytecodes::_if_icmple:
+      case Bytecodes::_ifeq:
+      case Bytecodes::_ifne:
+      case Bytecodes::_iflt:
+      case Bytecodes::_ifge:
+      case Bytecodes::_ifgt:
+      case Bytecodes::_ifle:
+      case Bytecodes::_if_acmpeq:
+      case Bytecodes::_if_acmpne:
+      case Bytecodes::_ifnull:
+      case Bytecodes::_ifnonnull:
+        target = bcs.dest();
+        if (visited_branches->contains(bci)) {
+          if (bci_stack->is_empty()) return true;
+          // Pop a bytecode starting offset and scan from there.
+          bcs.set_start(bci_stack->pop());
+        } else {
+          if (target > bci) { // forward branch
+            if (target >= code_length) return false;
+            // Push the branch target onto the stack.
+            bci_stack->push(target);
+            // then, scan bytecodes starting with next.
+            bcs.set_start(bcs.next_bci());
+          } else { // backward branch
+            // Push bytecode offset following backward branch onto the stack.
+            bci_stack->push(bcs.next_bci());
+            // Check bytecodes starting with branch target.
+            bcs.set_start(target);
+          }
+          // Record target so we don't branch here again.
+          visited_branches->append(bci);
+        }
+        break;
+
+      case Bytecodes::_goto:
+      case Bytecodes::_goto_w:
+        target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w());
+        if (visited_branches->contains(bci)) {
+          if (bci_stack->is_empty()) return true;
+          // Been here before, pop new starting offset from stack.
+          bcs.set_start(bci_stack->pop());
+        } else {
+          if (target >= code_length) return false;
+          // Continue scanning from the target onward.
+          bcs.set_start(target);
+          // Record target so we don't branch here again.
+          visited_branches->append(bci);
+        }
+        break;
+
+      // Check that all switch alternatives end in 'athrow' bytecodes. Since it
+      // is  difficult to determine where each switch alternative ends, parse
+      // each switch alternative until either hit a 'return', 'athrow', or reach
+      // the end of the method's bytecodes.  This is gross but should be okay
+      // because:
+      // 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit
+      //    constructor invocations should be rare.
+      // 2. if each switch alternative ends in an athrow then the parsing should be
+      //    short.  If there is no athrow then it is bogus code, anyway.
+      case Bytecodes::_lookupswitch:
+      case Bytecodes::_tableswitch:
+        {
+          address aligned_bcp = (address) round_to((intptr_t)(bcs.bcp() + 1), jintSize);
+          u4 default_offset = Bytes::get_Java_u4(aligned_bcp) + bci;
+          int keys, delta;
+          if (opcode == Bytecodes::_tableswitch) {
+            jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize);
+            jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize);
+            // This is invalid, but let the regular bytecode verifier
+            // report this because the user will get a better error message.
+            if (low > high) return true;
+            keys = high - low + 1;
+            delta = 1;
+          } else {
+            keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize);
+            delta = 2;
+          }
+          // Invalid, let the regular bytecode verifier deal with it.
+          if (keys < 0) return true;
+
+          // Push the offset of the next bytecode onto the stack.
+          bci_stack->push(bcs.next_bci());
+
+          // Push the switch alternatives onto the stack.
+          for (int i = 0; i < keys; i++) {
+            u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize);
+            if (target > code_length) return false;
+            bci_stack->push(target);
+          }
+
+          // Start bytecode parsing for the switch at the default alternative.
+          if (default_offset > code_length) return false;
+          bcs.set_start(default_offset);
+          break;
+        }
+
+      case Bytecodes::_return:
+        return false;
+
+      case Bytecodes::_athrow:
+        {
+          if (bci_stack->is_empty()) {
+            if (handler_stack->is_empty()) {
+              return true;
+            } else {
+              // Parse the catch handlers for try blocks containing athrow.
+              bcs.set_start(handler_stack->pop());
+            }
+          } else {
+            // Pop a bytecode offset and starting scanning from there.
+            bcs.set_start(bci_stack->pop());
+          }
+        }
+        break;
+
+      default:
+        ;
+    } // end switch
+  } // end while loop
+
+  return false;
+}
+
 void ClassVerifier::verify_invoke_init(
     RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type,
     StackMapFrame* current_frame, u4 code_length, bool *this_uninit,
@@ -2252,25 +2425,26 @@
       return;
     }
 
-    // Make sure that this call is not jumped over.
-    if (bci < furthest_jump()) {
-      verify_error(ErrorContext::bad_code(bci),
-                   "Bad <init> method call from inside of a branch");
-      return;
-    }
-
-    // Make sure that this call is not done from within a TRY block because
-    // that can result in returning an incomplete object.  Simply checking
-    // (bci >= start_pc) also ensures that this call is not done after a TRY
-    // block.  That is also illegal because this call must be the first Java
-    // statement in the constructor.
+    // Check if this call is done from inside of a TRY block.  If so, make
+    // sure that all catch clause paths end in a throw.  Otherwise, this
+    // can result in returning an incomplete object.
     ExceptionTable exhandlers(_method());
     int exlength = exhandlers.length();
     for(int i = 0; i < exlength; i++) {
-      if (bci >= exhandlers.start_pc(i)) {
-        verify_error(ErrorContext::bad_code(bci),
-                     "Bad <init> method call from after the start of a try block");
-        return;
+      u2 start_pc = exhandlers.start_pc(i);
+      u2 end_pc = exhandlers.end_pc(i);
+
+      if (bci >= start_pc && bci < end_pc) {
+        if (!ends_in_athrow(exhandlers.handler_pc(i))) {
+          verify_error(ErrorContext::bad_code(bci),
+            "Bad <init> method call from after the start of a try block");
+          return;
+        } else if (VerboseVerification) {
+          ResourceMark rm;
+          tty->print_cr(
+            "Survived call to ends_in_athrow(): %s",
+                        current_class()->name()->as_C_string());
+        }
       }
     }
 
diff --git a/hotspot/src/share/vm/classfile/verifier.hpp b/hotspot/src/share/vm/classfile/verifier.hpp
index 6eecd4b..4c8b589 100644
--- a/hotspot/src/share/vm/classfile/verifier.hpp
+++ b/hotspot/src/share/vm/classfile/verifier.hpp
@@ -30,6 +30,7 @@
 #include "oops/klass.hpp"
 #include "oops/method.hpp"
 #include "runtime/handles.hpp"
+#include "utilities/growableArray.hpp"
 #include "utilities/exceptions.hpp"
 
 // The verifier class
@@ -258,9 +259,6 @@
 
   ErrorContext _error_context;  // contains information about an error
 
-  // Used to detect illegal jumps over calls to super() nd this() in ctors.
-  int32_t _furthest_jump;
-
   void verify_method(methodHandle method, TRAPS);
   char* generate_code_data(methodHandle m, u4 code_length, TRAPS);
   void verify_exception_handler_table(u4 code_length, char* code_data,
@@ -306,6 +304,16 @@
     StackMapFrame* current_frame, u4 code_length, bool* this_uninit,
     constantPoolHandle cp, TRAPS);
 
+  // Used by ends_in_athrow() to push all handlers that contain bci onto
+  // the handler_stack, if the handler is not already on the stack.
+  void push_handlers(ExceptionTable* exhandlers,
+                     GrowableArray<u4>* handler_stack,
+                     u4 bci);
+
+  // Returns true if all paths starting with start_bc_offset end in athrow
+  // bytecode or loop.
+  bool ends_in_athrow(u4 start_bc_offset);
+
   void verify_invoke_instructions(
     RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
     bool* this_uninit, VerificationType return_type,
@@ -407,19 +415,6 @@
 
   TypeOrigin ref_ctx(const char* str, TRAPS);
 
-  // Keep track of the furthest branch done in a method to make sure that
-  // there are no branches over calls to super() or this() from inside of
-  // a constructor.
-  int32_t furthest_jump() { return _furthest_jump; }
-
-  void set_furthest_jump(int32_t target) {
-    _furthest_jump = target;
-  }
-
-  void update_furthest_jump(int32_t target) {
-    if (target > _furthest_jump) _furthest_jump = target;
-  }
-
 };
 
 inline int ClassVerifier::change_sig_to_verificationType(
diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp
index f923c7c..1ce7c47 100644
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp
@@ -789,6 +789,26 @@
    do_name(     decrypt_name,                                      "decrypt")                                           \
    do_signature(byteArray_int_int_byteArray_int_signature,         "([BII[BI)I")                                        \
                                                                                                                         \
+  /* support for sun.security.provider.SHA */                                                                           \
+  do_class(sun_security_provider_sha,                              "sun/security/provider/SHA")                         \
+  do_intrinsic(_sha_implCompress, sun_security_provider_sha, implCompress_name, implCompress_signature, F_R)            \
+   do_name(     implCompress_name,                                 "implCompress")                                      \
+   do_signature(implCompress_signature,                            "([BI)V")                                            \
+                                                                                                                        \
+  /* support for sun.security.provider.SHA2 */                                                                          \
+  do_class(sun_security_provider_sha2,                             "sun/security/provider/SHA2")                        \
+  do_intrinsic(_sha2_implCompress, sun_security_provider_sha2, implCompress_name, implCompress_signature, F_R)          \
+                                                                                                                        \
+  /* support for sun.security.provider.SHA5 */                                                                          \
+  do_class(sun_security_provider_sha5,                             "sun/security/provider/SHA5")                        \
+  do_intrinsic(_sha5_implCompress, sun_security_provider_sha5, implCompress_name, implCompress_signature, F_R)          \
+                                                                                                                        \
+  /* support for sun.security.provider.DigestBase */                                                                    \
+  do_class(sun_security_provider_digestbase,                       "sun/security/provider/DigestBase")                  \
+  do_intrinsic(_digestBase_implCompressMB, sun_security_provider_digestbase, implCompressMB_name, implCompressMB_signature, F_R)   \
+   do_name(     implCompressMB_name,                               "implCompressMultiBlock")                            \
+   do_signature(implCompressMB_signature,                          "([BII)I")                                           \
+                                                                                                                        \
   /* support for java.util.zip */                                                                                       \
   do_class(java_util_zip_CRC32,           "java/util/zip/CRC32")                                                        \
   do_intrinsic(_updateCRC32,               java_util_zip_CRC32,   update_name, int2_int_signature,               F_SN)  \
diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp
index 9ba6ef0..72f708e 100644
--- a/hotspot/src/share/vm/code/codeCache.cpp
+++ b/hotspot/src/share/vm/code/codeCache.cpp
@@ -337,6 +337,11 @@
 // Walk the list of methods which might contain non-perm oops.
 void CodeCache::scavenge_root_nmethods_do(CodeBlobClosure* f) {
   assert_locked_or_safepoint(CodeCache_lock);
+
+  if (UseG1GC) {
+    return;
+  }
+
   debug_only(mark_scavenge_root_nmethods());
 
   for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
@@ -362,6 +367,11 @@
 
 void CodeCache::add_scavenge_root_nmethod(nmethod* nm) {
   assert_locked_or_safepoint(CodeCache_lock);
+
+  if (UseG1GC) {
+    return;
+  }
+
   nm->set_on_scavenge_root_list();
   nm->set_scavenge_root_link(_scavenge_root_nmethods);
   set_scavenge_root_nmethods(nm);
@@ -370,6 +380,11 @@
 
 void CodeCache::drop_scavenge_root_nmethod(nmethod* nm) {
   assert_locked_or_safepoint(CodeCache_lock);
+
+  if (UseG1GC) {
+    return;
+  }
+
   print_trace("drop_scavenge_root", nm);
   nmethod* last = NULL;
   nmethod* cur = scavenge_root_nmethods();
@@ -391,6 +406,11 @@
 
 void CodeCache::prune_scavenge_root_nmethods() {
   assert_locked_or_safepoint(CodeCache_lock);
+
+  if (UseG1GC) {
+    return;
+  }
+
   debug_only(mark_scavenge_root_nmethods());
 
   nmethod* last = NULL;
@@ -423,6 +443,10 @@
 
 #ifndef PRODUCT
 void CodeCache::asserted_non_scavengable_nmethods_do(CodeBlobClosure* f) {
+  if (UseG1GC) {
+    return;
+  }
+
   // While we are here, verify the integrity of the list.
   mark_scavenge_root_nmethods();
   for (nmethod* cur = scavenge_root_nmethods(); cur != NULL; cur = cur->scavenge_root_link()) {
@@ -463,9 +487,36 @@
 }
 #endif //PRODUCT
 
+void CodeCache::verify_clean_inline_caches() {
+#ifdef ASSERT
+  FOR_ALL_ALIVE_BLOBS(cb) {
+    if (cb->is_nmethod()) {
+      nmethod* nm = (nmethod*)cb;
+      assert(!nm->is_unloaded(), "Tautology");
+      nm->verify_clean_inline_caches();
+      nm->verify();
+    }
+  }
+#endif
+}
+
+void CodeCache::verify_icholder_relocations() {
+#ifdef ASSERT
+  // make sure that we aren't leaking icholders
+  int count = 0;
+  FOR_ALL_BLOBS(cb) {
+    if (cb->is_nmethod()) {
+      nmethod* nm = (nmethod*)cb;
+      count += nm->verify_icholder_relocations();
+    }
+  }
+
+  assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
+         CompiledICHolder::live_count(), "must agree");
+#endif
+}
 
 void CodeCache::gc_prologue() {
-  assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_epilogue must be called");
 }
 
 void CodeCache::gc_epilogue() {
@@ -478,41 +529,15 @@
         nm->cleanup_inline_caches();
       }
       DEBUG_ONLY(nm->verify());
-      nm->fix_oop_relocations();
+      DEBUG_ONLY(nm->verify_oop_relocations());
     }
   }
   set_needs_cache_clean(false);
   prune_scavenge_root_nmethods();
-  assert(!nmethod::oops_do_marking_is_active(), "oops_do_marking_prologue must be called");
 
-#ifdef ASSERT
-  // make sure that we aren't leaking icholders
-  int count = 0;
-  FOR_ALL_BLOBS(cb) {
-    if (cb->is_nmethod()) {
-      RelocIterator iter((nmethod*)cb);
-      while(iter.next()) {
-        if (iter.type() == relocInfo::virtual_call_type) {
-          if (CompiledIC::is_icholder_call_site(iter.virtual_call_reloc())) {
-            CompiledIC *ic = CompiledIC_at(iter.reloc());
-            if (TraceCompiledIC) {
-              tty->print("noticed icholder " INTPTR_FORMAT " ", p2i(ic->cached_icholder()));
-              ic->print();
-            }
-            assert(ic->cached_icholder() != NULL, "must be non-NULL");
-            count++;
-          }
-        }
-      }
-    }
-  }
-
-  assert(count + InlineCacheBuffer::pending_icholder_count() + CompiledICHolder::live_not_claimed_count() ==
-         CompiledICHolder::live_count(), "must agree");
-#endif
+  verify_icholder_relocations();
 }
 
-
 void CodeCache::verify_oops() {
   MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
   VerifyOopClosure voc;
diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp
index e190b11..966304f 100644
--- a/hotspot/src/share/vm/code/codeCache.hpp
+++ b/hotspot/src/share/vm/code/codeCache.hpp
@@ -134,10 +134,6 @@
   // to) any unmarked codeBlobs in the cache.  Sets "marked_for_unloading"
   // to "true" iff some code got unloaded.
   static void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
-  static void oops_do(OopClosure* f) {
-    CodeBlobToOopClosure oopc(f, /*do_marking=*/ false);
-    blobs_do(&oopc);
-  }
   static void asserted_non_scavengable_nmethods_do(CodeBlobClosure* f = NULL) PRODUCT_RETURN;
   static void scavenge_root_nmethods_do(CodeBlobClosure* f);
 
@@ -172,6 +168,9 @@
   static void set_needs_cache_clean(bool v)      { _needs_cache_clean = v;    }
   static void clear_inline_caches();             // clear all inline caches
 
+  static void verify_clean_inline_caches();
+  static void verify_icholder_relocations();
+
   // Deoptimization
   static int  mark_for_deoptimization(DepChange& changes);
 #ifdef HOTSWAP
diff --git a/hotspot/src/share/vm/code/compiledIC.cpp b/hotspot/src/share/vm/code/compiledIC.cpp
index 9a03816..25ef072 100644
--- a/hotspot/src/share/vm/code/compiledIC.cpp
+++ b/hotspot/src/share/vm/code/compiledIC.cpp
@@ -99,13 +99,13 @@
   }
 
   {
-  MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+    MutexLockerEx pl(SafepointSynchronize::is_at_safepoint() ? NULL : Patching_lock, Mutex::_no_safepoint_check_flag);
 #ifdef ASSERT
-  CodeBlob* cb = CodeCache::find_blob_unsafe(_ic_call);
-  assert(cb != NULL && cb->is_nmethod(), "must be nmethod");
+    CodeBlob* cb = CodeCache::find_blob_unsafe(_ic_call);
+    assert(cb != NULL && cb->is_nmethod(), "must be nmethod");
 #endif
-  _ic_call->set_destination_mt_safe(entry_point);
-}
+     _ic_call->set_destination_mt_safe(entry_point);
+  }
 
   if (is_optimized() || is_icstub) {
     // Optimized call sites don't have a cache value and ICStub call
@@ -159,6 +159,50 @@
 //-----------------------------------------------------------------------------
 // High-level access to an inline cache. Guaranteed to be MT-safe.
 
+void CompiledIC::initialize_from_iter(RelocIterator* iter) {
+  assert(iter->addr() == _ic_call->instruction_address(), "must find ic_call");
+
+  if (iter->type() == relocInfo::virtual_call_type) {
+    virtual_call_Relocation* r = iter->virtual_call_reloc();
+    _is_optimized = false;
+    _value = nativeMovConstReg_at(r->cached_value());
+  } else {
+    assert(iter->type() == relocInfo::opt_virtual_call_type, "must be a virtual call");
+    _is_optimized = true;
+    _value = NULL;
+  }
+}
+
+CompiledIC::CompiledIC(nmethod* nm, NativeCall* call)
+  : _ic_call(call)
+{
+  address ic_call = _ic_call->instruction_address();
+
+  assert(ic_call != NULL, "ic_call address must be set");
+  assert(nm != NULL, "must pass nmethod");
+  assert(nm->contains(ic_call), "must be in nmethod");
+
+  // Search for the ic_call at the given address.
+  RelocIterator iter(nm, ic_call, ic_call+1);
+  bool ret = iter.next();
+  assert(ret == true, "relocInfo must exist at this address");
+  assert(iter.addr() == ic_call, "must find ic_call");
+
+  initialize_from_iter(&iter);
+}
+
+CompiledIC::CompiledIC(RelocIterator* iter)
+  : _ic_call(nativeCall_at(iter->addr()))
+{
+  address ic_call = _ic_call->instruction_address();
+
+  nmethod* nm = iter->code();
+  assert(ic_call != NULL, "ic_call address must be set");
+  assert(nm != NULL, "must pass nmethod");
+  assert(nm->contains(ic_call), "must be in nmethod");
+
+  initialize_from_iter(iter);
+}
 
 bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) {
   assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "");
@@ -485,7 +529,7 @@
 void CompiledStaticCall::set_to_clean() {
   assert (CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), "mt unsafe call");
   // Reset call site
-  MutexLockerEx pl(Patching_lock, Mutex::_no_safepoint_check_flag);
+  MutexLockerEx pl(SafepointSynchronize::is_at_safepoint() ? NULL : Patching_lock, Mutex::_no_safepoint_check_flag);
 #ifdef ASSERT
   CodeBlob* cb = CodeCache::find_blob_unsafe(this);
   assert(cb != NULL && cb->is_nmethod(), "must be nmethod");
diff --git a/hotspot/src/share/vm/code/compiledIC.hpp b/hotspot/src/share/vm/code/compiledIC.hpp
index 0d522af..f2207cc 100644
--- a/hotspot/src/share/vm/code/compiledIC.hpp
+++ b/hotspot/src/share/vm/code/compiledIC.hpp
@@ -150,6 +150,9 @@
   bool          _is_optimized;  // an optimized virtual call (i.e., no compiled IC)
 
   CompiledIC(nmethod* nm, NativeCall* ic_call);
+  CompiledIC(RelocIterator* iter);
+
+  void initialize_from_iter(RelocIterator* iter);
 
   static bool is_icholder_entry(address entry);
 
@@ -183,6 +186,7 @@
   friend CompiledIC* CompiledIC_before(nmethod* nm, address return_addr);
   friend CompiledIC* CompiledIC_at(nmethod* nm, address call_site);
   friend CompiledIC* CompiledIC_at(Relocation* call_site);
+  friend CompiledIC* CompiledIC_at(RelocIterator* reloc_iter);
 
   // This is used to release CompiledICHolder*s from nmethods that
   // are about to be freed.  The callsite might contain other stale
@@ -263,6 +267,13 @@
   return c_ic;
 }
 
+inline CompiledIC* CompiledIC_at(RelocIterator* reloc_iter) {
+  assert(reloc_iter->type() == relocInfo::virtual_call_type ||
+      reloc_iter->type() == relocInfo::opt_virtual_call_type, "wrong reloc. info");
+  CompiledIC* c_ic = new CompiledIC(reloc_iter);
+  c_ic->verify();
+  return c_ic;
+}
 
 //-----------------------------------------------------------------------------
 // The CompiledStaticCall represents a call to a static method in the compiled
diff --git a/hotspot/src/share/vm/code/dependencies.cpp b/hotspot/src/share/vm/code/dependencies.cpp
index 778efe8..539df17 100644
--- a/hotspot/src/share/vm/code/dependencies.cpp
+++ b/hotspot/src/share/vm/code/dependencies.cpp
@@ -32,6 +32,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/thread.inline.hpp"
 #include "utilities/copy.hpp"
 
 
@@ -406,56 +407,66 @@
 // for the sake of the compiler log, print out current dependencies:
 void Dependencies::log_all_dependencies() {
   if (log() == NULL)  return;
-  ciBaseObject* args[max_arg_count];
+  ResourceMark rm;
   for (int deptv = (int)FIRST_TYPE; deptv < (int)TYPE_LIMIT; deptv++) {
     DepType dept = (DepType)deptv;
     GrowableArray<ciBaseObject*>* deps = _deps[dept];
-    if (deps->length() == 0)  continue;
+    int deplen = deps->length();
+    if (deplen == 0) {
+      continue;
+    }
     int stride = dep_args(dept);
+    GrowableArray<ciBaseObject*>* ciargs = new GrowableArray<ciBaseObject*>(stride);
     for (int i = 0; i < deps->length(); i += stride) {
       for (int j = 0; j < stride; j++) {
         // flush out the identities before printing
-        args[j] = deps->at(i+j);
+        ciargs->push(deps->at(i+j));
       }
-      write_dependency_to(log(), dept, stride, args);
+      write_dependency_to(log(), dept, ciargs);
+      ciargs->clear();
     }
+    guarantee(deplen == deps->length(), "deps array cannot grow inside nested ResoureMark scope");
   }
 }
 
 void Dependencies::write_dependency_to(CompileLog* log,
                                        DepType dept,
-                                       int nargs, DepArgument args[],
+                                       GrowableArray<DepArgument>* args,
                                        Klass* witness) {
   if (log == NULL) {
     return;
   }
+  ResourceMark rm;
   ciEnv* env = ciEnv::current();
-  ciBaseObject* ciargs[max_arg_count];
-  assert(nargs <= max_arg_count, "oob");
-  for (int j = 0; j < nargs; j++) {
-    if (args[j].is_oop()) {
-      ciargs[j] = env->get_object(args[j].oop_value());
+  GrowableArray<ciBaseObject*>* ciargs = new GrowableArray<ciBaseObject*>(args->length());
+  for (GrowableArrayIterator<DepArgument> it = args->begin(); it != args->end(); ++it) {
+    DepArgument arg = *it;
+    if (arg.is_oop()) {
+      ciargs->push(env->get_object(arg.oop_value()));
     } else {
-      ciargs[j] = env->get_metadata(args[j].metadata_value());
+      ciargs->push(env->get_metadata(arg.metadata_value()));
     }
   }
-  Dependencies::write_dependency_to(log, dept, nargs, ciargs, witness);
+  int argslen = ciargs->length();
+  Dependencies::write_dependency_to(log, dept, ciargs, witness);
+  guarantee(argslen == ciargs->length(), "ciargs array cannot grow inside nested ResoureMark scope");
 }
 
 void Dependencies::write_dependency_to(CompileLog* log,
                                        DepType dept,
-                                       int nargs, ciBaseObject* args[],
+                                       GrowableArray<ciBaseObject*>* args,
                                        Klass* witness) {
-  if (log == NULL)  return;
-  assert(nargs <= max_arg_count, "oob");
-  int argids[max_arg_count];
-  int ctxkj = dep_context_arg(dept);  // -1 if no context arg
-  int j;
-  for (j = 0; j < nargs; j++) {
-    if (args[j]->is_object()) {
-      argids[j] = log->identify(args[j]->as_object());
+  if (log == NULL) {
+    return;
+  }
+  ResourceMark rm;
+  GrowableArray<int>* argids = new GrowableArray<int>(args->length());
+  for (GrowableArrayIterator<ciBaseObject*> it = args->begin(); it != args->end(); ++it) {
+    ciBaseObject* obj = *it;
+    if (obj->is_object()) {
+      argids->push(log->identify(obj->as_object()));
     } else {
-      argids[j] = log->identify(args[j]->as_metadata());
+      argids->push(log->identify(obj->as_metadata()));
     }
   }
   if (witness != NULL) {
@@ -464,16 +475,17 @@
     log->begin_elem("dependency");
   }
   log->print(" type='%s'", dep_name(dept));
-  if (ctxkj >= 0) {
-    log->print(" ctxk='%d'", argids[ctxkj]);
+  const int ctxkj = dep_context_arg(dept);  // -1 if no context arg
+  if (ctxkj >= 0 && ctxkj < argids->length()) {
+    log->print(" ctxk='%d'", argids->at(ctxkj));
   }
   // write remaining arguments, if any.
-  for (j = 0; j < nargs; j++) {
+  for (int j = 0; j < argids->length(); j++) {
     if (j == ctxkj)  continue;  // already logged
     if (j == 1) {
-      log->print(  " x='%d'",    argids[j]);
+      log->print(  " x='%d'",    argids->at(j));
     } else {
-      log->print(" x%d='%d'", j, argids[j]);
+      log->print(" x%d='%d'", j, argids->at(j));
     }
   }
   if (witness != NULL) {
@@ -485,9 +497,12 @@
 
 void Dependencies::write_dependency_to(xmlStream* xtty,
                                        DepType dept,
-                                       int nargs, DepArgument args[],
+                                       GrowableArray<DepArgument>* args,
                                        Klass* witness) {
-  if (xtty == NULL)  return;
+  if (xtty == NULL) {
+    return;
+  }
+  ResourceMark rm;
   ttyLocker ttyl;
   int ctxkj = dep_context_arg(dept);  // -1 if no context arg
   if (witness != NULL) {
@@ -497,23 +512,24 @@
   }
   xtty->print(" type='%s'", dep_name(dept));
   if (ctxkj >= 0) {
-    xtty->object("ctxk", args[ctxkj].metadata_value());
+    xtty->object("ctxk", args->at(ctxkj).metadata_value());
   }
   // write remaining arguments, if any.
-  for (int j = 0; j < nargs; j++) {
+  for (int j = 0; j < args->length(); j++) {
     if (j == ctxkj)  continue;  // already logged
+    DepArgument arg = args->at(j);
     if (j == 1) {
-      if (args[j].is_oop()) {
-        xtty->object("x", args[j].oop_value());
+      if (arg.is_oop()) {
+        xtty->object("x", arg.oop_value());
       } else {
-        xtty->object("x", args[j].metadata_value());
+        xtty->object("x", arg.metadata_value());
       }
     } else {
       char xn[10]; sprintf(xn, "x%d", j);
-      if (args[j].is_oop()) {
-        xtty->object(xn, args[j].oop_value());
+      if (arg.is_oop()) {
+        xtty->object(xn, arg.oop_value());
       } else {
-        xtty->object(xn, args[j].metadata_value());
+        xtty->object(xn, arg.metadata_value());
       }
     }
   }
@@ -524,7 +540,7 @@
   xtty->end_elem();
 }
 
-void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
+void Dependencies::print_dependency(DepType dept, GrowableArray<DepArgument>* args,
                                     Klass* witness) {
   ResourceMark rm;
   ttyLocker ttyl;   // keep the following output all in one block
@@ -533,8 +549,8 @@
                 dep_name(dept));
   // print arguments
   int ctxkj = dep_context_arg(dept);  // -1 if no context arg
-  for (int j = 0; j < nargs; j++) {
-    DepArgument arg = args[j];
+  for (int j = 0; j < args->length(); j++) {
+    DepArgument arg = args->at(j);
     bool put_star = false;
     if (arg.is_null())  continue;
     const char* what;
@@ -570,31 +586,33 @@
 void Dependencies::DepStream::log_dependency(Klass* witness) {
   if (_deps == NULL && xtty == NULL)  return;  // fast cutout for runtime
   ResourceMark rm;
-  int nargs = argument_count();
-  DepArgument args[max_arg_count];
+  const int nargs = argument_count();
+  GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
   for (int j = 0; j < nargs; j++) {
     if (type() == call_site_target_value) {
-      args[j] = argument_oop(j);
+      args->push(argument_oop(j));
     } else {
-      args[j] = argument(j);
+      args->push(argument(j));
     }
   }
+  int argslen = args->length();
   if (_deps != NULL && _deps->log() != NULL) {
-    Dependencies::write_dependency_to(_deps->log(),
-                                      type(), nargs, args, witness);
+    Dependencies::write_dependency_to(_deps->log(), type(), args, witness);
   } else {
-    Dependencies::write_dependency_to(xtty,
-                                      type(), nargs, args, witness);
+    Dependencies::write_dependency_to(xtty, type(), args, witness);
   }
+  guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
 }
 
 void Dependencies::DepStream::print_dependency(Klass* witness, bool verbose) {
+  ResourceMark rm;
   int nargs = argument_count();
-  DepArgument args[max_arg_count];
+  GrowableArray<DepArgument>* args = new GrowableArray<DepArgument>(nargs);
   for (int j = 0; j < nargs; j++) {
-    args[j] = argument(j);
+    args->push(argument(j));
   }
-  Dependencies::print_dependency(type(), nargs, args, witness);
+  int argslen = args->length();
+  Dependencies::print_dependency(type(), args, witness);
   if (verbose) {
     if (_code != NULL) {
       tty->print("  code: ");
@@ -602,6 +620,7 @@
       tty->cr();
     }
   }
+  guarantee(argslen == args->length(), "args array cannot grow inside nested ResoureMark scope");
 }
 
 
diff --git a/hotspot/src/share/vm/code/dependencies.hpp b/hotspot/src/share/vm/code/dependencies.hpp
index a91e1f1..1143227 100644
--- a/hotspot/src/share/vm/code/dependencies.hpp
+++ b/hotspot/src/share/vm/code/dependencies.hpp
@@ -368,20 +368,36 @@
   void copy_to(nmethod* nm);
 
   void log_all_dependencies();
-  void log_dependency(DepType dept, int nargs, ciBaseObject* args[]) {
-    write_dependency_to(log(), dept, nargs, args);
+
+  void log_dependency(DepType dept, GrowableArray<ciBaseObject*>* args) {
+    ResourceMark rm;
+    int argslen = args->length();
+    write_dependency_to(log(), dept, args);
+    guarantee(argslen == args->length(),
+              "args array cannot grow inside nested ResoureMark scope");
   }
+
   void log_dependency(DepType dept,
                       ciBaseObject* x0,
                       ciBaseObject* x1 = NULL,
                       ciBaseObject* x2 = NULL) {
-    if (log() == NULL)  return;
-    ciBaseObject* args[max_arg_count];
-    args[0] = x0;
-    args[1] = x1;
-    args[2] = x2;
-    assert(2 < max_arg_count, "");
-    log_dependency(dept, dep_args(dept), args);
+    if (log() == NULL) {
+      return;
+    }
+    ResourceMark rm;
+    GrowableArray<ciBaseObject*>* ciargs =
+                new GrowableArray<ciBaseObject*>(dep_args(dept));
+    assert (x0 != NULL, "no log x0");
+    ciargs->push(x0);
+
+    if (x1 != NULL) {
+      ciargs->push(x1);
+    }
+    if (x2 != NULL) {
+      ciargs->push(x2);
+    }
+    assert(ciargs->length() == dep_args(dept), "");
+    log_dependency(dept, ciargs);
   }
 
   class DepArgument : public ResourceObj {
@@ -404,20 +420,8 @@
     Metadata* metadata_value() const { assert(!_is_oop && _valid, "must be"); return (Metadata*) _value; }
   };
 
-  static void write_dependency_to(CompileLog* log,
-                                  DepType dept,
-                                  int nargs, ciBaseObject* args[],
-                                  Klass* witness = NULL);
-  static void write_dependency_to(CompileLog* log,
-                                  DepType dept,
-                                  int nargs, DepArgument args[],
-                                  Klass* witness = NULL);
-  static void write_dependency_to(xmlStream* xtty,
-                                  DepType dept,
-                                  int nargs, DepArgument args[],
-                                  Klass* witness = NULL);
   static void print_dependency(DepType dept,
-                               int nargs, DepArgument args[],
+                               GrowableArray<DepArgument>* args,
                                Klass* witness = NULL);
 
  private:
@@ -426,6 +430,18 @@
 
   static Klass* ctxk_encoded_as_null(DepType dept, Metadata* x);
 
+  static void write_dependency_to(CompileLog* log,
+                                  DepType dept,
+                                  GrowableArray<ciBaseObject*>* args,
+                                  Klass* witness = NULL);
+  static void write_dependency_to(CompileLog* log,
+                                  DepType dept,
+                                  GrowableArray<DepArgument>* args,
+                                  Klass* witness = NULL);
+  static void write_dependency_to(xmlStream* xtty,
+                                  DepType dept,
+                                  GrowableArray<DepArgument>* args,
+                                  Klass* witness = NULL);
  public:
   // Use this to iterate over an nmethod's dependency set.
   // Works on new and old dependency sets.
diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp
index 003bb30..deeffad 100644
--- a/hotspot/src/share/vm/code/nmethod.cpp
+++ b/hotspot/src/share/vm/code/nmethod.cpp
@@ -37,6 +37,7 @@
 #include "oops/methodData.hpp"
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "prims/jvmtiImpl.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/sweeper.hpp"
 #include "utilities/dtrace.hpp"
@@ -48,6 +49,8 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
+unsigned char nmethod::_global_unloading_clock = 0;
+
 #ifdef DTRACE_ENABLED
 
 // Only bother with this argument setup if dtrace is available
@@ -383,26 +386,29 @@
   set_exception_cache(new_entry);
 }
 
-void nmethod::remove_from_exception_cache(ExceptionCache* ec) {
+void nmethod::clean_exception_cache(BoolObjectClosure* is_alive) {
   ExceptionCache* prev = NULL;
   ExceptionCache* curr = exception_cache();
-  assert(curr != NULL, "nothing to remove");
-  // find the previous and next entry of ec
-  while (curr != ec) {
-    prev = curr;
-    curr = curr->next();
-    assert(curr != NULL, "ExceptionCache not found");
-  }
-  // now: curr == ec
-  ExceptionCache* next = curr->next();
-  if (prev == NULL) {
-    set_exception_cache(next);
-  } else {
-    prev->set_next(next);
-  }
-  delete curr;
-}
 
+  while (curr != NULL) {
+    ExceptionCache* next = curr->next();
+
+    Klass* ex_klass = curr->exception_type();
+    if (ex_klass != NULL && !ex_klass->is_loader_alive(is_alive)) {
+      if (prev == NULL) {
+        set_exception_cache(next);
+      } else {
+        prev->set_next(next);
+      }
+      delete curr;
+      // prev stays the same.
+    } else {
+      prev = curr;
+    }
+
+    curr = next;
+  }
+}
 
 // public method for accessing the exception cache
 // These are the public access methods.
@@ -462,6 +468,7 @@
 // Fill in default values for various flag fields
 void nmethod::init_defaults() {
   _state                      = in_use;
+  _unloading_clock            = 0;
   _marked_for_reclamation     = 0;
   _has_flushed_dependencies   = 0;
   _has_unsafe_access          = 0;
@@ -480,7 +487,11 @@
   _oops_do_mark_link       = NULL;
   _jmethod_id              = NULL;
   _osr_link                = NULL;
-  _scavenge_root_link      = NULL;
+  if (UseG1GC) {
+    _unloading_next        = NULL;
+  } else {
+    _scavenge_root_link    = NULL;
+  }
   _scavenge_root_state     = 0;
   _compiler                = NULL;
 #if INCLUDE_RTM_OPT
@@ -688,8 +699,10 @@
     _hotness_counter         = NMethodSweeper::hotness_counter_reset_val();
 
     code_buffer->copy_values_to(this);
-    if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
-      CodeCache::add_scavenge_root_nmethod(this);
+    if (ScavengeRootsInCode) {
+      if (detect_scavenge_root_oops()) {
+        CodeCache::add_scavenge_root_nmethod(this);
+      }
       Universe::heap()->register_nmethod(this);
     }
     debug_only(verify_scavenge_root_oops());
@@ -773,8 +786,10 @@
     _hotness_counter         = NMethodSweeper::hotness_counter_reset_val();
 
     code_buffer->copy_values_to(this);
-    if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
-      CodeCache::add_scavenge_root_nmethod(this);
+    if (ScavengeRootsInCode) {
+      if (detect_scavenge_root_oops()) {
+        CodeCache::add_scavenge_root_nmethod(this);
+      }
       Universe::heap()->register_nmethod(this);
     }
     DEBUG_ONLY(verify_scavenge_root_oops();)
@@ -889,8 +904,10 @@
     code_buffer->copy_values_to(this);
     debug_info->copy_to(this);
     dependencies->copy_to(this);
-    if (ScavengeRootsInCode && detect_scavenge_root_oops()) {
-      CodeCache::add_scavenge_root_nmethod(this);
+    if (ScavengeRootsInCode) {
+      if (detect_scavenge_root_oops()) {
+        CodeCache::add_scavenge_root_nmethod(this);
+      }
       Universe::heap()->register_nmethod(this);
     }
     debug_only(verify_scavenge_root_oops());
@@ -1156,7 +1173,7 @@
     switch(iter.type()) {
       case relocInfo::virtual_call_type:
       case relocInfo::opt_virtual_call_type: {
-        CompiledIC *ic = CompiledIC_at(iter.reloc());
+        CompiledIC *ic = CompiledIC_at(&iter);
         // Ok, to lookup references to zombies here
         CodeBlob *cb = CodeCache::find_blob_unsafe(ic->ic_destination());
         if( cb != NULL && cb->is_nmethod() ) {
@@ -1180,6 +1197,77 @@
   }
 }
 
+void nmethod::verify_clean_inline_caches() {
+  assert_locked_or_safepoint(CompiledIC_lock);
+
+  // If the method is not entrant or zombie then a JMP is plastered over the
+  // first few bytes.  If an oop in the old code was there, that oop
+  // should not get GC'd.  Skip the first few bytes of oops on
+  // not-entrant methods.
+  address low_boundary = verified_entry_point();
+  if (!is_in_use()) {
+    low_boundary += NativeJump::instruction_size;
+    // %%% Note:  On SPARC we patch only a 4-byte trap, not a full NativeJump.
+    // This means that the low_boundary is going to be a little too high.
+    // This shouldn't matter, since oops of non-entrant methods are never used.
+    // In fact, why are we bothering to look at oops in a non-entrant method??
+  }
+
+  ResourceMark rm;
+  RelocIterator iter(this, low_boundary);
+  while(iter.next()) {
+    switch(iter.type()) {
+      case relocInfo::virtual_call_type:
+      case relocInfo::opt_virtual_call_type: {
+        CompiledIC *ic = CompiledIC_at(&iter);
+        // Ok, to lookup references to zombies here
+        CodeBlob *cb = CodeCache::find_blob_unsafe(ic->ic_destination());
+        if( cb != NULL && cb->is_nmethod() ) {
+          nmethod* nm = (nmethod*)cb;
+          // Verify that inline caches pointing to both zombie and not_entrant methods are clean
+          if (!nm->is_in_use() || (nm->method()->code() != nm)) {
+            assert(ic->is_clean(), "IC should be clean");
+          }
+        }
+        break;
+      }
+      case relocInfo::static_call_type: {
+        CompiledStaticCall *csc = compiledStaticCall_at(iter.reloc());
+        CodeBlob *cb = CodeCache::find_blob_unsafe(csc->destination());
+        if( cb != NULL && cb->is_nmethod() ) {
+          nmethod* nm = (nmethod*)cb;
+          // Verify that inline caches pointing to both zombie and not_entrant methods are clean
+          if (!nm->is_in_use() || (nm->method()->code() != nm)) {
+            assert(csc->is_clean(), "IC should be clean");
+          }
+        }
+        break;
+      }
+    }
+  }
+}
+
+int nmethod::verify_icholder_relocations() {
+  int count = 0;
+
+  RelocIterator iter(this);
+  while(iter.next()) {
+    if (iter.type() == relocInfo::virtual_call_type) {
+      if (CompiledIC::is_icholder_call_site(iter.virtual_call_reloc())) {
+        CompiledIC *ic = CompiledIC_at(&iter);
+        if (TraceCompiledIC) {
+          tty->print("noticed icholder " INTPTR_FORMAT " ", p2i(ic->cached_icholder()));
+          ic->print();
+        }
+        assert(ic->cached_icholder() != NULL, "must be non-NULL");
+        count++;
+      }
+    }
+  }
+
+  return count;
+}
+
 // This is a private interface with the sweeper.
 void nmethod::mark_as_seen_on_stack() {
   assert(is_alive(), "Must be an alive method");
@@ -1212,6 +1300,23 @@
   mdo->inc_decompile_count();
 }
 
+void nmethod::increase_unloading_clock() {
+  _global_unloading_clock++;
+  if (_global_unloading_clock == 0) {
+    // _nmethods are allocated with _unloading_clock == 0,
+    // so 0 is never used as a clock value.
+    _global_unloading_clock = 1;
+  }
+}
+
+void nmethod::set_unloading_clock(unsigned char unloading_clock) {
+  OrderAccess::release_store((volatile jubyte*)&_unloading_clock, unloading_clock);
+}
+
+unsigned char nmethod::unloading_clock() {
+  return (unsigned char)OrderAccess::load_acquire((volatile jubyte*)&_unloading_clock);
+}
+
 void nmethod::make_unloaded(BoolObjectClosure* is_alive, oop cause) {
 
   post_compiled_method_unload();
@@ -1257,6 +1362,10 @@
     // for later on.
     CodeCache::set_needs_cache_clean(true);
   }
+
+  // Unregister must be done before the state change
+  Universe::heap()->unregister_nmethod(this);
+
   _state = unloaded;
 
   // Log the unloading.
@@ -1611,6 +1720,35 @@
   set_unload_reported();
 }
 
+void static clean_ic_if_metadata_is_dead(CompiledIC *ic, BoolObjectClosure *is_alive) {
+  if (ic->is_icholder_call()) {
+    // The only exception is compiledICHolder oops which may
+    // yet be marked below. (We check this further below).
+    CompiledICHolder* cichk_oop = ic->cached_icholder();
+    if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
+        cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
+      return;
+    }
+  } else {
+    Metadata* ic_oop = ic->cached_metadata();
+    if (ic_oop != NULL) {
+      if (ic_oop->is_klass()) {
+        if (((Klass*)ic_oop)->is_loader_alive(is_alive)) {
+          return;
+        }
+      } else if (ic_oop->is_method()) {
+        if (((Method*)ic_oop)->method_holder()->is_loader_alive(is_alive)) {
+          return;
+        }
+      } else {
+        ShouldNotReachHere();
+      }
+    }
+  }
+
+  ic->set_to_clean();
+}
+
 // This is called at the end of the strong tracing/marking phase of a
 // GC to unload an nmethod if it contains otherwise unreachable
 // oops.
@@ -1643,15 +1781,7 @@
   }
 
   // Exception cache
-  ExceptionCache* ec = exception_cache();
-  while (ec != NULL) {
-    Klass* ex_klass = ec->exception_type();
-    ExceptionCache* next_ec = ec->next();
-    if (ex_klass != NULL && !ex_klass->is_loader_alive(is_alive)) {
-      remove_from_exception_cache(ec);
-    }
-    ec = next_ec;
-  }
+  clean_exception_cache(is_alive);
 
   // If class unloading occurred we first iterate over all inline caches and
   // clear ICs where the cached oop is referring to an unloaded klass or method.
@@ -1661,32 +1791,8 @@
     RelocIterator iter(this, low_boundary);
     while(iter.next()) {
       if (iter.type() == relocInfo::virtual_call_type) {
-        CompiledIC *ic = CompiledIC_at(iter.reloc());
-        if (ic->is_icholder_call()) {
-          // The only exception is compiledICHolder oops which may
-          // yet be marked below. (We check this further below).
-          CompiledICHolder* cichk_oop = ic->cached_icholder();
-          if (cichk_oop->holder_method()->method_holder()->is_loader_alive(is_alive) &&
-              cichk_oop->holder_klass()->is_loader_alive(is_alive)) {
-            continue;
-          }
-        } else {
-          Metadata* ic_oop = ic->cached_metadata();
-          if (ic_oop != NULL) {
-            if (ic_oop->is_klass()) {
-              if (((Klass*)ic_oop)->is_loader_alive(is_alive)) {
-                continue;
-              }
-            } else if (ic_oop->is_method()) {
-              if (((Method*)ic_oop)->method_holder()->is_loader_alive(is_alive)) {
-                continue;
-              }
-            } else {
-              ShouldNotReachHere();
-            }
-          }
-        }
-        ic->set_to_clean();
+        CompiledIC *ic = CompiledIC_at(&iter);
+        clean_ic_if_metadata_is_dead(ic, is_alive);
       }
     }
   }
@@ -1724,6 +1830,175 @@
   verify_metadata_loaders(low_boundary, is_alive);
 }
 
+template <class CompiledICorStaticCall>
+static bool clean_if_nmethod_is_unloaded(CompiledICorStaticCall *ic, address addr, BoolObjectClosure *is_alive, nmethod* from) {
+  // Ok, to lookup references to zombies here
+  CodeBlob *cb = CodeCache::find_blob_unsafe(addr);
+  if (cb != NULL && cb->is_nmethod()) {
+    nmethod* nm = (nmethod*)cb;
+
+    if (nm->unloading_clock() != nmethod::global_unloading_clock()) {
+      // The nmethod has not been processed yet.
+      return true;
+    }
+
+    // Clean inline caches pointing to both zombie and not_entrant methods
+    if (!nm->is_in_use() || (nm->method()->code() != nm)) {
+      ic->set_to_clean();
+      assert(ic->is_clean(), err_msg("nmethod " PTR_FORMAT "not clean %s", from, from->method()->name_and_sig_as_C_string()));
+    }
+  }
+
+  return false;
+}
+
+static bool clean_if_nmethod_is_unloaded(CompiledIC *ic, BoolObjectClosure *is_alive, nmethod* from) {
+  return clean_if_nmethod_is_unloaded(ic, ic->ic_destination(), is_alive, from);
+}
+
+static bool clean_if_nmethod_is_unloaded(CompiledStaticCall *csc, BoolObjectClosure *is_alive, nmethod* from) {
+  return clean_if_nmethod_is_unloaded(csc, csc->destination(), is_alive, from);
+}
+
+bool nmethod::do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred) {
+  ResourceMark rm;
+
+  // Make sure the oop's ready to receive visitors
+  assert(!is_zombie() && !is_unloaded(),
+         "should not call follow on zombie or unloaded nmethod");
+
+  // If the method is not entrant then a JMP is plastered over the
+  // first few bytes.  If an oop in the old code was there, that oop
+  // should not get GC'd.  Skip the first few bytes of oops on
+  // not-entrant methods.
+  address low_boundary = verified_entry_point();
+  if (is_not_entrant()) {
+    low_boundary += NativeJump::instruction_size;
+    // %%% Note:  On SPARC we patch only a 4-byte trap, not a full NativeJump.
+    // (See comment above.)
+  }
+
+  // The RedefineClasses() API can cause the class unloading invariant
+  // to no longer be true. See jvmtiExport.hpp for details.
+  // Also, leave a debugging breadcrumb in local flag.
+  bool a_class_was_redefined = JvmtiExport::has_redefined_a_class();
+  if (a_class_was_redefined) {
+    // This set of the unloading_occurred flag is done before the
+    // call to post_compiled_method_unload() so that the unloading
+    // of this nmethod is reported.
+    unloading_occurred = true;
+  }
+
+  // Exception cache
+  clean_exception_cache(is_alive);
+
+  bool is_unloaded = false;
+  bool postponed = false;
+
+  RelocIterator iter(this, low_boundary);
+  while(iter.next()) {
+
+    switch (iter.type()) {
+
+    case relocInfo::virtual_call_type:
+      if (unloading_occurred) {
+        // If class unloading occurred we first iterate over all inline caches and
+        // clear ICs where the cached oop is referring to an unloaded klass or method.
+        clean_ic_if_metadata_is_dead(CompiledIC_at(&iter), is_alive);
+      }
+
+      postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      break;
+
+    case relocInfo::opt_virtual_call_type:
+      postponed |= clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      break;
+
+    case relocInfo::static_call_type:
+      postponed |= clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
+      break;
+
+    case relocInfo::oop_type:
+      if (!is_unloaded) {
+        // Unload check
+        oop_Relocation* r = iter.oop_reloc();
+        // Traverse those oops directly embedded in the code.
+        // Other oops (oop_index>0) are seen as part of scopes_oops.
+        assert(1 == (r->oop_is_immediate()) +
+                  (r->oop_addr() >= oops_begin() && r->oop_addr() < oops_end()),
+              "oop must be found in exactly one place");
+        if (r->oop_is_immediate() && r->oop_value() != NULL) {
+          if (can_unload(is_alive, r->oop_addr(), unloading_occurred)) {
+            is_unloaded = true;
+          }
+        }
+      }
+      break;
+
+    }
+  }
+
+  if (is_unloaded) {
+    return postponed;
+  }
+
+  // Scopes
+  for (oop* p = oops_begin(); p < oops_end(); p++) {
+    if (*p == Universe::non_oop_word())  continue;  // skip non-oops
+    if (can_unload(is_alive, p, unloading_occurred)) {
+      is_unloaded = true;
+      break;
+    }
+  }
+
+  if (is_unloaded) {
+    return postponed;
+  }
+
+  // Ensure that all metadata is still alive
+  verify_metadata_loaders(low_boundary, is_alive);
+
+  return postponed;
+}
+
+void nmethod::do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred) {
+  ResourceMark rm;
+
+  // Make sure the oop's ready to receive visitors
+  assert(!is_zombie(),
+         "should not call follow on zombie nmethod");
+
+  // If the method is not entrant then a JMP is plastered over the
+  // first few bytes.  If an oop in the old code was there, that oop
+  // should not get GC'd.  Skip the first few bytes of oops on
+  // not-entrant methods.
+  address low_boundary = verified_entry_point();
+  if (is_not_entrant()) {
+    low_boundary += NativeJump::instruction_size;
+    // %%% Note:  On SPARC we patch only a 4-byte trap, not a full NativeJump.
+    // (See comment above.)
+  }
+
+  RelocIterator iter(this, low_boundary);
+  while(iter.next()) {
+
+    switch (iter.type()) {
+
+    case relocInfo::virtual_call_type:
+      clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      break;
+
+    case relocInfo::opt_virtual_call_type:
+      clean_if_nmethod_is_unloaded(CompiledIC_at(&iter), is_alive, this);
+      break;
+
+    case relocInfo::static_call_type:
+      clean_if_nmethod_is_unloaded(compiledStaticCall_at(iter.reloc()), is_alive, this);
+      break;
+    }
+  }
+}
+
 #ifdef ASSERT
 
 class CheckClass : AllStatic {
@@ -1770,7 +2045,7 @@
     // compiled code is maintaining a link to dead metadata.
     address static_call_addr = NULL;
     if (iter.type() == relocInfo::opt_virtual_call_type) {
-      CompiledIC* cic = CompiledIC_at(iter.reloc());
+      CompiledIC* cic = CompiledIC_at(&iter);
       if (!cic->is_call_to_interpreted()) {
         static_call_addr = iter.addr();
       }
@@ -1822,7 +2097,7 @@
         }
       } else if (iter.type() == relocInfo::virtual_call_type) {
         // Check compiledIC holders associated with this nmethod
-        CompiledIC *ic = CompiledIC_at(iter.reloc());
+        CompiledIC *ic = CompiledIC_at(&iter);
         if (ic->is_icholder_call()) {
           CompiledICHolder* cichk = ic->cached_icholder();
           f(cichk->holder_method());
@@ -1940,7 +2215,7 @@
     assert(cur != NULL, "not NULL-terminated");
     nmethod* next = cur->_oops_do_mark_link;
     cur->_oops_do_mark_link = NULL;
-    cur->fix_oop_relocations();
+    cur->verify_oop_relocations();
     NOT_PRODUCT(if (TraceScavenge)  cur->print_on(tty, "oops_do, unmark"));
     cur = next;
   }
@@ -2482,6 +2757,10 @@
 };
 
 void nmethod::verify_scavenge_root_oops() {
+  if (UseG1GC) {
+    return;
+  }
+
   if (!on_scavenge_root_list()) {
     // Actually look inside, to verify the claim that it's clean.
     DebugScavengeRoot debug_scavenge_root(this);
@@ -2925,7 +3204,7 @@
     case relocInfo::virtual_call_type:
     case relocInfo::opt_virtual_call_type: {
       VerifyMutexLocker mc(CompiledIC_lock);
-      CompiledIC_at(iter.reloc())->print();
+      CompiledIC_at(&iter)->print();
       break;
     }
     case relocInfo::static_call_type:
diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp
index e1793ce..96f3e04 100644
--- a/hotspot/src/share/vm/code/nmethod.hpp
+++ b/hotspot/src/share/vm/code/nmethod.hpp
@@ -69,7 +69,12 @@
   friend class VMStructs;
  private:
   enum { cache_size = 4 };
-  PcDesc* _pc_descs[cache_size]; // last cache_size pc_descs found
+  // The array elements MUST be volatile! Several threads may modify
+  // and read from the cache concurrently. find_pc_desc_internal has
+  // returned wrong results. C++ compiler (namely xlC12) may duplicate
+  // C++ field accesses if the elements are not volatile.
+  typedef PcDesc* PcDescPtr;
+  volatile PcDescPtr _pc_descs[cache_size]; // last cache_size pc_descs found
  public:
   PcDescCache() { debug_only(_pc_descs[0] = NULL); }
   void    reset_to(PcDesc* initial_pc_desc);
@@ -111,6 +116,11 @@
   friend class NMethodSweeper;
   friend class CodeCache;  // scavengable oops
  private:
+
+  // GC support to help figure out if an nmethod has been
+  // cleaned/unloaded by the current GC.
+  static unsigned char _global_unloading_clock;
+
   // Shared fields for all nmethod's
   Method*   _method;
   int       _entry_bci;        // != InvocationEntryBci if this nmethod is an on-stack replacement method
@@ -118,7 +128,13 @@
 
   // To support simple linked-list chaining of nmethods:
   nmethod*  _osr_link;         // from InstanceKlass::osr_nmethods_head
-  nmethod*  _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
+
+  union {
+    // Used by G1 to chain nmethods.
+    nmethod* _unloading_next;
+    // Used by non-G1 GCs to chain nmethods.
+    nmethod* _scavenge_root_link; // from CodeCache::scavenge_root_nmethods
+  };
 
   static nmethod* volatile _oops_do_mark_nmethods;
   nmethod*        volatile _oops_do_mark_link;
@@ -180,6 +196,8 @@
   // Protected by Patching_lock
   volatile unsigned char _state;             // {alive, not_entrant, zombie, unloaded}
 
+  volatile unsigned char _unloading_clock;   // Incremented after GC unloaded/cleaned the nmethod
+
 #ifdef ASSERT
   bool _oops_are_stale;  // indicates that it's no longer safe to access oops section
 #endif
@@ -437,6 +455,15 @@
   bool  unload_reported()                         { return _unload_reported; }
   void  set_unload_reported()                     { _unload_reported = true; }
 
+  void set_unloading_next(nmethod* next)          { _unloading_next = next; }
+  nmethod* unloading_next()                       { return _unloading_next; }
+
+  static unsigned char global_unloading_clock()   { return _global_unloading_clock; }
+  static void increase_unloading_clock();
+
+  void set_unloading_clock(unsigned char unloading_clock);
+  unsigned char unloading_clock();
+
   bool  is_marked_for_deoptimization() const      { return _marked_for_deoptimization; }
   void  mark_for_deoptimization()                 { _marked_for_deoptimization = true; }
 
@@ -529,7 +556,7 @@
   void set_exception_cache(ExceptionCache *ec)    { _exception_cache = ec; }
   address handler_for_exception_and_pc(Handle exception, address pc);
   void add_handler_for_exception_and_pc(Handle exception, address pc, address handler);
-  void remove_from_exception_cache(ExceptionCache* ec);
+  void clean_exception_cache(BoolObjectClosure* is_alive);
 
   // implicit exceptions support
   address continuation_for_implicit_exception(address pc);
@@ -552,6 +579,10 @@
     return (addr >= code_begin() && addr < verified_entry_point());
   }
 
+  // Verify calls to dead methods have been cleaned.
+  void verify_clean_inline_caches();
+  // Verify and count cached icholder relocations.
+  int  verify_icholder_relocations();
   // Check that all metadata is still alive
   void verify_metadata_loaders(address low_boundary, BoolObjectClosure* is_alive);
 
@@ -577,6 +608,10 @@
 
   // GC support
   void do_unloading(BoolObjectClosure* is_alive, bool unloading_occurred);
+  //  The parallel versions are used by G1.
+  bool do_unloading_parallel(BoolObjectClosure* is_alive, bool unloading_occurred);
+  void do_unloading_parallel_postponed(BoolObjectClosure* is_alive, bool unloading_occurred);
+  //  Unload a nmethod if the *root object is dead.
   bool can_unload(BoolObjectClosure* is_alive, oop* root, bool unloading_occurred);
 
   void preserve_callee_argument_oops(frame fr, const RegisterMap *reg_map,
diff --git a/hotspot/src/share/vm/compiler/methodLiveness.cpp b/hotspot/src/share/vm/compiler/methodLiveness.cpp
index 0c1d9b0..eda1ab1 100644
--- a/hotspot/src/share/vm/compiler/methodLiveness.cpp
+++ b/hotspot/src/share/vm/compiler/methodLiveness.cpp
@@ -475,7 +475,7 @@
     bci = 0;
   }
 
-  MethodLivenessResult answer((uintptr_t*)NULL,0);
+  MethodLivenessResult answer((BitMap::bm_word_t*)NULL,0);
 
   if (_block_count > 0) {
     if (TimeLivenessAnalysis) _time_total.start();
@@ -1000,7 +1000,7 @@
 }
 
 MethodLivenessResult MethodLiveness::BasicBlock::get_liveness_at(ciMethod* method, int bci) {
-  MethodLivenessResult answer(NEW_RESOURCE_ARRAY(uintptr_t, _analyzer->bit_map_size_words()),
+  MethodLivenessResult answer(NEW_RESOURCE_ARRAY(BitMap::bm_word_t, _analyzer->bit_map_size_words()),
                 _analyzer->bit_map_size_bits());
   answer.set_is_valid();
 
diff --git a/hotspot/src/share/vm/compiler/oopMap.cpp b/hotspot/src/share/vm/compiler/oopMap.cpp
index 0989ac5..5e18015 100644
--- a/hotspot/src/share/vm/compiler/oopMap.cpp
+++ b/hotspot/src/share/vm/compiler/oopMap.cpp
@@ -467,7 +467,6 @@
   assert(cb != NULL, "no codeblob");
 
   // Any reg might be saved by a safepoint handler (see generate_handler_blob).
-  const int max_saved_on_entry_reg_count = ConcreteRegisterImpl::number_of_registers;
   assert( reg_map->_update_for_id == NULL || fr->is_older(reg_map->_update_for_id),
          "already updated this map; do not 'update' it twice!" );
   debug_only(reg_map->_update_for_id = fr->id());
@@ -477,27 +476,20 @@
           !cb->caller_must_gc_arguments(reg_map->thread())),
          "include_argument_oops should already be set");
 
-  int nof_callee = 0;
-  oop*        locs[2*max_saved_on_entry_reg_count+1];
-  VMReg regs[2*max_saved_on_entry_reg_count+1];
-  // ("+1" because max_saved_on_entry_reg_count might be zero)
-
   // Scan through oopmap and find location of all callee-saved registers
   // (we do not do update in place, since info could be overwritten)
 
   address pc = fr->pc();
-
   OopMap* map  = cb->oop_map_for_return_address(pc);
+  assert(map != NULL, "no ptr map found");
+  DEBUG_ONLY(int nof_callee = 0;)
 
-  assert(map != NULL, " no ptr map found");
-
-  OopMapValue omv;
-  for(OopMapStream oms(map,OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
-    omv = oms.current();
-    assert(nof_callee < 2*max_saved_on_entry_reg_count, "overflow");
-    regs[nof_callee] = omv.content_reg();
-    locs[nof_callee] = fr->oopmapreg_to_location(omv.reg(),reg_map);
-    nof_callee++;
+  for (OopMapStream oms(map, OopMapValue::callee_saved_value); !oms.is_done(); oms.next()) {
+    OopMapValue omv = oms.current();
+    VMReg reg = omv.content_reg();
+    oop* loc = fr->oopmapreg_to_location(omv.reg(), reg_map);
+    reg_map->set_location(reg, (address) loc);
+    DEBUG_ONLY(nof_callee++;)
   }
 
   // Check that runtime stubs save all callee-saved registers
@@ -506,11 +498,6 @@
          (nof_callee >= SAVED_ON_ENTRY_REG_COUNT || nof_callee >= C_SAVED_ON_ENTRY_REG_COUNT),
          "must save all");
 #endif // COMPILER2
-
-  // Copy found callee-saved register to reg_map
-  for(int i = 0; i < nof_callee; i++) {
-    reg_map->set_location(regs[i], (address)locs[i]);
-  }
 }
 
 //=============================================================================
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp
index a1627a3..b7f7ed1 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/adaptiveFreeList.cpp
@@ -158,7 +158,7 @@
                  " coal_deaths(" SIZE_FORMAT ")"
                  " + count(" SSIZE_FORMAT ")",
                  p2i(this), size(), _allocation_stats.prev_sweep(), _allocation_stats.split_births(),
-                 _allocation_stats.split_births(), _allocation_stats.split_deaths(),
+                 _allocation_stats.coal_births(), _allocation_stats.split_deaths(),
                  _allocation_stats.coal_deaths(), count()));
 }
 #endif
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
index a236a10..79f8fa5 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsCollectorPolicy.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 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,7 +53,8 @@
 }
 
 void ConcurrentMarkSweepPolicy::initialize_generations() {
-  _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL);
+  _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC,
+    CURRENT_PC, AllocFailStrategy::RETURN_NULL);
   if (_generations == NULL)
     vm_exit_during_initialization("Unable to allocate gen spec");
 
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp
index b910dd6e..5220ee1 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.hpp
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_HPP
 
 #include "memory/genOopClosures.hpp"
+#include "memory/iterator.hpp"
 
 /////////////////////////////////////////////////////////////////
 // Closures used by ConcurrentMarkSweepGeneration's collector
@@ -48,33 +49,13 @@
     }                                                     \
   }
 
-// Applies the given oop closure to all oops in all klasses visited.
-class CMKlassClosure : public KlassClosure {
-  friend class CMSOopClosure;
-  friend class CMSOopsInGenClosure;
-
-  OopClosure* _oop_closure;
-
-  // Used when _oop_closure couldn't be set in an initialization list.
-  void initialize(OopClosure* oop_closure) {
-    assert(_oop_closure == NULL, "Should only be called once");
-    _oop_closure = oop_closure;
-  }
+// TODO: This duplication of the MetadataAwareOopClosure class is only needed
+//       because some CMS OopClosures derive from OopsInGenClosure. It would be
+//       good to get rid of them completely.
+class MetadataAwareOopsInGenClosure: public OopsInGenClosure {
+  KlassToOopClosure _klass_closure;
  public:
-  CMKlassClosure(OopClosure* oop_closure = NULL) : _oop_closure(oop_closure) { }
-
-  void do_klass(Klass* k);
-};
-
-// The base class for all CMS marking closures.
-// It's used to proxy through the metadata to the oops defined in them.
-class CMSOopClosure: public ExtendedOopClosure {
-  CMKlassClosure      _klass_closure;
- public:
-  CMSOopClosure() : ExtendedOopClosure() {
-    _klass_closure.initialize(this);
-  }
-  CMSOopClosure(ReferenceProcessor* rp) : ExtendedOopClosure(rp) {
+  MetadataAwareOopsInGenClosure() {
     _klass_closure.initialize(this);
   }
 
@@ -87,26 +68,7 @@
   virtual void do_class_loader_data(ClassLoaderData* cld);
 };
 
-// TODO: This duplication of the CMSOopClosure class is only needed because
-//       some CMS OopClosures derive from OopsInGenClosure. It would be good
-//       to get rid of them completely.
-class CMSOopsInGenClosure: public OopsInGenClosure {
-  CMKlassClosure _klass_closure;
- public:
-  CMSOopsInGenClosure() {
-    _klass_closure.initialize(this);
-  }
-
-  virtual bool do_metadata()    { return do_metadata_nv(); }
-  inline  bool do_metadata_nv() { return true; }
-
-  virtual void do_klass(Klass* k);
-  void do_klass_nv(Klass* k);
-
-  virtual void do_class_loader_data(ClassLoaderData* cld);
-};
-
-class MarkRefsIntoClosure: public CMSOopsInGenClosure {
+class MarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
  private:
   const MemRegion _span;
   CMSBitMap*      _bitMap;
@@ -122,7 +84,7 @@
   }
 };
 
-class Par_MarkRefsIntoClosure: public CMSOopsInGenClosure {
+class Par_MarkRefsIntoClosure: public MetadataAwareOopsInGenClosure {
  private:
   const MemRegion _span;
   CMSBitMap*      _bitMap;
@@ -140,7 +102,7 @@
 
 // A variant of the above used in certain kinds of CMS
 // marking verification.
-class MarkRefsIntoVerifyClosure: public CMSOopsInGenClosure {
+class MarkRefsIntoVerifyClosure: public MetadataAwareOopsInGenClosure {
  private:
   const MemRegion _span;
   CMSBitMap*      _verification_bm;
@@ -159,7 +121,7 @@
 };
 
 // The non-parallel version (the parallel version appears further below).
-class PushAndMarkClosure: public CMSOopClosure {
+class PushAndMarkClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector* _collector;
   MemRegion     _span;
@@ -193,7 +155,7 @@
 // synchronization (for instance, via CAS). The marking stack
 // used in the non-parallel case above is here replaced with
 // an OopTaskQueue structure to allow efficient work stealing.
-class Par_PushAndMarkClosure: public CMSOopClosure {
+class Par_PushAndMarkClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector* _collector;
   MemRegion     _span;
@@ -218,7 +180,7 @@
 };
 
 // The non-parallel version (the parallel version appears further below).
-class MarkRefsIntoAndScanClosure: public CMSOopsInGenClosure {
+class MarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure {
  private:
   MemRegion          _span;
   CMSBitMap*         _bit_map;
@@ -262,7 +224,7 @@
 // stack and the bitMap are shared, so access needs to be suitably
 // sycnhronized. An OopTaskQueue structure, supporting efficient
 // workstealing, replaces a CMSMarkStack for storing grey objects.
-class Par_MarkRefsIntoAndScanClosure: public CMSOopsInGenClosure {
+class Par_MarkRefsIntoAndScanClosure: public MetadataAwareOopsInGenClosure {
  private:
   MemRegion              _span;
   CMSBitMap*             _bit_map;
@@ -291,7 +253,7 @@
 // This closure is used during the concurrent marking phase
 // following the first checkpoint. Its use is buried in
 // the closure MarkFromRootsClosure.
-class PushOrMarkClosure: public CMSOopClosure {
+class PushOrMarkClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector*   _collector;
   MemRegion       _span;
@@ -324,7 +286,7 @@
 // This closure is used during the concurrent marking phase
 // following the first checkpoint. Its use is buried in
 // the closure Par_MarkFromRootsClosure.
-class Par_PushOrMarkClosure: public CMSOopClosure {
+class Par_PushOrMarkClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector*    _collector;
   MemRegion        _whole_span;
@@ -364,7 +326,7 @@
 // processing phase of the CMS final checkpoint step, as
 // well as during the concurrent precleaning of the discovered
 // reference lists.
-class CMSKeepAliveClosure: public CMSOopClosure {
+class CMSKeepAliveClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector* _collector;
   const MemRegion _span;
@@ -384,7 +346,7 @@
   inline void do_oop_nv(narrowOop* p) { CMSKeepAliveClosure::do_oop_work(p); }
 };
 
-class CMSInnerParMarkAndPushClosure: public CMSOopClosure {
+class CMSInnerParMarkAndPushClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector* _collector;
   MemRegion     _span;
@@ -405,7 +367,7 @@
 // A parallel (MT) version of the above, used when
 // reference processing is parallel; the only difference
 // is in the do_oop method.
-class CMSParKeepAliveClosure: public CMSOopClosure {
+class CMSParKeepAliveClosure: public MetadataAwareOopClosure {
  private:
   MemRegion     _span;
   OopTaskQueue* _work_queue;
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp
index 499ba4b..2980f0d 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/cmsOopClosures.inline.hpp
@@ -44,33 +44,20 @@
   }
 }
 
-// CMSOopClosure and CMSoopsInGenClosure are duplicated,
+// MetadataAwareOopClosure and MetadataAwareOopsInGenClosure are duplicated,
 // until we get rid of OopsInGenClosure.
 
-inline void CMSOopClosure::do_klass(Klass* k)       { do_klass_nv(k); }
-inline void CMSOopsInGenClosure::do_klass(Klass* k) { do_klass_nv(k); }
-
-inline void CMSOopClosure::do_klass_nv(Klass* k) {
+inline void MetadataAwareOopsInGenClosure::do_klass_nv(Klass* k) {
   ClassLoaderData* cld = k->class_loader_data();
   do_class_loader_data(cld);
 }
-inline void CMSOopsInGenClosure::do_klass_nv(Klass* k) {
-  ClassLoaderData* cld = k->class_loader_data();
-  do_class_loader_data(cld);
-}
+inline void MetadataAwareOopsInGenClosure::do_klass(Klass* k) { do_klass_nv(k); }
 
-inline void CMSOopClosure::do_class_loader_data(ClassLoaderData* cld) {
+inline void MetadataAwareOopsInGenClosure::do_class_loader_data(ClassLoaderData* cld) {
   assert(_klass_closure._oop_closure == this, "Must be");
 
   bool claim = true;  // Must claim the class loader data before processing.
   cld->oops_do(_klass_closure._oop_closure, &_klass_closure, claim);
 }
-inline void CMSOopsInGenClosure::do_class_loader_data(ClassLoaderData* cld) {
-  assert(_klass_closure._oop_closure == this, "Must be");
-
-  bool claim = true;  // Must claim the class loader data before processing.
-  cld->oops_do(_klass_closure._oop_closure, &_klass_closure, claim);
-}
-
 
 #endif // SHARE_VM_GC_IMPLEMENTATION_CONCURRENTMARKSWEEP_CMSOOPCLOSURES_INLINE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
index 61afb75..f153ad7 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.cpp
@@ -33,12 +33,14 @@
 #include "memory/allocation.inline.hpp"
 #include "memory/blockOffsetTable.inline.hpp"
 #include "memory/resourceArea.hpp"
+#include "memory/space.inline.hpp"
 #include "memory/universe.inline.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/java.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "utilities/copy.hpp"
 
@@ -793,53 +795,6 @@
   }
 }
 
-// Apply the given closure to each oop in the space \intersect memory region.
-void CompactibleFreeListSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  assert_lock_strong(freelistLock());
-  if (is_empty()) {
-    return;
-  }
-  MemRegion cur = MemRegion(bottom(), end());
-  mr = mr.intersection(cur);
-  if (mr.is_empty()) {
-    return;
-  }
-  if (mr.equals(cur)) {
-    oop_iterate(cl);
-    return;
-  }
-  assert(mr.end() <= end(), "just took an intersection above");
-  HeapWord* obj_addr = block_start(mr.start());
-  HeapWord* t = mr.end();
-
-  SpaceMemRegionOopsIterClosure smr_blk(cl, mr);
-  if (block_is_obj(obj_addr)) {
-    // Handle first object specially.
-    oop obj = oop(obj_addr);
-    obj_addr += adjustObjectSize(obj->oop_iterate(&smr_blk));
-  } else {
-    FreeChunk* fc = (FreeChunk*)obj_addr;
-    obj_addr += fc->size();
-  }
-  while (obj_addr < t) {
-    HeapWord* obj = obj_addr;
-    obj_addr += block_size(obj_addr);
-    // If "obj_addr" is not greater than top, then the
-    // entire object "obj" is within the region.
-    if (obj_addr <= t) {
-      if (block_is_obj(obj)) {
-        oop(obj)->oop_iterate(cl);
-      }
-    } else {
-      // "obj" extends beyond end of region
-      if (block_is_obj(obj)) {
-        oop(obj)->oop_iterate(&smr_blk);
-      }
-      break;
-    }
-  }
-}
-
 // NOTE: In the following methods, in order to safely be able to
 // apply the closure to an object, we need to be sure that the
 // object has been initialized. We are guaranteed that an object
@@ -898,42 +853,60 @@
                                                   UpwardsObjectClosure* cl) {
   assert_locked(freelistLock());
   NOT_PRODUCT(verify_objects_initialized());
-  Space::object_iterate_mem(mr, cl);
+  assert(!mr.is_empty(), "Should be non-empty");
+  // We use MemRegion(bottom(), end()) rather than used_region() below
+  // because the two are not necessarily equal for some kinds of
+  // spaces, in particular, certain kinds of free list spaces.
+  // We could use the more complicated but more precise:
+  // MemRegion(used_region().start(), round_to(used_region().end(), CardSize))
+  // but the slight imprecision seems acceptable in the assertion check.
+  assert(MemRegion(bottom(), end()).contains(mr),
+         "Should be within used space");
+  HeapWord* prev = cl->previous();   // max address from last time
+  if (prev >= mr.end()) { // nothing to do
+    return;
+  }
+  // This assert will not work when we go from cms space to perm
+  // space, and use same closure. Easy fix deferred for later. XXX YSR
+  // assert(prev == NULL || contains(prev), "Should be within space");
+
+  bool last_was_obj_array = false;
+  HeapWord *blk_start_addr, *region_start_addr;
+  if (prev > mr.start()) {
+    region_start_addr = prev;
+    blk_start_addr    = prev;
+    // The previous invocation may have pushed "prev" beyond the
+    // last allocated block yet there may be still be blocks
+    // in this region due to a particular coalescing policy.
+    // Relax the assertion so that the case where the unallocated
+    // block is maintained and "prev" is beyond the unallocated
+    // block does not cause the assertion to fire.
+    assert((BlockOffsetArrayUseUnallocatedBlock &&
+            (!is_in(prev))) ||
+           (blk_start_addr == block_start(region_start_addr)), "invariant");
+  } else {
+    region_start_addr = mr.start();
+    blk_start_addr    = block_start(region_start_addr);
+  }
+  HeapWord* region_end_addr = mr.end();
+  MemRegion derived_mr(region_start_addr, region_end_addr);
+  while (blk_start_addr < region_end_addr) {
+    const size_t size = block_size(blk_start_addr);
+    if (block_is_obj(blk_start_addr)) {
+      last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr);
+    } else {
+      last_was_obj_array = false;
+    }
+    blk_start_addr += size;
+  }
+  if (!last_was_obj_array) {
+    assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()),
+           "Should be within (closed) used space");
+    assert(blk_start_addr > prev, "Invariant");
+    cl->set_previous(blk_start_addr); // min address for next time
+  }
 }
 
-// Callers of this iterator beware: The closure application should
-// be robust in the face of uninitialized objects and should (always)
-// return a correct size so that the next addr + size below gives us a
-// valid block boundary. [See for instance,
-// ScanMarkedObjectsAgainCarefullyClosure::do_object_careful()
-// in ConcurrentMarkSweepGeneration.cpp.]
-HeapWord*
-CompactibleFreeListSpace::object_iterate_careful(ObjectClosureCareful* cl) {
-  assert_lock_strong(freelistLock());
-  HeapWord *addr, *last;
-  size_t size;
-  for (addr = bottom(), last  = end();
-       addr < last; addr += size) {
-    FreeChunk* fc = (FreeChunk*)addr;
-    if (fc->is_free()) {
-      // Since we hold the free list lock, which protects direct
-      // allocation in this generation by mutators, a free object
-      // will remain free throughout this iteration code.
-      size = fc->size();
-    } else {
-      // Note that the object need not necessarily be initialized,
-      // because (for instance) the free list lock does NOT protect
-      // object initialization. The closure application below must
-      // therefore be correct in the face of uninitialized objects.
-      size = cl->do_object_careful(oop(addr));
-      if (size == 0) {
-        // An unparsable object found. Signal early termination.
-        return addr;
-      }
-    }
-  }
-  return NULL;
-}
 
 // Callers of this iterator beware: The closure application should
 // be robust in the face of uninitialized objects and should (always)
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
index 35b8e72..e79ba69 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp
@@ -337,10 +337,6 @@
                      unallocated_block() : end());
   }
 
-  bool is_in(const void* p) const {
-    return used_region().contains(p);
-  }
-
   virtual bool is_free_block(const HeapWord* p) const;
 
   // Resizing support
@@ -350,7 +346,6 @@
   Mutex* freelistLock() const { return &_freelistLock; }
 
   // Iteration support
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   void oop_iterate(ExtendedOopClosure* cl);
 
   void object_iterate(ObjectClosure* blk);
@@ -363,6 +358,12 @@
   // obj_is_alive() to determine whether it is safe to iterate of
   // an object.
   void safe_object_iterate(ObjectClosure* blk);
+
+  // Iterate over all objects that intersect with mr, calling "cl->do_object"
+  // on each.  There is an exception to this: if this closure has already
+  // been invoked on an object, it may skip such objects in some cases.  This is
+  // Most likely to happen in an "upwards" (ascending address) iteration of
+  // MemRegions.
   void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
 
   // Requires that "mr" be entirely within the space.
@@ -371,11 +372,8 @@
   // terminate the iteration and return the address of the start of the
   // subregion that isn't done.  Return of "NULL" indicates that the
   // interation completed.
-  virtual HeapWord*
-       object_iterate_careful_m(MemRegion mr,
-                                ObjectClosureCareful* cl);
-  virtual HeapWord*
-       object_iterate_careful(ObjectClosureCareful* cl);
+ HeapWord* object_iterate_careful_m(MemRegion mr,
+                                    ObjectClosureCareful* cl);
 
   // Override: provides a DCTO_CL specific to this kind of space.
   DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
index dea030f..0f34360 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp
@@ -49,7 +49,7 @@
 #include "memory/genCollectedHeap.hpp"
 #include "memory/genMarkSweep.hpp"
 #include "memory/genOopClosures.inline.hpp"
-#include "memory/iterator.hpp"
+#include "memory/iterator.inline.hpp"
 #include "memory/padded.hpp"
 #include "memory/referencePolicy.hpp"
 #include "memory/resourceArea.hpp"
@@ -59,6 +59,7 @@
 #include "runtime/globals_extension.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "services/memoryService.hpp"
 #include "services/runtimeService.hpp"
@@ -1513,6 +1514,8 @@
     gclog_or_tty->print_cr("cms_allocation_rate=%g", stats().cms_allocation_rate());
     gclog_or_tty->print_cr("occupancy=%3.7f", _cmsGen->occupancy());
     gclog_or_tty->print_cr("initiatingOccupancy=%3.7f", _cmsGen->initiating_occupancy());
+    gclog_or_tty->print_cr("cms_time_since_begin=%3.7f", stats().cms_time_since_begin());
+    gclog_or_tty->print_cr("cms_time_since_end=%3.7f", stats().cms_time_since_end());
     gclog_or_tty->print_cr("metadata initialized %d",
       MetaspaceGC::should_concurrent_collect());
   }
@@ -1569,11 +1572,33 @@
   }
 
   if (MetaspaceGC::should_concurrent_collect()) {
-      if (Verbose && PrintGCDetails) {
+    if (Verbose && PrintGCDetails) {
       gclog_or_tty->print("CMSCollector: collect for metadata allocation ");
+    }
+    return true;
+  }
+
+  // CMSTriggerInterval starts a CMS cycle if enough time has passed.
+  if (CMSTriggerInterval >= 0) {
+    if (CMSTriggerInterval == 0) {
+      // Trigger always
+      return true;
+    }
+
+    // Check the CMS time since begin (we do not check the stats validity
+    // as we want to be able to trigger the first CMS cycle as well)
+    if (stats().cms_time_since_begin() >= (CMSTriggerInterval / ((double) MILLIUNITS))) {
+      if (Verbose && PrintGCDetails) {
+        if (stats().valid()) {
+          gclog_or_tty->print_cr("CMSCollector: collect because of trigger interval (time since last begin %3.7f secs)",
+                                 stats().cms_time_since_begin());
+        } else {
+          gclog_or_tty->print_cr("CMSCollector: collect because of trigger interval (first collection)");
+        }
       }
       return true;
     }
+  }
 
   return false;
 }
@@ -1999,7 +2024,7 @@
   SerialOldTracer* gc_tracer = GenMarkSweep::gc_tracer();
   gc_tracer->report_gc_start(gch->gc_cause(), gc_timer->gc_start());
 
-  GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL);
+  GCTraceTime t("CMS:MSC ", PrintGCDetails && Verbose, true, NULL, gc_tracer->gc_id());
   if (PrintGC && Verbose && !(GCCause::is_user_requested_gc(gch->gc_cause()))) {
     gclog_or_tty->print_cr("Compact ConcurrentMarkSweepGeneration after %d "
       "collections passed to foreground collector", _full_gcs_since_conc_gc);
@@ -2509,8 +2534,10 @@
   assert(ConcurrentMarkSweepThread::vm_thread_has_cms_token(),
          "VM thread should have CMS token");
 
+  // The gc id is created in register_foreground_gc_start if this collection is synchronous
+  const GCId gc_id = _collectorState == InitialMarking ? GCId::peek() : _gc_tracer_cm->gc_id();
   NOT_PRODUCT(GCTraceTime t("CMS:MS (foreground) ", PrintGCDetails && Verbose,
-    true, NULL);)
+    true, NULL, gc_id);)
   if (UseAdaptiveSizePolicy) {
     size_policy()->ms_collection_begin();
   }
@@ -3025,22 +3052,21 @@
   HandleMark  hm;
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
-  // Get a clear set of claim bits for the strong roots processing to work with.
+  // Get a clear set of claim bits for the roots processing to work with.
   ClassLoaderDataGraph::clear_claimed_marks();
 
   // Mark from roots one level into CMS
   MarkRefsIntoClosure notOlder(_span, verification_mark_bm());
   gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
 
-  gch->gen_process_strong_roots(_cmsGen->level(),
-                                true,   // younger gens are roots
-                                true,   // activate StrongRootsScope
-                                false,  // not scavenging
-                                SharedHeap::ScanningOption(roots_scanning_options()),
-                                &notOlder,
-                                true,   // walk code active on stacks
-                                NULL,
-                                NULL); // SSS: Provide correct closure
+  gch->gen_process_roots(_cmsGen->level(),
+                         true,   // younger gens are roots
+                         true,   // activate StrongRootsScope
+                         SharedHeap::ScanningOption(roots_scanning_options()),
+                         should_unload_classes(),
+                         &notOlder,
+                         NULL,
+                         NULL);  // SSS: Provide correct closure
 
   // Now mark from the roots
   MarkFromRootsClosure markFromRootsClosure(this, _span,
@@ -3091,24 +3117,24 @@
   HandleMark  hm;
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
-  // Get a clear set of claim bits for the strong roots processing to work with.
+  // Get a clear set of claim bits for the roots processing to work with.
   ClassLoaderDataGraph::clear_claimed_marks();
 
   // Mark from roots one level into CMS
   MarkRefsIntoVerifyClosure notOlder(_span, verification_mark_bm(),
                                      markBitMap());
-  CMKlassClosure klass_closure(&notOlder);
+  CLDToOopClosure cld_closure(&notOlder, true);
 
   gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
-  gch->gen_process_strong_roots(_cmsGen->level(),
-                                true,   // younger gens are roots
-                                true,   // activate StrongRootsScope
-                                false,  // not scavenging
-                                SharedHeap::ScanningOption(roots_scanning_options()),
-                                &notOlder,
-                                true,   // walk code active on stacks
-                                NULL,
-                                &klass_closure);
+
+  gch->gen_process_roots(_cmsGen->level(),
+                         true,   // younger gens are roots
+                         true,   // activate StrongRootsScope
+                         SharedHeap::ScanningOption(roots_scanning_options()),
+                         should_unload_classes(),
+                         &notOlder,
+                         NULL,
+                         &cld_closure);
 
   // Now mark from the roots
   MarkFromRootsVerifyClosure markFromRootsClosure(this, _span,
@@ -3169,16 +3195,6 @@
 }
 
 void
-ConcurrentMarkSweepGeneration::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  if (freelistLock()->owned_by_self()) {
-    Generation::oop_iterate(mr, cl);
-  } else {
-    MutexLockerEx x(freelistLock(), Mutex::_no_safepoint_check_flag);
-    Generation::oop_iterate(mr, cl);
-  }
-}
-
-void
 ConcurrentMarkSweepGeneration::oop_iterate(ExtendedOopClosure* cl) {
   if (freelistLock()->owned_by_self()) {
     Generation::oop_iterate(cl);
@@ -3305,12 +3321,10 @@
 void CMSCollector::setup_cms_unloading_and_verification_state() {
   const  bool should_verify =   VerifyBeforeGC || VerifyAfterGC || VerifyDuringGC
                              || VerifyBeforeExit;
-  const  int  rso           =   SharedHeap::SO_Strings | SharedHeap::SO_CodeCache;
+  const  int  rso           =   SharedHeap::SO_AllCodeCache;
 
   // We set the proper root for this CMS cycle here.
   if (should_unload_classes()) {   // Should unload classes this cycle
-    remove_root_scanning_option(SharedHeap::SO_AllClasses);
-    add_root_scanning_option(SharedHeap::SO_SystemClasses);
     remove_root_scanning_option(rso);  // Shrink the root set appropriately
     set_verifying(should_verify);    // Set verification state for this cycle
     return;                            // Nothing else needs to be done at this time
@@ -3318,8 +3332,6 @@
 
   // Not unloading classes this cycle
   assert(!should_unload_classes(), "Inconsitency!");
-  remove_root_scanning_option(SharedHeap::SO_SystemClasses);
-  add_root_scanning_option(SharedHeap::SO_AllClasses);
 
   if ((!verifying() || unloaded_classes_last_cycle()) && should_verify) {
     // Include symbols, strings and code cache elements to prevent their resurrection.
@@ -3527,6 +3539,7 @@
  public:
   CMSPhaseAccounting(CMSCollector *collector,
                      const char *phase,
+                     const GCId gc_id,
                      bool print_cr = true);
   ~CMSPhaseAccounting();
 
@@ -3535,6 +3548,7 @@
   const char *_phase;
   elapsedTimer _wallclock;
   bool _print_cr;
+  const GCId _gc_id;
 
  public:
   // Not MT-safe; so do not pass around these StackObj's
@@ -3550,15 +3564,15 @@
 
 CMSPhaseAccounting::CMSPhaseAccounting(CMSCollector *collector,
                                        const char *phase,
+                                       const GCId gc_id,
                                        bool print_cr) :
-  _collector(collector), _phase(phase), _print_cr(print_cr) {
+  _collector(collector), _phase(phase), _print_cr(print_cr), _gc_id(gc_id) {
 
   if (PrintCMSStatistics != 0) {
     _collector->resetYields();
   }
   if (PrintGCDetails) {
-    gclog_or_tty->date_stamp(PrintGCDateStamps);
-    gclog_or_tty->stamp(PrintGCTimeStamps);
+    gclog_or_tty->gclog_stamp(_gc_id);
     gclog_or_tty->print_cr("[%s-concurrent-%s-start]",
       _collector->cmsGen()->short_name(), _phase);
   }
@@ -3572,8 +3586,7 @@
   _collector->stopTimer();
   _wallclock.stop();
   if (PrintGCDetails) {
-    gclog_or_tty->date_stamp(PrintGCDateStamps);
-    gclog_or_tty->stamp(PrintGCTimeStamps);
+    gclog_or_tty->gclog_stamp(_gc_id);
     gclog_or_tty->print("[%s-concurrent-%s: %3.3f/%3.3f secs]",
                  _collector->cmsGen()->short_name(),
                  _phase, _collector->timerValue(), _wallclock.seconds());
@@ -3671,7 +3684,7 @@
   setup_cms_unloading_and_verification_state();
 
   NOT_PRODUCT(GCTraceTime t("\ncheckpointRootsInitialWork",
-    PrintGCDetails && Verbose, true, _gc_timer_cm);)
+    PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());)
   if (UseAdaptiveSizePolicy) {
     size_policy()->checkpoint_roots_initial_begin();
   }
@@ -3684,12 +3697,6 @@
   ResourceMark rm;
   HandleMark  hm;
 
-  FalseClosure falseClosure;
-  // In the case of a synchronous collection, we will elide the
-  // remark step, so it's important to catch all the nmethod oops
-  // in this step.
-  // The final 'true' flag to gen_process_strong_roots will ensure this.
-  // If 'async' is true, we can relax the nmethod tracing.
   MarkRefsIntoClosure notOlder(_span, &_markBitMap);
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
@@ -3735,17 +3742,16 @@
       gch->set_par_threads(0);
     } else {
       // The serial version.
-      CMKlassClosure klass_closure(&notOlder);
+      CLDToOopClosure cld_closure(&notOlder, true);
       gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
-      gch->gen_process_strong_roots(_cmsGen->level(),
-                                    true,   // younger gens are roots
-                                    true,   // activate StrongRootsScope
-                                    false,  // not scavenging
-                                    SharedHeap::ScanningOption(roots_scanning_options()),
-                                    &notOlder,
-                                    true,   // walk all of code cache if (so & SO_CodeCache)
-                                    NULL,
-                                    &klass_closure);
+      gch->gen_process_roots(_cmsGen->level(),
+                             true,   // younger gens are roots
+                             true,   // activate StrongRootsScope
+                             SharedHeap::ScanningOption(roots_scanning_options()),
+                             should_unload_classes(),
+                             &notOlder,
+                             NULL,
+                             &cld_closure);
     }
   }
 
@@ -3796,7 +3802,7 @@
 
     CMSTokenSyncWithLocks ts(true, bitMapLock());
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    CMSPhaseAccounting pa(this, "mark", !PrintGCDetails);
+    CMSPhaseAccounting pa(this, "mark", _gc_tracer_cm->gc_id(), !PrintGCDetails);
     res = markFromRootsWork(asynch);
     if (res) {
       _collectorState = Precleaning;
@@ -4199,7 +4205,7 @@
   pst->all_tasks_completed();
 }
 
-class Par_ConcMarkingClosure: public CMSOopClosure {
+class Par_ConcMarkingClosure: public MetadataAwareOopClosure {
  private:
   CMSCollector* _collector;
   CMSConcMarkingTask* _task;
@@ -4212,7 +4218,7 @@
  public:
   Par_ConcMarkingClosure(CMSCollector* collector, CMSConcMarkingTask* task, OopTaskQueue* work_queue,
                          CMSBitMap* bit_map, CMSMarkStack* overflow_stack):
-    CMSOopClosure(collector->ref_processor()),
+    MetadataAwareOopClosure(collector->ref_processor()),
     _collector(collector),
     _task(task),
     _span(collector->_span),
@@ -4519,7 +4525,7 @@
       _start_sampling = false;
     }
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    CMSPhaseAccounting pa(this, "preclean", !PrintGCDetails);
+    CMSPhaseAccounting pa(this, "preclean", _gc_tracer_cm->gc_id(), !PrintGCDetails);
     preclean_work(CMSPrecleanRefLists1, CMSPrecleanSurvivors1);
   }
   CMSTokenSync x(true); // is cms thread
@@ -4548,7 +4554,7 @@
   // we will never do an actual abortable preclean cycle.
   if (get_eden_used() > CMSScheduleRemarkEdenSizeThreshold) {
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    CMSPhaseAccounting pa(this, "abortable-preclean", !PrintGCDetails);
+    CMSPhaseAccounting pa(this, "abortable-preclean", _gc_tracer_cm->gc_id(), !PrintGCDetails);
     // We need more smarts in the abortable preclean
     // loop below to deal with cases where allocation
     // in young gen is very very slow, and our precleaning
@@ -4693,7 +4699,7 @@
     GCTimer *gc_timer = NULL; // Currently not tracing concurrent phases
     rp->preclean_discovered_references(
           rp->is_alive_non_header(), &keep_alive, &complete_trace, &yield_cl,
-          gc_timer);
+          gc_timer, _gc_tracer_cm->gc_id());
   }
 
   if (clean_survivor) {  // preclean the active survivor space(s)
@@ -4983,7 +4989,7 @@
 }
 
 class PrecleanKlassClosure : public KlassClosure {
-  CMKlassClosure _cm_klass_closure;
+  KlassToOopClosure _cm_klass_closure;
  public:
   PrecleanKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {}
   void do_klass(Klass* k) {
@@ -5036,7 +5042,7 @@
       // expect it to be false and set to true
       FlagSetting fl(gch->_is_gc_active, false);
       NOT_PRODUCT(GCTraceTime t("Scavenge-Before-Remark",
-        PrintGCDetails && Verbose, true, _gc_timer_cm);)
+        PrintGCDetails && Verbose, true, _gc_timer_cm, _gc_tracer_cm->gc_id());)
       int level = _cmsGen->level() - 1;
       if (level >= 0) {
         gch->do_collection(true,        // full (i.e. force, see below)
@@ -5065,7 +5071,7 @@
 void CMSCollector::checkpointRootsFinalWork(bool asynch,
   bool clear_all_soft_refs, bool init_mark_was_synchronous) {
 
-  NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm);)
+  NOT_PRODUCT(GCTraceTime tr("checkpointRootsFinalWork", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());)
 
   assert(haveFreelistLocks(), "must have free list locks");
   assert_lock_strong(bitMapLock());
@@ -5120,11 +5126,11 @@
       // the most recent young generation GC, minus those cleaned up by the
       // concurrent precleaning.
       if (CMSParallelRemarkEnabled && CollectedHeap::use_parallel_gc_threads()) {
-        GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm);
+        GCTraceTime t("Rescan (parallel) ", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
         do_remark_parallel();
       } else {
         GCTraceTime t("Rescan (non-parallel) ", PrintGCDetails, false,
-                    _gc_timer_cm);
+                    _gc_timer_cm, _gc_tracer_cm->gc_id());
         do_remark_non_parallel();
       }
     }
@@ -5137,7 +5143,7 @@
   verify_overflow_empty();
 
   {
-    NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm);)
+    NOT_PRODUCT(GCTraceTime ts("refProcessingWork", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());)
     refProcessingWork(asynch, clear_all_soft_refs);
   }
   verify_work_stacks_empty();
@@ -5221,7 +5227,6 @@
   _timer.start();
   GenCollectedHeap* gch = GenCollectedHeap::heap();
   Par_MarkRefsIntoClosure par_mri_cl(_collector->_span, &(_collector->_markBitMap));
-  CMKlassClosure klass_closure(&par_mri_cl);
 
   // ---------- young gen roots --------------
   {
@@ -5237,17 +5242,19 @@
   // ---------- remaining roots --------------
   _timer.reset();
   _timer.start();
-  gch->gen_process_strong_roots(_collector->_cmsGen->level(),
-                                false,     // yg was scanned above
-                                false,     // this is parallel code
-                                false,     // not scavenging
-                                SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
-                                &par_mri_cl,
-                                true,   // walk all of code cache if (so & SO_CodeCache)
-                                NULL,
-                                &klass_closure);
+
+  CLDToOopClosure cld_closure(&par_mri_cl, true);
+
+  gch->gen_process_roots(_collector->_cmsGen->level(),
+                         false,     // yg was scanned above
+                         false,     // this is parallel code
+                         SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+                         _collector->should_unload_classes(),
+                         &par_mri_cl,
+                         NULL,
+                         &cld_closure);
   assert(_collector->should_unload_classes()
-         || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache),
+         || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_AllCodeCache),
          "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
   _timer.stop();
   if (PrintCMSStatistics != 0) {
@@ -5297,7 +5304,7 @@
 };
 
 class RemarkKlassClosure : public KlassClosure {
-  CMKlassClosure _cm_klass_closure;
+  KlassToOopClosure _cm_klass_closure;
  public:
   RemarkKlassClosure(OopClosure* oop_closure) : _cm_klass_closure(oop_closure) {}
   void do_klass(Klass* k) {
@@ -5374,17 +5381,17 @@
   // ---------- remaining roots --------------
   _timer.reset();
   _timer.start();
-  gch->gen_process_strong_roots(_collector->_cmsGen->level(),
-                                false,     // yg was scanned above
-                                false,     // this is parallel code
-                                false,     // not scavenging
-                                SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
-                                &par_mrias_cl,
-                                true,   // walk all of code cache if (so & SO_CodeCache)
-                                NULL,
-                                NULL);     // The dirty klasses will be handled below
+  gch->gen_process_roots(_collector->_cmsGen->level(),
+                         false,     // yg was scanned above
+                         false,     // this is parallel code
+                         SharedHeap::ScanningOption(_collector->CMSCollector::roots_scanning_options()),
+                         _collector->should_unload_classes(),
+                         &par_mrias_cl,
+                         NULL,
+                         NULL);     // The dirty klasses will be handled below
+
   assert(_collector->should_unload_classes()
-         || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_CodeCache),
+         || (_collector->CMSCollector::roots_scanning_options() & SharedHeap::SO_AllCodeCache),
          "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
   _timer.stop();
   if (PrintCMSStatistics != 0) {
@@ -5437,7 +5444,7 @@
   // We might have added oops to ClassLoaderData::_handles during the
   // concurrent marking phase. These oops point to newly allocated objects
   // that are guaranteed to be kept alive. Either by the direct allocation
-  // code, or when the young collector processes the strong roots. Hence,
+  // code, or when the young collector processes the roots. Hence,
   // we don't have to revisit the _handles block during the remark phase.
 
   // ---------- rescan dirty cards ------------
@@ -5859,7 +5866,7 @@
     cms_space,
     n_workers, workers, task_queues());
 
-  // Set up for parallel process_strong_roots work.
+  // Set up for parallel process_roots work.
   gch->set_par_threads(n_workers);
   // We won't be iterating over the cards in the card table updating
   // the younger_gen cards, so we shouldn't call the following else
@@ -5868,7 +5875,7 @@
   // gch->rem_set()->prepare_for_younger_refs_iterate(true); // parallel
 
   // The young gen rescan work will not be done as part of
-  // process_strong_roots (which currently doesn't knw how to
+  // process_roots (which currently doesn't know how to
   // parallelize such a scan), but rather will be broken up into
   // a set of parallel tasks (via the sampling that the [abortable]
   // preclean phase did of EdenSpace, plus the [two] tasks of
@@ -5922,7 +5929,7 @@
                               NULL,  // space is set further below
                               &_markBitMap, &_markStack, &mrias_cl);
   {
-    GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm);
+    GCTraceTime t("grey object rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
     // Iterate over the dirty cards, setting the corresponding bits in the
     // mod union table.
     {
@@ -5959,29 +5966,29 @@
     Universe::verify();
   }
   {
-    GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm);
+    GCTraceTime t("root rescan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
 
     verify_work_stacks_empty();
 
     gch->rem_set()->prepare_for_younger_refs_iterate(false); // Not parallel.
     GenCollectedHeap::StrongRootsScope srs(gch);
-    gch->gen_process_strong_roots(_cmsGen->level(),
-                                  true,  // younger gens as roots
-                                  false, // use the local StrongRootsScope
-                                  false, // not scavenging
-                                  SharedHeap::ScanningOption(roots_scanning_options()),
-                                  &mrias_cl,
-                                  true,   // walk code active on stacks
-                                  NULL,
-                                  NULL);  // The dirty klasses will be handled below
+
+    gch->gen_process_roots(_cmsGen->level(),
+                           true,  // younger gens as roots
+                           false, // use the local StrongRootsScope
+                           SharedHeap::ScanningOption(roots_scanning_options()),
+                           should_unload_classes(),
+                           &mrias_cl,
+                           NULL,
+                           NULL); // The dirty klasses will be handled below
 
     assert(should_unload_classes()
-           || (roots_scanning_options() & SharedHeap::SO_CodeCache),
+           || (roots_scanning_options() & SharedHeap::SO_AllCodeCache),
            "if we didn't scan the code cache, we have to be ready to drop nmethods with expired weak oops");
   }
 
   {
-    GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm);
+    GCTraceTime t("visit unhandled CLDs", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
 
     verify_work_stacks_empty();
 
@@ -6000,7 +6007,7 @@
   }
 
   {
-    GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm);
+    GCTraceTime t("dirty klass scan", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
 
     verify_work_stacks_empty();
 
@@ -6013,7 +6020,7 @@
   // We might have added oops to ClassLoaderData::_handles during the
   // concurrent marking phase. These oops point to newly allocated objects
   // that are guaranteed to be kept alive. Either by the direct allocation
-  // code, or when the young collector processes the strong roots. Hence,
+  // code, or when the young collector processes the roots. Hence,
   // we don't have to revisit the _handles block during the remark phase.
 
   verify_work_stacks_empty();
@@ -6068,6 +6075,8 @@
 };
 
 void CMSRefProcTaskProxy::work(uint worker_id) {
+  ResourceMark rm;
+  HandleMark hm;
   assert(_collector->_span.equals(_span), "Inconsistency in _span");
   CMSParKeepAliveClosure par_keep_alive(_collector, _span,
                                         _mark_bit_map,
@@ -6202,7 +6211,7 @@
                                 _span, &_markBitMap, &_markStack,
                                 &cmsKeepAliveClosure, false /* !preclean */);
   {
-    GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm);
+    GCTraceTime t("weak refs processing", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
 
     ReferenceProcessorStats stats;
     if (rp->processing_is_mt()) {
@@ -6227,13 +6236,15 @@
                                         &cmsKeepAliveClosure,
                                         &cmsDrainMarkingStackClosure,
                                         &task_executor,
-                                        _gc_timer_cm);
+                                        _gc_timer_cm,
+                                        _gc_tracer_cm->gc_id());
     } else {
       stats = rp->process_discovered_references(&_is_alive_closure,
                                         &cmsKeepAliveClosure,
                                         &cmsDrainMarkingStackClosure,
                                         NULL,
-                                        _gc_timer_cm);
+                                        _gc_timer_cm,
+                                        _gc_tracer_cm->gc_id());
     }
     _gc_tracer_cm->report_gc_reference_stats(stats);
 
@@ -6244,7 +6255,7 @@
 
   if (should_unload_classes()) {
     {
-      GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm);
+      GCTraceTime t("class unloading", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
 
       // Unload classes and purge the SystemDictionary.
       bool purged_class = SystemDictionary::do_unloading(&_is_alive_closure);
@@ -6257,19 +6268,18 @@
     }
 
     {
-      GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm);
+      GCTraceTime t("scrub symbol table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
       // Clean up unreferenced symbols in symbol table.
       SymbolTable::unlink();
     }
+
+    {
+      GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm, _gc_tracer_cm->gc_id());
+      // Delete entries for dead interned strings.
+      StringTable::unlink(&_is_alive_closure);
+    }
   }
 
-  // CMS doesn't use the StringTable as hard roots when class unloading is turned off.
-  // Need to check if we really scanned the StringTable.
-  if ((roots_scanning_options() & SharedHeap::SO_Strings) == 0) {
-    GCTraceTime t("scrub string table", PrintGCDetails, false, _gc_timer_cm);
-    // Delete entries for dead interned strings.
-    StringTable::unlink(&_is_alive_closure);
-  }
 
   // Restore any preserved marks as a result of mark stack or
   // work queue overflow
@@ -6333,7 +6343,7 @@
   _intra_sweep_timer.start();
   if (asynch) {
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    CMSPhaseAccounting pa(this, "sweep", !PrintGCDetails);
+    CMSPhaseAccounting pa(this, "sweep", _gc_tracer_cm->gc_id(), !PrintGCDetails);
     // First sweep the old gen
     {
       CMSTokenSyncWithLocks ts(true, _cmsGen->freelistLock(),
@@ -6554,7 +6564,7 @@
     // Clear the mark bitmap (no grey objects to start with)
     // for the next cycle.
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    CMSPhaseAccounting cmspa(this, "reset", !PrintGCDetails);
+    CMSPhaseAccounting cmspa(this, "reset", _gc_tracer_cm->gc_id(), !PrintGCDetails);
 
     HeapWord* curAddr = _markBitMap.startWord();
     while (curAddr < _markBitMap.endWord()) {
@@ -6620,7 +6630,7 @@
 void CMSCollector::do_CMS_operation(CMS_op_type op, GCCause::Cause gc_cause) {
   gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
   TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-  GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL);
+  GCTraceTime t(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer_cm->gc_id());
   TraceCollectorStats tcs(counters());
 
   switch (op) {
@@ -7738,7 +7748,7 @@
   CMSCollector* collector, MemRegion span,
   CMSBitMap* verification_bm, CMSBitMap* cms_bm,
   CMSMarkStack*  mark_stack):
-  CMSOopClosure(collector->ref_processor()),
+  MetadataAwareOopClosure(collector->ref_processor()),
   _collector(collector),
   _span(span),
   _verification_bm(verification_bm),
@@ -7791,7 +7801,7 @@
                      MemRegion span,
                      CMSBitMap* bitMap, CMSMarkStack*  markStack,
                      HeapWord* finger, MarkFromRootsClosure* parent) :
-  CMSOopClosure(collector->ref_processor()),
+  MetadataAwareOopClosure(collector->ref_processor()),
   _collector(collector),
   _span(span),
   _bitMap(bitMap),
@@ -7808,7 +7818,7 @@
                      HeapWord* finger,
                      HeapWord** global_finger_addr,
                      Par_MarkFromRootsClosure* parent) :
-  CMSOopClosure(collector->ref_processor()),
+  MetadataAwareOopClosure(collector->ref_processor()),
   _collector(collector),
   _whole_span(collector->_span),
   _span(span),
@@ -7857,11 +7867,6 @@
   _overflow_stack->expand(); // expand the stack if possible
 }
 
-void CMKlassClosure::do_klass(Klass* k) {
-  assert(_oop_closure != NULL, "Not initialized?");
-  k->oops_do(_oop_closure);
-}
-
 void PushOrMarkClosure::do_oop(oop obj) {
   // Ignore mark word because we are running concurrent with mutators.
   assert(obj->is_oop_or_null(true), "expected an oop or NULL");
@@ -7959,7 +7964,7 @@
                                        CMSBitMap* mod_union_table,
                                        CMSMarkStack*  mark_stack,
                                        bool           concurrent_precleaning):
-  CMSOopClosure(rp),
+  MetadataAwareOopClosure(rp),
   _collector(collector),
   _span(span),
   _bit_map(bit_map),
@@ -8032,7 +8037,7 @@
                                                ReferenceProcessor* rp,
                                                CMSBitMap* bit_map,
                                                OopTaskQueue* work_queue):
-  CMSOopClosure(rp),
+  MetadataAwareOopClosure(rp),
   _collector(collector),
   _span(span),
   _bit_map(bit_map),
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
index 2c87671..86b25f7 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.hpp
@@ -32,6 +32,7 @@
 #include "gc_implementation/shared/generationCounters.hpp"
 #include "memory/freeBlockDictionary.hpp"
 #include "memory/generation.hpp"
+#include "memory/iterator.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/virtualspace.hpp"
 #include "services/memoryService.hpp"
@@ -1285,7 +1286,6 @@
   void save_sweep_limit();
 
   // More iteration support
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   virtual void oop_iterate(ExtendedOopClosure* cl);
   virtual void safe_object_iterate(ObjectClosure* cl);
   virtual void object_iterate(ObjectClosure* cl);
@@ -1383,13 +1383,6 @@
 // Closures of various sorts used by CMS to accomplish its work
 //
 
-// This closure is used to check that a certain set of oops is empty.
-class FalseClosure: public OopClosure {
- public:
-  void do_oop(oop* p)       { guarantee(false, "Should be an empty set"); }
-  void do_oop(narrowOop* p) { guarantee(false, "Should be an empty set"); }
-};
-
 // This closure is used to do concurrent marking from the roots
 // following the first checkpoint.
 class MarkFromRootsClosure: public BitMapClosure {
@@ -1454,7 +1447,7 @@
 
 // The following closures are used to do certain kinds of verification of
 // CMS marking.
-class PushAndMarkVerifyClosure: public CMSOopClosure {
+class PushAndMarkVerifyClosure: public MetadataAwareOopClosure {
   CMSCollector*    _collector;
   MemRegion        _span;
   CMSBitMap*       _verification_bm;
@@ -1507,6 +1500,19 @@
   }
 };
 
+// A version of ObjectClosure with "memory" (see _previous_address below)
+class UpwardsObjectClosure: public BoolObjectClosure {
+  HeapWord* _previous_address;
+ public:
+  UpwardsObjectClosure() : _previous_address(NULL) { }
+  void set_previous(HeapWord* addr) { _previous_address = addr; }
+  HeapWord* previous()              { return _previous_address; }
+  // A return value of "true" can be used by the caller to decide
+  // if this object's end should *NOT* be recorded in
+  // _previous_address above.
+  virtual bool do_object_bm(oop obj, MemRegion mr) = 0;
+};
+
 // This closure is used during the second checkpointing phase
 // to rescan the marked objects on the dirty cards in the mod
 // union table and the card table proper. It's invoked via
diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
index c5ae1d4..0d43aa2 100644
--- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
+++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/vmCMSOperations.cpp
@@ -64,7 +64,7 @@
 void VM_CMS_Operation::verify_before_gc() {
   if (VerifyBeforeGC &&
       GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
-    GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm);
+    GCTraceTime tm("Verify Before", false, false, _collector->_gc_timer_cm, _collector->_gc_tracer_cm->gc_id());
     HandleMark hm;
     FreelistLocker x(_collector);
     MutexLockerEx  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
@@ -76,7 +76,7 @@
 void VM_CMS_Operation::verify_after_gc() {
   if (VerifyAfterGC &&
       GenCollectedHeap::heap()->total_collections() >= VerifyGCStartAt) {
-    GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm);
+    GCTraceTime tm("Verify After", false, false, _collector->_gc_timer_cm, _collector->_gc_tracer_cm->gc_id());
     HandleMark hm;
     FreelistLocker x(_collector);
     MutexLockerEx  y(_collector->bitMapLock(), Mutex::_no_safepoint_check_flag);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp
new file mode 100644
index 0000000..d1edd60
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.cpp
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/bufferingOopClosure.hpp"
+#include "memory/iterator.hpp"
+#include "utilities/debug.hpp"
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+class TestBufferingOopClosure {
+
+  // Helper class to fake a set of oop*s and narrowOop*s.
+  class FakeRoots {
+   public:
+    // Used for sanity checking of the values passed to the do_oops functions in the test.
+    static const uintptr_t NarrowOopMarker = uintptr_t(1) << (BitsPerWord -1);
+
+    int    _num_narrow;
+    int    _num_full;
+    void** _narrow;
+    void** _full;
+
+    FakeRoots(int num_narrow, int num_full) :
+        _num_narrow(num_narrow),
+        _num_full(num_full),
+        _narrow((void**)::malloc(sizeof(void*) * num_narrow)),
+        _full((void**)::malloc(sizeof(void*) * num_full)) {
+
+      for (int i = 0; i < num_narrow; i++) {
+        _narrow[i] = (void*)(NarrowOopMarker + (uintptr_t)i);
+      }
+      for (int i = 0; i < num_full; i++) {
+        _full[i] = (void*)(uintptr_t)i;
+      }
+    }
+
+    ~FakeRoots() {
+      ::free(_narrow);
+      ::free(_full);
+    }
+
+    void oops_do_narrow_then_full(OopClosure* cl) {
+      for (int i = 0; i < _num_narrow; i++) {
+        cl->do_oop((narrowOop*)_narrow[i]);
+      }
+      for (int i = 0; i < _num_full; i++) {
+        cl->do_oop((oop*)_full[i]);
+      }
+    }
+
+    void oops_do_full_then_narrow(OopClosure* cl) {
+      for (int i = 0; i < _num_full; i++) {
+        cl->do_oop((oop*)_full[i]);
+      }
+      for (int i = 0; i < _num_narrow; i++) {
+        cl->do_oop((narrowOop*)_narrow[i]);
+      }
+    }
+
+    void oops_do_mixed(OopClosure* cl) {
+      int i;
+      for (i = 0; i < _num_full && i < _num_narrow; i++) {
+        cl->do_oop((oop*)_full[i]);
+        cl->do_oop((narrowOop*)_narrow[i]);
+      }
+      for (int j = i; j < _num_full; j++) {
+        cl->do_oop((oop*)_full[i]);
+      }
+      for (int j = i; j < _num_narrow; j++) {
+        cl->do_oop((narrowOop*)_narrow[i]);
+      }
+    }
+
+    static const int MaxOrder = 2;
+
+    void oops_do(OopClosure* cl, int do_oop_order) {
+      switch(do_oop_order) {
+        case 0:
+          oops_do_narrow_then_full(cl);
+          break;
+        case 1:
+          oops_do_full_then_narrow(cl);
+          break;
+        case 2:
+          oops_do_mixed(cl);
+          break;
+        default:
+          oops_do_narrow_then_full(cl);
+          break;
+      }
+    }
+  };
+
+  class CountOopClosure : public OopClosure {
+    int _narrow_oop_count;
+    int _full_oop_count;
+   public:
+    CountOopClosure() : _narrow_oop_count(0), _full_oop_count(0) {}
+    void do_oop(narrowOop* p) {
+      assert((uintptr_t(p) & FakeRoots::NarrowOopMarker) != 0,
+          "The narrowOop was unexpectedly not marked with the NarrowOopMarker");
+      _narrow_oop_count++;
+    }
+
+    void do_oop(oop* p){
+      assert((uintptr_t(p) & FakeRoots::NarrowOopMarker) == 0,
+          "The oop was unexpectedly marked with the NarrowOopMarker");
+      _full_oop_count++;
+    }
+
+    int narrow_oop_count() { return _narrow_oop_count; }
+    int full_oop_count()   { return _full_oop_count; }
+    int all_oop_count()    { return _narrow_oop_count + _full_oop_count; }
+  };
+
+  class DoNothingOopClosure : public OopClosure {
+   public:
+    void do_oop(narrowOop* p) {}
+    void do_oop(oop* p)       {}
+  };
+
+  static void testCount(int num_narrow, int num_full, int do_oop_order) {
+    FakeRoots fr(num_narrow, num_full);
+
+    CountOopClosure coc;
+    BufferingOopClosure boc(&coc);
+
+    fr.oops_do(&boc, do_oop_order);
+
+    boc.done();
+
+    #define assert_testCount(got, expected)                                     \
+       assert((got) == (expected),                                              \
+           err_msg("Expected: %d, got: %d, when running testCount(%d, %d, %d)", \
+               (got), (expected), num_narrow, num_full, do_oop_order))
+
+    assert_testCount(num_narrow, coc.narrow_oop_count());
+    assert_testCount(num_full, coc.full_oop_count());
+    assert_testCount(num_narrow + num_full, coc.all_oop_count());
+  }
+
+  static void testCount() {
+    int buffer_length = BufferingOopClosure::BufferLength;
+
+    for (int order = 0; order < FakeRoots::MaxOrder; order++) {
+      testCount(0,                 0,                 order);
+      testCount(10,                0,                 order);
+      testCount(0,                 10,                order);
+      testCount(10,                10,                order);
+      testCount(buffer_length,     10,                order);
+      testCount(10,                buffer_length,     order);
+      testCount(buffer_length,     buffer_length,     order);
+      testCount(buffer_length + 1, 10,                order);
+      testCount(10,                buffer_length + 1, order);
+      testCount(buffer_length + 1, buffer_length,     order);
+      testCount(buffer_length,     buffer_length + 1, order);
+      testCount(buffer_length + 1, buffer_length + 1, order);
+    }
+  }
+
+  static void testIsBufferEmptyOrFull(int num_narrow, int num_full, bool expect_empty, bool expect_full) {
+    FakeRoots fr(num_narrow, num_full);
+
+    DoNothingOopClosure cl;
+    BufferingOopClosure boc(&cl);
+
+    fr.oops_do(&boc, 0);
+
+    #define assert_testIsBufferEmptyOrFull(got, expected)                             \
+        assert((got) == (expected),                                                   \
+            err_msg("Expected: %d, got: %d. testIsBufferEmptyOrFull(%d, %d, %s, %s)", \
+                (got), (expected), num_narrow, num_full,                              \
+                BOOL_TO_STR(expect_empty), BOOL_TO_STR(expect_full)))
+
+    assert_testIsBufferEmptyOrFull(expect_empty, boc.is_buffer_empty());
+    assert_testIsBufferEmptyOrFull(expect_full, boc.is_buffer_full());
+  }
+
+  static void testIsBufferEmptyOrFull() {
+    int bl = BufferingOopClosure::BufferLength;
+
+    testIsBufferEmptyOrFull(0,       0, true,  false);
+    testIsBufferEmptyOrFull(1,       0, false, false);
+    testIsBufferEmptyOrFull(0,       1, false, false);
+    testIsBufferEmptyOrFull(1,       1, false, false);
+    testIsBufferEmptyOrFull(10,      0, false, false);
+    testIsBufferEmptyOrFull(0,      10, false, false);
+    testIsBufferEmptyOrFull(10,     10, false, false);
+    testIsBufferEmptyOrFull(0,      bl, false, true);
+    testIsBufferEmptyOrFull(bl,      0, false, true);
+    testIsBufferEmptyOrFull(bl/2, bl/2, false, true);
+    testIsBufferEmptyOrFull(bl-1,    1, false, true);
+    testIsBufferEmptyOrFull(1,    bl-1, false, true);
+    // Processed
+    testIsBufferEmptyOrFull(bl+1,    0, false, false);
+    testIsBufferEmptyOrFull(bl*2,    0, false, true);
+  }
+
+  static void testEmptyAfterDone(int num_narrow, int num_full) {
+    FakeRoots fr(num_narrow, num_full);
+
+    DoNothingOopClosure cl;
+    BufferingOopClosure boc(&cl);
+
+    fr.oops_do(&boc, 0);
+
+    // Make sure all get processed.
+    boc.done();
+
+    assert(boc.is_buffer_empty(),
+        err_msg("Should be empty after call to done(). testEmptyAfterDone(%d, %d)",
+            num_narrow, num_full));
+  }
+
+  static void testEmptyAfterDone() {
+    int bl = BufferingOopClosure::BufferLength;
+
+    testEmptyAfterDone(0,       0);
+    testEmptyAfterDone(1,       0);
+    testEmptyAfterDone(0,       1);
+    testEmptyAfterDone(1,       1);
+    testEmptyAfterDone(10,      0);
+    testEmptyAfterDone(0,      10);
+    testEmptyAfterDone(10,     10);
+    testEmptyAfterDone(0,      bl);
+    testEmptyAfterDone(bl,      0);
+    testEmptyAfterDone(bl/2, bl/2);
+    testEmptyAfterDone(bl-1,    1);
+    testEmptyAfterDone(1,    bl-1);
+    // Processed
+    testEmptyAfterDone(bl+1,    0);
+    testEmptyAfterDone(bl*2,    0);
+  }
+
+  public:
+  static void test() {
+    testCount();
+    testIsBufferEmptyOrFull();
+    testEmptyAfterDone();
+  }
+};
+
+void TestBufferingOopClosure_test() {
+  TestBufferingOopClosure::test();
+}
+
+#endif
diff --git a/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp
index cde2132..2e23e92 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/bufferingOopClosure.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -25,10 +25,10 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_BUFFERINGOOPCLOSURE_HPP
 
-#include "memory/genOopClosures.hpp"
-#include "memory/generation.hpp"
+#include "memory/iterator.hpp"
+#include "oops/oopsHierarchy.hpp"
 #include "runtime/os.hpp"
-#include "utilities/taskqueue.hpp"
+#include "utilities/debug.hpp"
 
 // A BufferingOops closure tries to separate out the cost of finding roots
 // from the cost of applying closures to them.  It maintains an array of
@@ -41,60 +41,103 @@
 // The caller must be sure to call "done" to process any unprocessed
 // buffered entriess.
 
-class Generation;
-class HeapRegion;
-
 class BufferingOopClosure: public OopClosure {
+  friend class TestBufferingOopClosure;
 protected:
-  enum PrivateConstants {
-    BufferLength = 1024
-  };
+  static const size_t BufferLength = 1024;
 
-  StarTask  _buffer[BufferLength];
-  StarTask* _buffer_top;
-  StarTask* _buffer_curr;
+  // We need to know if the buffered addresses contain oops or narrowOops.
+  // We can't tag the addresses the way StarTask does, because we need to
+  // be able to handle unaligned addresses coming from oops embedded in code.
+  //
+  // The addresses for the full-sized oops are filled in from the bottom,
+  // while the addresses for the narrowOops are filled in from the top.
+  OopOrNarrowOopStar  _buffer[BufferLength];
+  OopOrNarrowOopStar* _oop_top;
+  OopOrNarrowOopStar* _narrowOop_bottom;
 
   OopClosure* _oc;
   double      _closure_app_seconds;
 
-  void process_buffer () {
-    double start = os::elapsedTime();
-    for (StarTask* curr = _buffer; curr < _buffer_curr; ++curr) {
-      if (curr->is_narrow()) {
-        assert(UseCompressedOops, "Error");
-        _oc->do_oop((narrowOop*)(*curr));
-      } else {
-        _oc->do_oop((oop*)(*curr));
-      }
+
+  bool is_buffer_empty() {
+    return _oop_top == _buffer && _narrowOop_bottom == (_buffer + BufferLength - 1);
+  }
+
+  bool is_buffer_full() {
+    return _narrowOop_bottom < _oop_top;
+  }
+
+  // Process addresses containing full-sized oops.
+  void process_oops() {
+    for (OopOrNarrowOopStar* curr = _buffer; curr < _oop_top; ++curr) {
+      _oc->do_oop((oop*)(*curr));
     }
-    _buffer_curr = _buffer;
+    _oop_top = _buffer;
+  }
+
+  // Process addresses containing narrow oops.
+  void process_narrowOops() {
+    for (OopOrNarrowOopStar* curr = _buffer + BufferLength - 1; curr > _narrowOop_bottom; --curr) {
+      _oc->do_oop((narrowOop*)(*curr));
+    }
+    _narrowOop_bottom = _buffer + BufferLength - 1;
+  }
+
+  // Apply the closure to all oops and clear the buffer.
+  // Accumulate the time it took.
+  void process_buffer() {
+    double start = os::elapsedTime();
+
+    process_oops();
+    process_narrowOops();
+
     _closure_app_seconds += (os::elapsedTime() - start);
   }
 
-  template <class T> inline void do_oop_work(T* p) {
-    if (_buffer_curr == _buffer_top) {
+  void process_buffer_if_full() {
+    if (is_buffer_full()) {
       process_buffer();
     }
-    StarTask new_ref(p);
-    *_buffer_curr = new_ref;
-    ++_buffer_curr;
+  }
+
+  void add_narrowOop(narrowOop* p) {
+    assert(!is_buffer_full(), "Buffer should not be full");
+    *_narrowOop_bottom = (OopOrNarrowOopStar)p;
+    _narrowOop_bottom--;
+  }
+
+  void add_oop(oop* p) {
+    assert(!is_buffer_full(), "Buffer should not be full");
+    *_oop_top = (OopOrNarrowOopStar)p;
+    _oop_top++;
   }
 
 public:
-  virtual void do_oop(narrowOop* p) { do_oop_work(p); }
-  virtual void do_oop(oop* p)       { do_oop_work(p); }
+  virtual void do_oop(narrowOop* p) {
+    process_buffer_if_full();
+    add_narrowOop(p);
+  }
 
-  void done () {
-    if (_buffer_curr > _buffer) {
+  virtual void do_oop(oop* p)       {
+    process_buffer_if_full();
+    add_oop(p);
+  }
+
+  void done() {
+    if (!is_buffer_empty()) {
       process_buffer();
     }
   }
-  double closure_app_seconds () {
+
+  double closure_app_seconds() {
     return _closure_app_seconds;
   }
-  BufferingOopClosure (OopClosure *oc) :
+
+  BufferingOopClosure(OopClosure *oc) :
     _oc(oc),
-    _buffer_curr(_buffer), _buffer_top(_buffer + BufferLength),
+    _oop_top(_buffer),
+    _narrowOop_bottom(_buffer + BufferLength - 1),
     _closure_app_seconds(0.0) { }
 };
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp
index 62713af..9286013 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.cpp
@@ -29,7 +29,7 @@
 #include "gc_implementation/g1/g1HotCardCache.hpp"
 #include "runtime/java.hpp"
 
-ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) :
+ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure) :
   _threads(NULL), _n_threads(0),
   _hot_card_cache(g1h)
 {
@@ -61,7 +61,7 @@
 
   ConcurrentG1RefineThread *next = NULL;
   for (uint i = _n_threads - 1; i != UINT_MAX; i--) {
-    ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, worker_id_offset, i);
+    ConcurrentG1RefineThread* t = new ConcurrentG1RefineThread(this, next, refine_closure, worker_id_offset, i);
     assert(t != NULL, "Conc refine should have been created");
     if (t->osthread() == NULL) {
         vm_shutdown_during_initialization("Could not create ConcurrentG1RefineThread");
@@ -81,8 +81,8 @@
   }
 }
 
-void ConcurrentG1Refine::init() {
-  _hot_card_cache.initialize();
+void ConcurrentG1Refine::init(G1RegionToSpaceMapper* card_counts_storage) {
+  _hot_card_cache.initialize(card_counts_storage);
 }
 
 void ConcurrentG1Refine::stop() {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp
index 1aea234..7f77163 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1Refine.hpp
@@ -34,6 +34,7 @@
 class ConcurrentG1RefineThread;
 class G1CollectedHeap;
 class G1HotCardCache;
+class G1RegionToSpaceMapper;
 class G1RemSet;
 class DirtyCardQueue;
 
@@ -71,10 +72,10 @@
   void reset_threshold_step();
 
  public:
-  ConcurrentG1Refine(G1CollectedHeap* g1h);
+  ConcurrentG1Refine(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure);
   ~ConcurrentG1Refine();
 
-  void init(); // Accomplish some initialization that has to wait.
+  void init(G1RegionToSpaceMapper* card_counts_storage);
   void stop();
 
   void reinitialize_threads();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
index 6de2f88..a42b8ec 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.cpp
@@ -33,8 +33,10 @@
 
 ConcurrentG1RefineThread::
 ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *next,
+                         CardTableEntryClosure* refine_closure,
                          uint worker_id_offset, uint worker_id) :
   ConcurrentGCThread(),
+  _refine_closure(refine_closure),
   _worker_id_offset(worker_id_offset),
   _worker_id(worker_id),
   _active(false),
@@ -71,6 +73,7 @@
 }
 
 void ConcurrentG1RefineThread::sample_young_list_rs_lengths() {
+  SuspendibleThreadSetJoiner sts;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   G1CollectorPolicy* g1p = g1h->g1_policy();
   if (g1p->adaptive_young_list_length()) {
@@ -82,8 +85,8 @@
 
       // we try to yield every time we visit 10 regions
       if (regions_visited == 10) {
-        if (_sts.should_yield()) {
-          _sts.yield("G1 refine");
+        if (sts.should_yield()) {
+          sts.yield();
           // we just abandon the iteration
           break;
         }
@@ -99,9 +102,7 @@
   DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set();
   _vtime_start = os::elapsedVTime();
   while(!_should_terminate) {
-    _sts.join();
     sample_young_list_rs_lengths();
-    _sts.leave();
 
     if (os::supports_vtime()) {
       _vtime_accum = (os::elapsedVTime() - _vtime_start);
@@ -182,37 +183,37 @@
       break;
     }
 
-    _sts.join();
+    {
+      SuspendibleThreadSetJoiner sts;
 
-    do {
-      int curr_buffer_num = (int)dcqs.completed_buffers_num();
-      // If the number of the buffers falls down into the yellow zone,
-      // that means that the transition period after the evacuation pause has ended.
-      if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
-        dcqs.set_completed_queue_padding(0);
-      }
+      do {
+        int curr_buffer_num = (int)dcqs.completed_buffers_num();
+        // If the number of the buffers falls down into the yellow zone,
+        // that means that the transition period after the evacuation pause has ended.
+        if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) {
+          dcqs.set_completed_queue_padding(0);
+        }
 
-      if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
-        // If the number of the buffer has fallen below our threshold
-        // we should deactivate. The predecessor will reactivate this
-        // thread should the number of the buffers cross the threshold again.
+        if (_worker_id > 0 && curr_buffer_num <= _deactivation_threshold) {
+          // If the number of the buffer has fallen below our threshold
+          // we should deactivate. The predecessor will reactivate this
+          // thread should the number of the buffers cross the threshold again.
+          deactivate();
+          break;
+        }
+
+        // Check if we need to activate the next thread.
+        if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
+          _next->activate();
+        }
+      } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone()));
+
+      // We can exit the loop above while being active if there was a yield request.
+      if (is_active()) {
         deactivate();
-        break;
       }
-
-      // Check if we need to activate the next thread.
-      if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) {
-        _next->activate();
-      }
-    } while (dcqs.apply_closure_to_completed_buffer(_worker_id + _worker_id_offset, cg1r()->green_zone()));
-
-    // We can exit the loop above while being active if there was a yield request.
-    if (is_active()) {
-      deactivate();
     }
 
-    _sts.leave();
-
     if (os::supports_vtime()) {
       _vtime_accum = (os::elapsedVTime() - _vtime_start);
     } else {
@@ -223,17 +224,6 @@
   terminate();
 }
 
-
-void ConcurrentG1RefineThread::yield() {
-  if (G1TraceConcRefinement) {
-    gclog_or_tty->print_cr("G1-Refine-yield");
-  }
-  _sts.yield("G1 refine");
-  if (G1TraceConcRefinement) {
-    gclog_or_tty->print_cr("G1-Refine-yield-end");
-  }
-}
-
 void ConcurrentG1RefineThread::stop() {
   // it is ok to take late safepoints here, if needed
   {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
index 6eb0864..05a8dc4 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentG1RefineThread.hpp
@@ -28,6 +28,7 @@
 #include "gc_implementation/shared/concurrentGCThread.hpp"
 
 // Forward Decl.
+class CardTableEntryClosure;
 class ConcurrentG1Refine;
 
 // The G1 Concurrent Refinement Thread (could be several in the future).
@@ -49,6 +50,9 @@
   Monitor* _monitor;
   ConcurrentG1Refine* _cg1r;
 
+  // The closure applied to completed log buffers.
+  CardTableEntryClosure* _refine_closure;
+
   int _thread_threshold_step;
   // This thread activation threshold
   int _threshold;
@@ -64,13 +68,11 @@
   void activate();
   void deactivate();
 
-  // For use by G1CollectedHeap, which is a friend.
-  static SuspendibleThreadSet* sts() { return &_sts; }
-
 public:
   virtual void run();
   // Constructor
   ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread* next,
+                           CardTableEntryClosure* refine_closure,
                            uint worker_id_offset, uint worker_id);
 
   void initialize();
@@ -84,8 +86,6 @@
 
   ConcurrentG1Refine* cg1r() { return _cg1r;     }
 
-  // Yield for GC
-  void yield();
   // shutdown
   void stop();
 };
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
index 977f1f9..7571287 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "classfile/symbolTable.hpp"
+#include "code/codeCache.hpp"
 #include "gc_implementation/g1/concurrentMark.inline.hpp"
 #include "gc_implementation/g1/concurrentMarkThread.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
@@ -35,16 +36,19 @@
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
 #include "gc_implementation/shared/vmGCOperations.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcTraceTime.hpp"
+#include "memory/allocation.hpp"
 #include "memory/genOopClosures.inline.hpp"
 #include "memory/referencePolicy.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
+#include "runtime/prefetch.inline.hpp"
 #include "services/memTracker.hpp"
 
 // Concurrent marking bit map wrapper
@@ -56,8 +60,8 @@
   _bmWordSize = 0;
 }
 
-HeapWord* CMBitMapRO::getNextMarkedWordAddress(HeapWord* addr,
-                                               HeapWord* limit) const {
+HeapWord* CMBitMapRO::getNextMarkedWordAddress(const HeapWord* addr,
+                                               const HeapWord* limit) const {
   // First we must round addr *up* to a possible object boundary.
   addr = (HeapWord*)align_size_up((intptr_t)addr,
                                   HeapWordSize << _shifter);
@@ -74,8 +78,8 @@
   return nextAddr;
 }
 
-HeapWord* CMBitMapRO::getNextUnmarkedWordAddress(HeapWord* addr,
-                                                 HeapWord* limit) const {
+HeapWord* CMBitMapRO::getNextUnmarkedWordAddress(const HeapWord* addr,
+                                                 const HeapWord* limit) const {
   size_t addrOffset = heapWordToOffset(addr);
   if (limit == NULL) {
     limit = _bmStartWord + _bmWordSize;
@@ -95,12 +99,12 @@
 }
 
 #ifndef PRODUCT
-bool CMBitMapRO::covers(ReservedSpace heap_rs) const {
+bool CMBitMapRO::covers(MemRegion heap_rs) const {
   // assert(_bm.map() == _virtual_space.low(), "map inconsistency");
   assert(((size_t)_bm.size() * ((size_t)1 << _shifter)) == _bmWordSize,
          "size inconsistency");
-  return _bmStartWord == (HeapWord*)(heap_rs.base()) &&
-         _bmWordSize  == heap_rs.size()>>LogHeapWordSize;
+  return _bmStartWord == (HeapWord*)(heap_rs.start()) &&
+         _bmWordSize  == heap_rs.word_size();
 }
 #endif
 
@@ -108,33 +112,73 @@
   _bm.print_on_error(st, prefix);
 }
 
-bool CMBitMap::allocate(ReservedSpace heap_rs) {
-  _bmStartWord = (HeapWord*)(heap_rs.base());
-  _bmWordSize  = heap_rs.size()/HeapWordSize;    // heap_rs.size() is in bytes
-  ReservedSpace brs(ReservedSpace::allocation_align_size_up(
-                     (_bmWordSize >> (_shifter + LogBitsPerByte)) + 1));
-  if (!brs.is_reserved()) {
-    warning("ConcurrentMark marking bit map allocation failure");
-    return false;
-  }
-  MemTracker::record_virtual_memory_type((address)brs.base(), mtGC);
-  // For now we'll just commit all of the bit map up front.
-  // Later on we'll try to be more parsimonious with swap.
-  if (!_virtual_space.initialize(brs, brs.size())) {
-    warning("ConcurrentMark marking bit map backing store failure");
-    return false;
-  }
-  assert(_virtual_space.committed_size() == brs.size(),
-         "didn't reserve backing store for all of concurrent marking bit map?");
-  _bm.set_map((uintptr_t*)_virtual_space.low());
-  assert(_virtual_space.committed_size() << (_shifter + LogBitsPerByte) >=
-         _bmWordSize, "inconsistency in bit map sizing");
-  _bm.set_size(_bmWordSize >> _shifter);
-  return true;
+size_t CMBitMap::compute_size(size_t heap_size) {
+  return heap_size / mark_distance();
 }
 
+size_t CMBitMap::mark_distance() {
+  return MinObjAlignmentInBytes * BitsPerByte;
+}
+
+void CMBitMap::initialize(MemRegion heap, G1RegionToSpaceMapper* storage) {
+  _bmStartWord = heap.start();
+  _bmWordSize = heap.word_size();
+
+  _bm.set_map((BitMap::bm_word_t*) storage->reserved().start());
+  _bm.set_size(_bmWordSize >> _shifter);
+
+  storage->set_mapping_changed_listener(&_listener);
+}
+
+void CMBitMapMappingChangedListener::on_commit(uint start_region, size_t num_regions) {
+  // We need to clear the bitmap on commit, removing any existing information.
+  MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_region), num_regions * HeapRegion::GrainWords);
+  _bm->clearRange(mr);
+}
+
+// Closure used for clearing the given mark bitmap.
+class ClearBitmapHRClosure : public HeapRegionClosure {
+ private:
+  ConcurrentMark* _cm;
+  CMBitMap* _bitmap;
+  bool _may_yield;      // The closure may yield during iteration. If yielded, abort the iteration.
+ public:
+  ClearBitmapHRClosure(ConcurrentMark* cm, CMBitMap* bitmap, bool may_yield) : HeapRegionClosure(), _cm(cm), _bitmap(bitmap), _may_yield(may_yield) {
+    assert(!may_yield || cm != NULL, "CM must be non-NULL if this closure is expected to yield.");
+  }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    size_t const chunk_size_in_words = M / HeapWordSize;
+
+    HeapWord* cur = r->bottom();
+    HeapWord* const end = r->end();
+
+    while (cur < end) {
+      MemRegion mr(cur, MIN2(cur + chunk_size_in_words, end));
+      _bitmap->clearRange(mr);
+
+      cur += chunk_size_in_words;
+
+      // Abort iteration if after yielding the marking has been aborted.
+      if (_may_yield && _cm->do_yield_check() && _cm->has_aborted()) {
+        return true;
+      }
+      // Repeat the asserts from before the start of the closure. We will do them
+      // as asserts here to minimize their overhead on the product. However, we
+      // will have them as guarantees at the beginning / end of the bitmap
+      // clearing to get some checking in the product.
+      assert(!_may_yield || _cm->cmThread()->during_cycle(), "invariant");
+      assert(!_may_yield || !G1CollectedHeap::heap()->mark_in_progress(), "invariant");
+    }
+
+    return false;
+  }
+};
+
 void CMBitMap::clearAll() {
-  _bm.clear();
+  ClearBitmapHRClosure cl(NULL, this, false /* may_yield */);
+  G1CollectedHeap::heap()->heap_region_iterate(&cl);
+  guarantee(cl.complete(), "Must have completed iteration.");
   return;
 }
 
@@ -479,10 +523,10 @@
   return MAX2((n_par_threads + 2) / 4, 1U);
 }
 
-ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) :
+ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage) :
   _g1h(g1h),
-  _markBitMap1(log2_intptr(MinObjAlignment)),
-  _markBitMap2(log2_intptr(MinObjAlignment)),
+  _markBitMap1(),
+  _markBitMap2(),
   _parallel_marking_threads(0),
   _max_parallel_marking_threads(0),
   _sleep_factor(0.0),
@@ -491,7 +535,7 @@
   _cleanup_task_overhead(1.0),
   _cleanup_list("Cleanup List"),
   _region_bm((BitMap::idx_t)(g1h->max_regions()), false /* in_resource_area*/),
-  _card_bm((heap_rs.size() + CardTableModRefBS::card_size - 1) >>
+  _card_bm((g1h->reserved_region().byte_size() + CardTableModRefBS::card_size - 1) >>
             CardTableModRefBS::card_shift,
             false /* in_resource_area*/),
 
@@ -510,6 +554,7 @@
   _has_overflown(false),
   _concurrent(false),
   _has_aborted(false),
+  _aborted_gc_id(GCId::undefined()),
   _restart_for_overflow(false),
   _concurrent_marking_in_progress(false),
 
@@ -540,14 +585,8 @@
                            "heap end = " INTPTR_FORMAT, p2i(_heap_start), p2i(_heap_end));
   }
 
-  if (!_markBitMap1.allocate(heap_rs)) {
-    warning("Failed to allocate first CM bit map");
-    return;
-  }
-  if (!_markBitMap2.allocate(heap_rs)) {
-    warning("Failed to allocate second CM bit map");
-    return;
-  }
+  _markBitMap1.initialize(g1h->reserved_region(), prev_bitmap_storage);
+  _markBitMap2.initialize(g1h->reserved_region(), next_bitmap_storage);
 
   // Create & start a ConcurrentMark thread.
   _cmThread = new ConcurrentMarkThread(this);
@@ -558,8 +597,8 @@
   }
 
   assert(CGC_lock != NULL, "Where's the CGC_lock?");
-  assert(_markBitMap1.covers(heap_rs), "_markBitMap1 inconsistency");
-  assert(_markBitMap2.covers(heap_rs), "_markBitMap2 inconsistency");
+  assert(_markBitMap1.covers(g1h->reserved_region()), "_markBitMap1 inconsistency");
+  assert(_markBitMap2.covers(g1h->reserved_region()), "_markBitMap2 inconsistency");
 
   SATBMarkQueueSet& satb_qs = JavaThread::satb_mark_queue_set();
   satb_qs.set_buffer_size(G1SATBBufferSize);
@@ -719,38 +758,17 @@
   clear_all_count_data();
 
   // so that the call below can read a sensible value
-  _heap_start = (HeapWord*) heap_rs.base();
+  _heap_start = g1h->reserved_region().start();
   set_non_marking_state();
   _completed_initialization = true;
 }
 
-void ConcurrentMark::update_g1_committed(bool force) {
-  // If concurrent marking is not in progress, then we do not need to
-  // update _heap_end.
-  if (!concurrent_marking_in_progress() && !force) return;
-
-  MemRegion committed = _g1h->g1_committed();
-  assert(committed.start() == _heap_start, "start shouldn't change");
-  HeapWord* new_end = committed.end();
-  if (new_end > _heap_end) {
-    // The heap has been expanded.
-
-    _heap_end = new_end;
-  }
-  // Notice that the heap can also shrink. However, this only happens
-  // during a Full GC (at least currently) and the entire marking
-  // phase will bail out and the task will not be restarted. So, let's
-  // do nothing.
-}
-
 void ConcurrentMark::reset() {
   // Starting values for these two. This should be called in a STW
-  // phase. CM will be notified of any future g1_committed expansions
-  // will be at the end of evacuation pauses, when tasks are
-  // inactive.
-  MemRegion committed = _g1h->g1_committed();
-  _heap_start = committed.start();
-  _heap_end   = committed.end();
+  // phase.
+  MemRegion reserved = _g1h->g1_reserved();
+  _heap_start = reserved.start();
+  _heap_end   = reserved.end();
 
   // Separated the asserts so that we know which one fires.
   assert(_heap_start != NULL, "heap bounds should look ok");
@@ -822,7 +840,6 @@
     assert(out_of_regions(),
            err_msg("only way to get here: _finger: "PTR_FORMAT", _heap_end: "PTR_FORMAT,
                    p2i(_finger), p2i(_heap_end)));
-    update_g1_committed(true);
   }
 }
 
@@ -841,7 +858,6 @@
 
 void ConcurrentMark::clearNextBitmap() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  G1CollectorPolicy* g1p = g1h->g1_policy();
 
   // Make sure that the concurrent mark thread looks to still be in
   // the current cycle.
@@ -853,39 +869,38 @@
   // is the case.
   guarantee(!g1h->mark_in_progress(), "invariant");
 
-  // clear the mark bitmap (no grey objects to start with).
-  // We need to do this in chunks and offer to yield in between
-  // each chunk.
-  HeapWord* start  = _nextMarkBitMap->startWord();
-  HeapWord* end    = _nextMarkBitMap->endWord();
-  HeapWord* cur    = start;
-  size_t chunkSize = M;
-  while (cur < end) {
-    HeapWord* next = cur + chunkSize;
-    if (next > end) {
-      next = end;
-    }
-    MemRegion mr(cur,next);
-    _nextMarkBitMap->clearRange(mr);
-    cur = next;
-    do_yield_check();
+  ClearBitmapHRClosure cl(this, _nextMarkBitMap, true /* may_yield */);
+  g1h->heap_region_iterate(&cl);
 
-    // Repeat the asserts from above. We'll do them as asserts here to
-    // minimize their overhead on the product. However, we'll have
-    // them as guarantees at the beginning / end of the bitmap
-    // clearing to get some checking in the product.
-    assert(cmThread()->during_cycle(), "invariant");
-    assert(!g1h->mark_in_progress(), "invariant");
+  // Clear the liveness counting data. If the marking has been aborted, the abort()
+  // call already did that.
+  if (cl.complete()) {
+    clear_all_count_data();
   }
 
-  // Clear the liveness counting data
-  clear_all_count_data();
-
   // Repeat the asserts from above.
   guarantee(cmThread()->during_cycle(), "invariant");
   guarantee(!g1h->mark_in_progress(), "invariant");
 }
 
+class CheckBitmapClearHRClosure : public HeapRegionClosure {
+  CMBitMap* _bitmap;
+  bool _error;
+ public:
+  CheckBitmapClearHRClosure(CMBitMap* bitmap) : _bitmap(bitmap) {
+  }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    return _bitmap->getNextMarkedWordAddress(r->bottom(), r->end()) != r->end();
+  }
+};
+
+bool ConcurrentMark::nextMarkBitmapIsClear() {
+  CheckBitmapClearHRClosure cl(_nextMarkBitMap);
+  _g1h->heap_region_iterate(&cl);
+  return cl.complete();
+}
+
 class NoteStartOfMarkHRClosure: public HeapRegionClosure {
 public:
   bool doHeapRegion(HeapRegion* r) {
@@ -976,13 +991,13 @@
   }
 
   if (concurrent()) {
-    ConcurrentGCThread::stsLeave();
+    SuspendibleThreadSet::leave();
   }
 
   bool barrier_aborted = !_first_overflow_barrier_sync.enter();
 
   if (concurrent()) {
-    ConcurrentGCThread::stsJoin();
+    SuspendibleThreadSet::join();
   }
   // at this point everyone should have synced up and not be doing any
   // more work
@@ -1019,8 +1034,7 @@
       force_overflow()->update();
 
       if (G1Log::fine()) {
-        gclog_or_tty->date_stamp(PrintGCDateStamps);
-        gclog_or_tty->stamp(PrintGCTimeStamps);
+        gclog_or_tty->gclog_stamp(concurrent_gc_id());
         gclog_or_tty->print_cr("[GC concurrent-mark-reset-for-overflow]");
       }
     }
@@ -1036,13 +1050,13 @@
   }
 
   if (concurrent()) {
-    ConcurrentGCThread::stsLeave();
+    SuspendibleThreadSet::leave();
   }
 
   bool barrier_aborted = !_second_overflow_barrier_sync.enter();
 
   if (concurrent()) {
-    ConcurrentGCThread::stsJoin();
+    SuspendibleThreadSet::join();
   }
   // at this point everything should be re-initialized and ready to go
 
@@ -1094,7 +1108,7 @@
 
     double start_vtime = os::elapsedVTime();
 
-    ConcurrentGCThread::stsJoin();
+    SuspendibleThreadSet::join();
 
     assert(worker_id < _cm->active_tasks(), "invariant");
     CMTask* the_task = _cm->task(worker_id);
@@ -1121,9 +1135,9 @@
         if (!_cm->has_aborted() && the_task->has_aborted()) {
           sleep_time_ms =
             (jlong) (elapsed_vtime_sec * _cm->sleep_factor() * 1000.0);
-          ConcurrentGCThread::stsLeave();
+          SuspendibleThreadSet::leave();
           os::sleep(Thread::current(), sleep_time_ms, false);
-          ConcurrentGCThread::stsJoin();
+          SuspendibleThreadSet::join();
         }
         double end_time2_sec = os::elapsedTime();
         double elapsed_time2_sec = end_time2_sec - start_time_sec;
@@ -1141,7 +1155,7 @@
     the_task->record_end_time();
     guarantee(!the_task->has_aborted() || _cm->has_aborted(), "invariant");
 
-    ConcurrentGCThread::stsLeave();
+    SuspendibleThreadSet::leave();
 
     double end_vtime = os::elapsedVTime();
     _cm->update_accum_task_vtime(worker_id, end_vtime - start_vtime);
@@ -1221,6 +1235,9 @@
 };
 
 void ConcurrentMark::scanRootRegions() {
+  // Start of concurrent marking.
+  ClassLoaderDataGraph::clear_claimed_marks();
+
   // scan_in_progress() will have been set to true only if there was
   // at least one root region to scan. So, if it's false, we
   // should not attempt to do any further work.
@@ -1269,7 +1286,7 @@
   CMConcurrentMarkingTask markingTask(this, cmThread());
   if (use_parallel_marking_threads()) {
     _parallel_workers->set_active_workers((int)active_workers);
-    // Don't set _n_par_threads because it affects MT in proceess_strong_roots()
+    // Don't set _n_par_threads because it affects MT in process_roots()
     // and the decisions on that MT processing is made elsewhere.
     assert(_parallel_workers->active_workers() > 0, "Should have been set");
     _parallel_workers->run_task(&markingTask);
@@ -1300,6 +1317,7 @@
     Universe::verify(VerifyOption_G1UsePrevMarking,
                      " VerifyDuringGC:(before)");
   }
+  g1h->check_bitmaps("Remark Start");
 
   G1CollectorPolicy* g1p = g1h->g1_policy();
   g1p->record_concurrent_mark_remark_start();
@@ -1348,6 +1366,7 @@
       Universe::verify(VerifyOption_G1UseNextMarking,
                        " VerifyDuringGC:(after)");
     }
+    g1h->check_bitmaps("Remark End");
     assert(!restart_for_overflow(), "sanity");
     // Completely reset the marking state since marking completed
     set_non_marking_state();
@@ -1997,6 +2016,7 @@
     Universe::verify(VerifyOption_G1UsePrevMarking,
                      " VerifyDuringGC:(before)");
   }
+  g1h->check_bitmaps("Cleanup Start");
 
   G1CollectorPolicy* g1p = G1CollectedHeap::heap()->g1_policy();
   g1p->record_concurrent_mark_cleanup_start();
@@ -2034,8 +2054,8 @@
     // that calculated by walking the marking bitmap.
 
     // Bitmaps to hold expected values
-    BitMap expected_region_bm(_region_bm.size(), false);
-    BitMap expected_card_bm(_card_bm.size(), false);
+    BitMap expected_region_bm(_region_bm.size(), true);
+    BitMap expected_card_bm(_card_bm.size(), true);
 
     G1ParVerifyFinalCountTask g1_par_verify_task(g1h,
                                                  &_region_bm,
@@ -2137,22 +2157,30 @@
   // Update the soft reference policy with the new heap occupancy.
   Universe::update_heap_info_at_gc();
 
-  // We need to make this be a "collection" so any collection pause that
-  // races with it goes around and waits for completeCleanup to finish.
-  g1h->increment_total_collections();
-
-  // We reclaimed old regions so we should calculate the sizes to make
-  // sure we update the old gen/space data.
-  g1h->g1mm()->update_sizes();
-
   if (VerifyDuringGC) {
     HandleMark hm;  // handle scope
     Universe::heap()->prepare_for_verify();
     Universe::verify(VerifyOption_G1UsePrevMarking,
                      " VerifyDuringGC:(after)");
   }
+  g1h->check_bitmaps("Cleanup End");
 
   g1h->verify_region_sets_optional();
+
+  // We need to make this be a "collection" so any collection pause that
+  // races with it goes around and waits for completeCleanup to finish.
+  g1h->increment_total_collections();
+
+  // Clean out dead classes and update Metaspace sizes.
+  if (ClassUnloadingWithConcurrentMark) {
+    ClassLoaderDataGraph::purge();
+  }
+  MetaspaceGC::compute_new_size();
+
+  // We reclaimed old regions so we should calculate the sizes to make
+  // sure we update the old gen/space data.
+  g1h->g1mm()->update_sizes();
+
   g1h->trace_heap_after_concurrent_cycle();
 }
 
@@ -2170,10 +2198,10 @@
                            _cleanup_list.length());
   }
 
-  // Noone else should be accessing the _cleanup_list at this point,
-  // so it's not necessary to take any locks
+  // No one else should be accessing the _cleanup_list at this point,
+  // so it is not necessary to take any locks
   while (!_cleanup_list.is_empty()) {
-    HeapRegion* hr = _cleanup_list.remove_head();
+    HeapRegion* hr = _cleanup_list.remove_region(true /* from_head */);
     assert(hr != NULL, "Got NULL from a non-empty list");
     hr->par_clear();
     tmp_free_list.add_ordered(hr);
@@ -2382,6 +2410,8 @@
   }
 
   virtual void work(uint worker_id) {
+    ResourceMark rm;
+    HandleMark hm;
     CMTask* task = _cm->task(worker_id);
     G1CMIsAliveClosure g1_is_alive(_g1h);
     G1CMKeepAliveAndDrainClosure g1_par_keep_alive(_cm, task, false /* is_serial */);
@@ -2439,6 +2469,26 @@
   _g1h->set_par_threads(0);
 }
 
+void ConcurrentMark::weakRefsWorkParallelPart(BoolObjectClosure* is_alive, bool purged_classes) {
+  G1CollectedHeap::heap()->parallel_cleaning(is_alive, true, true, purged_classes);
+}
+
+// Helper class to get rid of some boilerplate code.
+class G1RemarkGCTraceTime : public GCTraceTime {
+  static bool doit_and_prepend(bool doit) {
+    if (doit) {
+      gclog_or_tty->put(' ');
+    }
+    return doit;
+  }
+
+ public:
+  G1RemarkGCTraceTime(const char* title, bool doit)
+    : GCTraceTime(title, doit_and_prepend(doit), false, G1CollectedHeap::heap()->gc_timer_cm(),
+        G1CollectedHeap::heap()->concurrent_mark()->concurrent_gc_id()) {
+  }
+};
+
 void ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) {
   if (has_overflown()) {
     // Skip processing the discovered references if we have
@@ -2464,7 +2514,7 @@
     if (G1Log::finer()) {
       gclog_or_tty->put(' ');
     }
-    GCTraceTime t("GC ref-proc", G1Log::finer(), false, g1h->gc_timer_cm());
+    GCTraceTime t("GC ref-proc", G1Log::finer(), false, g1h->gc_timer_cm(), concurrent_gc_id());
 
     ReferenceProcessor* rp = g1h->ref_processor_cm();
 
@@ -2521,7 +2571,8 @@
                                           &g1_keep_alive,
                                           &g1_drain_mark_stack,
                                           executor,
-                                          g1h->gc_timer_cm());
+                                          g1h->gc_timer_cm(),
+                                          concurrent_gc_id());
     g1h->gc_tracer_cm()->report_gc_reference_stats(stats);
 
     // The do_oop work routines of the keep_alive and drain_marking_stack
@@ -2550,9 +2601,31 @@
     return;
   }
 
-  g1h->unlink_string_and_symbol_table(&g1_is_alive,
-                                      /* process_strings */ false, // currently strings are always roots
-                                      /* process_symbols */ true);
+  assert(_markStack.isEmpty(), "Marking should have completed");
+
+  // Unload Klasses, String, Symbols, Code Cache, etc.
+  {
+    G1RemarkGCTraceTime trace("Unloading", G1Log::finer());
+
+    if (ClassUnloadingWithConcurrentMark) {
+      bool purged_classes;
+
+      {
+        G1RemarkGCTraceTime trace("System Dictionary Unloading", G1Log::finest());
+        purged_classes = SystemDictionary::do_unloading(&g1_is_alive);
+      }
+
+      {
+        G1RemarkGCTraceTime trace("Parallel Unloading", G1Log::finest());
+        weakRefsWorkParallelPart(&g1_is_alive, purged_classes);
+      }
+    }
+
+    if (G1StringDedup::is_enabled()) {
+      G1RemarkGCTraceTime trace("String Deduplication Unlink", G1Log::finest());
+      G1StringDedup::unlink(&g1_is_alive);
+    }
+  }
 }
 
 void ConcurrentMark::swapMarkBitMaps() {
@@ -2561,6 +2634,57 @@
   _nextMarkBitMap  = (CMBitMap*)  temp;
 }
 
+class CMObjectClosure;
+
+// Closure for iterating over objects, currently only used for
+// processing SATB buffers.
+class CMObjectClosure : public ObjectClosure {
+private:
+  CMTask* _task;
+
+public:
+  void do_object(oop obj) {
+    _task->deal_with_reference(obj);
+  }
+
+  CMObjectClosure(CMTask* task) : _task(task) { }
+};
+
+class G1RemarkThreadsClosure : public ThreadClosure {
+  CMObjectClosure _cm_obj;
+  G1CMOopClosure _cm_cl;
+  MarkingCodeBlobClosure _code_cl;
+  int _thread_parity;
+  bool _is_par;
+
+ public:
+  G1RemarkThreadsClosure(G1CollectedHeap* g1h, CMTask* task, bool is_par) :
+    _cm_obj(task), _cm_cl(g1h, g1h->concurrent_mark(), task), _code_cl(&_cm_cl, !CodeBlobToOopClosure::FixRelocations),
+    _thread_parity(SharedHeap::heap()->strong_roots_parity()), _is_par(is_par) {}
+
+  void do_thread(Thread* thread) {
+    if (thread->is_Java_thread()) {
+      if (thread->claim_oops_do(_is_par, _thread_parity)) {
+        JavaThread* jt = (JavaThread*)thread;
+
+        // In theory it should not be neccessary to explicitly walk the nmethods to find roots for concurrent marking
+        // however the liveness of oops reachable from nmethods have very complex lifecycles:
+        // * Alive if on the stack of an executing method
+        // * Weakly reachable otherwise
+        // Some objects reachable from nmethods, such as the class loader (or klass_holder) of the receiver should be
+        // live by the SATB invariant but other oops recorded in nmethods may behave differently.
+        jt->nmethods_do(&_code_cl);
+
+        jt->satb_mark_queue().apply_closure_and_empty(&_cm_obj);
+      }
+    } else if (thread->is_VM_thread()) {
+      if (thread->claim_oops_do(_is_par, _thread_parity)) {
+        JavaThread::satb_mark_queue_set().shared_satb_queue()->apply_closure_and_empty(&_cm_obj);
+      }
+    }
+  }
+};
+
 class CMRemarkTask: public AbstractGangTask {
 private:
   ConcurrentMark* _cm;
@@ -2572,6 +2696,14 @@
     if (worker_id < _cm->active_tasks()) {
       CMTask* task = _cm->task(worker_id);
       task->record_start_time();
+      {
+        ResourceMark rm;
+        HandleMark hm;
+
+        G1RemarkThreadsClosure threads_f(G1CollectedHeap::heap(), task, !_is_serial);
+        Threads::threads_do(&threads_f);
+      }
+
       do {
         task->do_marking_step(1000000000.0 /* something very large */,
                               true         /* do_termination       */,
@@ -2594,6 +2726,8 @@
   HandleMark   hm;
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
+  G1RemarkGCTraceTime trace("Finalize Marking", G1Log::finer());
+
   g1h->ensure_parsability(false);
 
   if (G1CollectedHeap::use_parallel_gc_threads()) {
@@ -2673,7 +2807,6 @@
       str = " O";
     } else {
       HeapRegion* hr  = _g1h->heap_region_containing(obj);
-      guarantee(hr != NULL, "invariant");
       bool over_tams = _g1h->allocated_since_marking(obj, hr, _vo);
       bool marked = _g1h->is_marked(obj, _vo);
 
@@ -2852,22 +2985,25 @@
     // claim_region() and a humongous object allocation might force us
     // to do a bit of unnecessary work (due to some unnecessary bitmap
     // iterations) but it should not introduce and correctness issues.
-    HeapRegion* curr_region   = _g1h->heap_region_containing_raw(finger);
-    HeapWord*   bottom        = curr_region->bottom();
-    HeapWord*   end           = curr_region->end();
-    HeapWord*   limit         = curr_region->next_top_at_mark_start();
+    HeapRegion* curr_region = _g1h->heap_region_containing_raw(finger);
 
-    if (verbose_low()) {
-      gclog_or_tty->print_cr("[%u] curr_region = "PTR_FORMAT" "
-                             "["PTR_FORMAT", "PTR_FORMAT"), "
-                             "limit = "PTR_FORMAT,
-                             worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit));
-    }
+    // Above heap_region_containing_raw may return NULL as we always scan claim
+    // until the end of the heap. In this case, just jump to the next region.
+    HeapWord* end = curr_region != NULL ? curr_region->end() : finger + HeapRegion::GrainWords;
 
     // Is the gap between reading the finger and doing the CAS too long?
     HeapWord* res = (HeapWord*) Atomic::cmpxchg_ptr(end, &_finger, finger);
-    if (res == finger) {
+    if (res == finger && curr_region != NULL) {
       // we succeeded
+      HeapWord*   bottom        = curr_region->bottom();
+      HeapWord*   limit         = curr_region->next_top_at_mark_start();
+
+      if (verbose_low()) {
+        gclog_or_tty->print_cr("[%u] curr_region = "PTR_FORMAT" "
+                               "["PTR_FORMAT", "PTR_FORMAT"), "
+                               "limit = "PTR_FORMAT,
+                               worker_id, p2i(curr_region), p2i(bottom), p2i(end), p2i(limit));
+      }
 
       // notice that _finger == end cannot be guaranteed here since,
       // someone else might have moved the finger even further
@@ -2898,10 +3034,17 @@
     } else {
       assert(_finger > finger, "the finger should have moved forward");
       if (verbose_low()) {
-        gclog_or_tty->print_cr("[%u] somebody else moved the finger, "
-                               "global finger = "PTR_FORMAT", "
-                               "our finger = "PTR_FORMAT,
-                               worker_id, p2i(_finger), p2i(finger));
+        if (curr_region == NULL) {
+          gclog_or_tty->print_cr("[%u] found uncommitted region, moving finger, "
+                                 "global finger = "PTR_FORMAT", "
+                                 "our finger = "PTR_FORMAT,
+                                 worker_id, p2i(_finger), p2i(finger));
+        } else {
+          gclog_or_tty->print_cr("[%u] somebody else moved the finger, "
+                                 "global finger = "PTR_FORMAT", "
+                                 "our finger = "PTR_FORMAT,
+                                 worker_id, p2i(_finger), p2i(finger));
+        }
       }
 
       // read it again
@@ -3016,8 +3159,10 @@
       // happens, heap_region_containing() will return the bottom of the
       // corresponding starts humongous region and the check below will
       // not hold any more.
+      // Since we always iterate over all regions, we might get a NULL HeapRegion
+      // here.
       HeapRegion* global_hr = _g1h->heap_region_containing_raw(global_finger);
-      guarantee(global_finger == global_hr->bottom(),
+      guarantee(global_hr == NULL || global_finger == global_hr->bottom(),
                 err_msg("global finger: "PTR_FORMAT" region: "HR_FORMAT,
                         p2i(global_finger), HR_FORMAT_PARAMS(global_hr)));
     }
@@ -3030,7 +3175,7 @@
       if (task_finger != NULL && task_finger < _heap_end) {
         // See above note on the global finger verification.
         HeapRegion* task_hr = _g1h->heap_region_containing_raw(task_finger);
-        guarantee(task_finger == task_hr->bottom() ||
+        guarantee(task_hr == NULL || task_finger == task_hr->bottom() ||
                   !task_hr->in_collection_set(),
                   err_msg("task finger: "PTR_FORMAT" region: "HR_FORMAT,
                           p2i(task_finger), HR_FORMAT_PARAMS(task_hr)));
@@ -3241,8 +3386,14 @@
 
 // abandon current marking iteration due to a Full GC
 void ConcurrentMark::abort() {
-  // Clear all marks to force marking thread to do nothing
+  // Clear all marks in the next bitmap for the next marking cycle. This will allow us to skip the next
+  // concurrent bitmap clearing.
   _nextMarkBitMap->clearAll();
+
+  // Note we cannot clear the previous marking bitmap here
+  // since VerifyDuringGC verifies the objects marked during
+  // a full GC against the previous bitmap.
+
   // Clear the liveness counting data
   clear_all_count_data();
   // Empty mark stack
@@ -3252,6 +3403,12 @@
   }
   _first_overflow_barrier_sync.abort();
   _second_overflow_barrier_sync.abort();
+  const GCId& gc_id = _g1h->gc_tracer_cm()->gc_id();
+  if (!gc_id.is_undefined()) {
+    // We can do multiple full GCs before ConcurrentMarkThread::run() gets a chance
+    // to detect that it was aborted. Only keep track of the first GC id that we aborted.
+    _aborted_gc_id = gc_id;
+   }
   _has_aborted = true;
 
   SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set();
@@ -3266,6 +3423,13 @@
   _g1h->register_concurrent_cycle_end();
 }
 
+const GCId& ConcurrentMark::concurrent_gc_id() {
+  if (has_aborted()) {
+    return _aborted_gc_id;
+  }
+  return _g1h->gc_tracer_cm()->gc_id();
+}
+
 static void print_ms_time_info(const char* prefix, const char* name,
                                NumberSeq& ns) {
   gclog_or_tty->print_cr("%s%5d %12s: total time = %8.2f s (avg = %8.2f ms).",
@@ -3322,21 +3486,17 @@
 
 // We take a break if someone is trying to stop the world.
 bool ConcurrentMark::do_yield_check(uint worker_id) {
-  if (should_yield()) {
+  if (SuspendibleThreadSet::should_yield()) {
     if (worker_id == 0) {
       _g1h->g1_policy()->record_concurrent_pause();
     }
-    cmThread()->yield();
+    SuspendibleThreadSet::yield();
     return true;
   } else {
     return false;
   }
 }
 
-bool ConcurrentMark::should_yield() {
-  return cmThread()->should_yield();
-}
-
 bool ConcurrentMark::containing_card_is_marked(void* p) {
   size_t offset = pointer_delta(p, _g1h->reserved_region().start(), 1);
   return _card_bm.at(offset >> CardTableModRefBS::card_shift);
@@ -3410,20 +3570,6 @@
   }
 };
 
-// Closure for iterating over objects, currently only used for
-// processing SATB buffers.
-class CMObjectClosure : public ObjectClosure {
-private:
-  CMTask* _task;
-
-public:
-  void do_object(oop obj) {
-    _task->deal_with_reference(obj);
-  }
-
-  CMObjectClosure(CMTask* task) : _task(task) { }
-};
-
 G1CMOopClosure::G1CMOopClosure(G1CollectedHeap* g1h,
                                ConcurrentMark* cm,
                                CMTask* task)
@@ -3437,9 +3583,8 @@
 }
 
 void CMTask::setup_for_region(HeapRegion* hr) {
-  // Separated the asserts so that we know which one fires.
   assert(hr != NULL,
-        "claim_region() should have filtered out continues humongous regions");
+        "claim_region() should have filtered out NULL regions");
   assert(!hr->continuesHumongous(),
         "claim_region() should have filtered out continues humongous regions");
 
@@ -3625,7 +3770,7 @@
 #endif // _MARKING_STATS_
 
   // (4) We check whether we should yield. If we have to, then we abort.
-  if (_cm->should_yield()) {
+  if (SuspendibleThreadSet::should_yield()) {
     // We should yield. To do this we abort the task. The caller is
     // responsible for yielding.
     set_has_aborted();
@@ -3889,15 +4034,6 @@
     }
   }
 
-  if (!concurrent() && !has_aborted()) {
-    // We should only do this during remark.
-    if (G1CollectedHeap::use_parallel_gc_threads()) {
-      satb_mq_set.par_iterate_closure_all_threads(_worker_id);
-    } else {
-      satb_mq_set.iterate_closure_all_threads();
-    }
-  }
-
   _draining_satb_buffers = false;
 
   assert(has_aborted() ||
@@ -4555,7 +4691,6 @@
     _hum_prev_live_bytes(0), _hum_next_live_bytes(0),
     _total_remset_bytes(0), _total_strong_code_roots_bytes(0) {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  MemRegion g1_committed = g1h->g1_committed();
   MemRegion g1_reserved = g1h->g1_reserved();
   double now = os::elapsedTime();
 
@@ -4563,10 +4698,8 @@
   _out->cr();
   _out->print_cr(G1PPRL_LINE_PREFIX" PHASE %s @ %1.3f", phase_name, now);
   _out->print_cr(G1PPRL_LINE_PREFIX" HEAP"
-                 G1PPRL_SUM_ADDR_FORMAT("committed")
                  G1PPRL_SUM_ADDR_FORMAT("reserved")
                  G1PPRL_SUM_BYTE_FORMAT("region-size"),
-                 p2i(g1_committed.start()), p2i(g1_committed.end()),
                  p2i(g1_reserved.start()), p2i(g1_reserved.end()),
                  HeapRegion::GrainBytes);
   _out->print_cr(G1PPRL_LINE_PREFIX);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp
index 8808ed1..45de4c0 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.hpp
@@ -25,10 +25,14 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_CONCURRENTMARK_HPP
 
+#include "classfile/javaClasses.hpp"
 #include "gc_implementation/g1/heapRegionSet.hpp"
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
+#include "gc_implementation/shared/gcId.hpp"
 #include "utilities/taskqueue.hpp"
 
 class G1CollectedHeap;
+class CMBitMap;
 class CMTask;
 typedef GenericTaskQueue<oop, mtGC>            CMTaskQueue;
 typedef GenericTaskQueueSet<CMTaskQueue, mtGC> CMTaskQueueSet;
@@ -55,7 +59,6 @@
   HeapWord* _bmStartWord;      // base address of range covered by map
   size_t    _bmWordSize;       // map size (in #HeapWords covered)
   const int _shifter;          // map to char or bit
-  VirtualSpace _virtual_space; // underlying the bit map
   BitMap    _bm;               // the bit map itself
 
  public:
@@ -85,19 +88,19 @@
   // Return the address corresponding to the next marked bit at or after
   // "addr", and before "limit", if "limit" is non-NULL.  If there is no
   // such bit, returns "limit" if that is non-NULL, or else "endWord()".
-  HeapWord* getNextMarkedWordAddress(HeapWord* addr,
-                                     HeapWord* limit = NULL) const;
+  HeapWord* getNextMarkedWordAddress(const HeapWord* addr,
+                                     const HeapWord* limit = NULL) const;
   // Return the address corresponding to the next unmarked bit at or after
   // "addr", and before "limit", if "limit" is non-NULL.  If there is no
   // such bit, returns "limit" if that is non-NULL, or else "endWord()".
-  HeapWord* getNextUnmarkedWordAddress(HeapWord* addr,
-                                       HeapWord* limit = NULL) const;
+  HeapWord* getNextUnmarkedWordAddress(const HeapWord* addr,
+                                       const HeapWord* limit = NULL) const;
 
   // conversion utilities
   HeapWord* offsetToHeapWord(size_t offset) const {
     return _bmStartWord + (offset << _shifter);
   }
-  size_t heapWordToOffset(HeapWord* addr) const {
+  size_t heapWordToOffset(const HeapWord* addr) const {
     return pointer_delta(addr, _bmStartWord) >> _shifter;
   }
   int heapWordDiffToOffsetDiff(size_t diff) const;
@@ -113,42 +116,41 @@
   void print_on_error(outputStream* st, const char* prefix) const;
 
   // debugging
-  NOT_PRODUCT(bool covers(ReservedSpace rs) const;)
+  NOT_PRODUCT(bool covers(MemRegion rs) const;)
+};
+
+class CMBitMapMappingChangedListener : public G1MappingChangedListener {
+ private:
+  CMBitMap* _bm;
+ public:
+  CMBitMapMappingChangedListener() : _bm(NULL) {}
+
+  void set_bitmap(CMBitMap* bm) { _bm = bm; }
+
+  virtual void on_commit(uint start_idx, size_t num_regions);
 };
 
 class CMBitMap : public CMBitMapRO {
+ private:
+  CMBitMapMappingChangedListener _listener;
 
  public:
-  // constructor
-  CMBitMap(int shifter) :
-    CMBitMapRO(shifter) {}
+  static size_t compute_size(size_t heap_size);
+  // Returns the amount of bytes on the heap between two marks in the bitmap.
+  static size_t mark_distance();
 
-  // Allocates the back store for the marking bitmap
-  bool allocate(ReservedSpace heap_rs);
+  CMBitMap() : CMBitMapRO(LogMinObjAlignment), _listener() { _listener.set_bitmap(this); }
 
-  // write marks
-  void mark(HeapWord* addr) {
-    assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
-           "outside underlying space?");
-    _bm.set_bit(heapWordToOffset(addr));
-  }
-  void clear(HeapWord* addr) {
-    assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
-           "outside underlying space?");
-    _bm.clear_bit(heapWordToOffset(addr));
-  }
-  bool parMark(HeapWord* addr) {
-    assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
-           "outside underlying space?");
-    return _bm.par_set_bit(heapWordToOffset(addr));
-  }
-  bool parClear(HeapWord* addr) {
-    assert(_bmStartWord <= addr && addr < (_bmStartWord + _bmWordSize),
-           "outside underlying space?");
-    return _bm.par_clear_bit(heapWordToOffset(addr));
-  }
+  // Initializes the underlying BitMap to cover the given area.
+  void initialize(MemRegion heap, G1RegionToSpaceMapper* storage);
+
+  // Write marks.
+  inline void mark(HeapWord* addr);
+  inline void clear(HeapWord* addr);
+  inline bool parMark(HeapWord* addr);
+  inline bool parClear(HeapWord* addr);
+
   void markRange(MemRegion mr);
-  void clearAll();
   void clearRange(MemRegion mr);
 
   // Starting at the bit corresponding to "addr" (inclusive), find the next
@@ -159,6 +161,9 @@
   // the run.  If there is no "1" bit at or after "addr", return an empty
   // MemRegion.
   MemRegion getAndClearMarkedRegion(HeapWord* addr, HeapWord* end_addr);
+
+  // Clear the whole mark bitmap.
+  void clearAll();
 };
 
 // Represents a marking stack used by ConcurrentMarking in the G1 collector.
@@ -444,6 +449,7 @@
   volatile bool           _concurrent;
   // set at the end of a Full GC so that marking aborts
   volatile bool           _has_aborted;
+  GCId                    _aborted_gc_id;
 
   // used when remark aborts due to an overflow to indicate that
   // another concurrent marking phase should start
@@ -474,6 +480,7 @@
   ForceOverflowSettings _force_overflow_conc;
   ForceOverflowSettings _force_overflow_stw;
 
+  void weakRefsWorkParallelPart(BoolObjectClosure* is_alive, bool purged_classes);
   void weakRefsWork(bool clear_all_soft_refs);
 
   void swapMarkBitMaps();
@@ -676,7 +683,7 @@
     return _task_queues->steal(worker_id, hash_seed, obj);
   }
 
-  ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs);
+  ConcurrentMark(G1CollectedHeap* g1h, G1RegionToSpaceMapper* prev_bitmap_storage, G1RegionToSpaceMapper* next_bitmap_storage);
   ~ConcurrentMark();
 
   ConcurrentMarkThread* cmThread() { return _cmThread; }
@@ -732,6 +739,10 @@
   // Clear the next marking bitmap (will be called concurrently).
   void clearNextBitmap();
 
+  // Return whether the next mark bitmap has no marks set. To be used for assertions
+  // only. Will not yield to pause requests.
+  bool nextMarkBitmapIsClear();
+
   // These two do the work that needs to be done before and after the
   // initial root checkpoint. Since this checkpoint can be done at two
   // different points (i.e. an explicit pause or piggy-backed on a
@@ -787,12 +798,6 @@
                            bool verify_thread_buffers,
                            bool verify_fingers) PRODUCT_RETURN;
 
-  // It is called at the end of an evacuation pause during marking so
-  // that CM is notified of where the new end of the heap is. It
-  // doesn't do anything if concurrent_marking_in_progress() is false,
-  // unless the force parameter is true.
-  void update_g1_committed(bool force = false);
-
   bool isMarked(oop p) const {
     assert(p != NULL && p->is_oop(), "expected an oop");
     HeapWord* addr = (HeapWord*)p;
@@ -818,13 +823,14 @@
   }
 
   inline bool do_yield_check(uint worker_i = 0);
-  inline bool should_yield();
 
   // Called to abort the marking cycle after a Full GC takes palce.
   void abort();
 
   bool has_aborted()      { return _has_aborted; }
 
+  const GCId& concurrent_gc_id();
+
   // This prints the global/local fingers. It is used for debugging.
   NOT_PRODUCT(void print_finger();)
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp
index 0627245..39536df 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.inline.hpp
@@ -268,6 +268,36 @@
   return iterate(cl, mr);
 }
 
+#define check_mark(addr)                                                       \
+  assert(_bmStartWord <= (addr) && (addr) < (_bmStartWord + _bmWordSize),      \
+         "outside underlying space?");                                         \
+  assert(G1CollectedHeap::heap()->is_in_exact(addr),                           \
+         err_msg("Trying to access not available bitmap "PTR_FORMAT            \
+                 " corresponding to "PTR_FORMAT" (%u)",                        \
+                 p2i(this), p2i(addr), G1CollectedHeap::heap()->addr_to_region(addr)));
+
+inline void CMBitMap::mark(HeapWord* addr) {
+  check_mark(addr);
+  _bm.set_bit(heapWordToOffset(addr));
+}
+
+inline void CMBitMap::clear(HeapWord* addr) {
+  check_mark(addr);
+  _bm.clear_bit(heapWordToOffset(addr));
+}
+
+inline bool CMBitMap::parMark(HeapWord* addr) {
+  check_mark(addr);
+  return _bm.par_set_bit(heapWordToOffset(addr));
+}
+
+inline bool CMBitMap::parClear(HeapWord* addr) {
+  check_mark(addr);
+  return _bm.par_clear_bit(heapWordToOffset(addr));
+}
+
+#undef check_mark
+
 inline void CMTask::push(oop obj) {
   HeapWord* objAddr = (HeapWord*) obj;
   assert(_g1h->is_in_g1_reserved(objAddr), "invariant");
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
index 5b396f2..b56e309 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.cpp
@@ -1,4 +1,4 @@
-/*
+ /*
  * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
@@ -29,6 +29,7 @@
 #include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MMUTracker.hpp"
 #include "gc_implementation/g1/vm_operations_g1.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "memory/resourceArea.hpp"
 #include "runtime/vmThread.hpp"
 
@@ -109,8 +110,7 @@
       double scan_start = os::elapsedTime();
       if (!cm()->has_aborted()) {
         if (G1Log::fine()) {
-          gclog_or_tty->date_stamp(PrintGCDateStamps);
-          gclog_or_tty->stamp(PrintGCTimeStamps);
+          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
           gclog_or_tty->print_cr("[GC concurrent-root-region-scan-start]");
         }
 
@@ -118,8 +118,7 @@
 
         double scan_end = os::elapsedTime();
         if (G1Log::fine()) {
-          gclog_or_tty->date_stamp(PrintGCDateStamps);
-          gclog_or_tty->stamp(PrintGCTimeStamps);
+          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
           gclog_or_tty->print_cr("[GC concurrent-root-region-scan-end, %1.7lf secs]",
                                  scan_end - scan_start);
         }
@@ -127,8 +126,7 @@
 
       double mark_start_sec = os::elapsedTime();
       if (G1Log::fine()) {
-        gclog_or_tty->date_stamp(PrintGCDateStamps);
-        gclog_or_tty->stamp(PrintGCTimeStamps);
+        gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
         gclog_or_tty->print_cr("[GC concurrent-mark-start]");
       }
 
@@ -151,8 +149,7 @@
           }
 
           if (G1Log::fine()) {
-            gclog_or_tty->date_stamp(PrintGCDateStamps);
-            gclog_or_tty->stamp(PrintGCTimeStamps);
+            gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
             gclog_or_tty->print_cr("[GC concurrent-mark-end, %1.7lf secs]",
                                       mark_end_sec - mark_start_sec);
           }
@@ -167,8 +164,7 @@
                                    "in remark (restart #%d).", iter);
           }
           if (G1Log::fine()) {
-            gclog_or_tty->date_stamp(PrintGCDateStamps);
-            gclog_or_tty->stamp(PrintGCTimeStamps);
+            gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
             gclog_or_tty->print_cr("[GC concurrent-mark-restart-for-overflow]");
           }
         }
@@ -194,9 +190,8 @@
       } else {
         // We don't want to update the marking status if a GC pause
         // is already underway.
-        _sts.join();
+        SuspendibleThreadSetJoiner sts;
         g1h->set_marking_complete();
-        _sts.leave();
       }
 
       // Check if cleanup set the free_regions_coming flag. If it
@@ -212,8 +207,7 @@
 
         double cleanup_start_sec = os::elapsedTime();
         if (G1Log::fine()) {
-          gclog_or_tty->date_stamp(PrintGCDateStamps);
-          gclog_or_tty->stamp(PrintGCTimeStamps);
+          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
           gclog_or_tty->print_cr("[GC concurrent-cleanup-start]");
         }
 
@@ -233,8 +227,7 @@
 
         double cleanup_end_sec = os::elapsedTime();
         if (G1Log::fine()) {
-          gclog_or_tty->date_stamp(PrintGCDateStamps);
-          gclog_or_tty->stamp(PrintGCTimeStamps);
+          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
           gclog_or_tty->print_cr("[GC concurrent-cleanup-end, %1.7lf secs]",
                                  cleanup_end_sec - cleanup_start_sec);
         }
@@ -266,46 +259,47 @@
       // record_concurrent_mark_cleanup_completed() (and, in fact, it's
       // not needed any more as the concurrent mark state has been
       // already reset).
-      _sts.join();
-      if (!cm()->has_aborted()) {
-        g1_policy->record_concurrent_mark_cleanup_completed();
+      {
+        SuspendibleThreadSetJoiner sts;
+        if (!cm()->has_aborted()) {
+          g1_policy->record_concurrent_mark_cleanup_completed();
+        }
       }
-      _sts.leave();
 
       if (cm()->has_aborted()) {
         if (G1Log::fine()) {
-          gclog_or_tty->date_stamp(PrintGCDateStamps);
-          gclog_or_tty->stamp(PrintGCTimeStamps);
+          gclog_or_tty->gclog_stamp(cm()->concurrent_gc_id());
           gclog_or_tty->print_cr("[GC concurrent-mark-abort]");
         }
       }
 
       // We now want to allow clearing of the marking bitmap to be
       // suspended by a collection pause.
-      _sts.join();
-      _cm->clearNextBitmap();
-      _sts.leave();
+      // We may have aborted just before the remark. Do not bother clearing the
+      // bitmap then, as it has been done during mark abort.
+      if (!cm()->has_aborted()) {
+        SuspendibleThreadSetJoiner sts;
+        _cm->clearNextBitmap();
+      } else {
+        assert(!G1VerifyBitmaps || _cm->nextMarkBitmapIsClear(), "Next mark bitmap must be clear");
+      }
     }
 
     // Update the number of full collections that have been
     // completed. This will also notify the FullGCCount_lock in case a
     // Java thread is waiting for a full GC to happen (e.g., it
     // called System.gc() with +ExplicitGCInvokesConcurrent).
-    _sts.join();
-    g1h->increment_old_marking_cycles_completed(true /* concurrent */);
-    g1h->register_concurrent_cycle_end();
-    _sts.leave();
+    {
+      SuspendibleThreadSetJoiner sts;
+      g1h->increment_old_marking_cycles_completed(true /* concurrent */);
+      g1h->register_concurrent_cycle_end();
+    }
   }
   assert(_should_terminate, "just checking");
 
   terminate();
 }
 
-
-void ConcurrentMarkThread::yield() {
-  _sts.yield("Concurrent Mark");
-}
-
 void ConcurrentMarkThread::stop() {
   {
     MutexLockerEx ml(Terminator_lock);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp
index 5f3d9ee..caa7f42 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMarkThread.hpp
@@ -89,9 +89,6 @@
   // that started() is set and set in_progress().
   bool during_cycle()      { return started() || in_progress(); }
 
-  // Yield for GC
-  void            yield();
-
   // shutdown
   void stop();
 };
diff --git a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
index 1168343..6e84e51 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.cpp
@@ -70,7 +70,7 @@
 
 DirtyCardQueueSet::DirtyCardQueueSet(bool notify_when_complete) :
   PtrQueueSet(notify_when_complete),
-  _closure(NULL),
+  _mut_process_closure(NULL),
   _shared_dirty_card_queue(this, true /*perm*/),
   _free_ids(NULL),
   _processed_buffers_mut(0), _processed_buffers_rs_thread(0)
@@ -83,10 +83,11 @@
   return (uint)os::processor_count();
 }
 
-void DirtyCardQueueSet::initialize(Monitor* cbl_mon, Mutex* fl_lock,
+void DirtyCardQueueSet::initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
                                    int process_completed_threshold,
                                    int max_completed_queue,
                                    Mutex* lock, PtrQueueSet* fl_owner) {
+  _mut_process_closure = cl;
   PtrQueueSet::initialize(cbl_mon, fl_lock, process_completed_threshold,
                           max_completed_queue, fl_owner);
   set_buffer_size(G1UpdateBufferSize);
@@ -98,18 +99,15 @@
   t->dirty_card_queue().handle_zero_index();
 }
 
-void DirtyCardQueueSet::set_closure(CardTableEntryClosure* closure) {
-  _closure = closure;
-}
-
-void DirtyCardQueueSet::iterate_closure_all_threads(bool consume,
+void DirtyCardQueueSet::iterate_closure_all_threads(CardTableEntryClosure* cl,
+                                                    bool consume,
                                                     uint worker_i) {
   assert(SafepointSynchronize::is_at_safepoint(), "Must be at safepoint.");
   for(JavaThread* t = Threads::first(); t; t = t->next()) {
-    bool b = t->dirty_card_queue().apply_closure(_closure, consume);
+    bool b = t->dirty_card_queue().apply_closure(cl, consume);
     guarantee(b, "Should not be interrupted.");
   }
-  bool b = shared_dirty_card_queue()->apply_closure(_closure,
+  bool b = shared_dirty_card_queue()->apply_closure(cl,
                                                     consume,
                                                     worker_i);
   guarantee(b, "Should not be interrupted.");
@@ -143,7 +141,7 @@
 
   bool b = false;
   if (worker_i != UINT_MAX) {
-    b = DirtyCardQueue::apply_closure_to_buffer(_closure, buf, 0,
+    b = DirtyCardQueue::apply_closure_to_buffer(_mut_process_closure, buf, 0,
                                                 _sz, true, worker_i);
     if (b) Atomic::inc(&_processed_buffers_mut);
 
@@ -218,18 +216,11 @@
   return res;
 }
 
-bool DirtyCardQueueSet::apply_closure_to_completed_buffer(uint worker_i,
-                                                          int stop_at,
-                                                          bool during_pause) {
-  return apply_closure_to_completed_buffer(_closure, worker_i,
-                                           stop_at, during_pause);
-}
-
-void DirtyCardQueueSet::apply_closure_to_all_completed_buffers() {
+void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
   BufferNode* nd = _completed_buffers_head;
   while (nd != NULL) {
     bool b =
-      DirtyCardQueue::apply_closure_to_buffer(_closure,
+      DirtyCardQueue::apply_closure_to_buffer(cl,
                                               BufferNode::make_buffer_from_node(nd),
                                               0, _sz, false);
     guarantee(b, "Should not stop early.");
@@ -237,6 +228,24 @@
   }
 }
 
+void DirtyCardQueueSet::par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) {
+  BufferNode* nd = _cur_par_buffer_node;
+  while (nd != NULL) {
+    BufferNode* next = (BufferNode*)nd->next();
+    BufferNode* actual = (BufferNode*)Atomic::cmpxchg_ptr((void*)next, (volatile void*)&_cur_par_buffer_node, (void*)nd);
+    if (actual == nd) {
+      bool b =
+        DirtyCardQueue::apply_closure_to_buffer(cl,
+                                                BufferNode::make_buffer_from_node(actual),
+                                                0, _sz, false);
+      guarantee(b, "Should not stop early.");
+      nd = next;
+    } else {
+      nd = actual;
+    }
+  }
+}
+
 // Deallocates any completed log buffers
 void DirtyCardQueueSet::clear() {
   BufferNode* buffers_to_delete = NULL;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp
index 0412c89..ac066a0 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/dirtyCardQueue.hpp
@@ -73,7 +73,8 @@
 
 
 class DirtyCardQueueSet: public PtrQueueSet {
-  CardTableEntryClosure* _closure;
+  // The closure used in mut_process_buffer().
+  CardTableEntryClosure* _mut_process_closure;
 
   DirtyCardQueue _shared_dirty_card_queue;
 
@@ -88,10 +89,12 @@
   jint _processed_buffers_mut;
   jint _processed_buffers_rs_thread;
 
+  // Current buffer node used for parallel iteration.
+  BufferNode* volatile _cur_par_buffer_node;
 public:
   DirtyCardQueueSet(bool notify_when_complete = true);
 
-  void initialize(Monitor* cbl_mon, Mutex* fl_lock,
+  void initialize(CardTableEntryClosure* cl, Monitor* cbl_mon, Mutex* fl_lock,
                   int process_completed_threshold,
                   int max_completed_queue,
                   Mutex* lock, PtrQueueSet* fl_owner = NULL);
@@ -102,33 +105,15 @@
 
   static void handle_zero_index_for_thread(JavaThread* t);
 
-  // Register "blk" as "the closure" for all queues.  Only one such closure
-  // is allowed.  The "apply_closure_to_completed_buffer" method will apply
-  // this closure to a completed buffer, and "iterate_closure_all_threads"
-  // applies it to partially-filled buffers (the latter should only be done
-  // with the world stopped).
-  void set_closure(CardTableEntryClosure* closure);
-
-  // If there is a registered closure for buffers, apply it to all entries
-  // in all currently-active buffers.  This should only be applied at a
-  // safepoint.  (Currently must not be called in parallel; this should
-  // change in the future.)  If "consume" is true, processed entries are
-  // discarded.
-  void iterate_closure_all_threads(bool consume = true,
+  // Apply the given closure to all entries in all currently-active buffers.
+  // This should only be applied at a safepoint. (Currently must not be called
+  // in parallel; this should change in the future.)  If "consume" is true,
+  // processed entries are discarded.
+  void iterate_closure_all_threads(CardTableEntryClosure* cl,
+                                   bool consume = true,
                                    uint worker_i = 0);
 
   // If there exists some completed buffer, pop it, then apply the
-  // registered closure to all its elements, nulling out those elements
-  // processed.  If all elements are processed, returns "true".  If no
-  // completed buffers exist, returns false.  If a completed buffer exists,
-  // but is only partially completed before a "yield" happens, the
-  // partially completed buffer (with its processed elements set to NULL)
-  // is returned to the completed buffer set, and this call returns false.
-  bool apply_closure_to_completed_buffer(uint worker_i = 0,
-                                         int stop_at = 0,
-                                         bool during_pause = false);
-
-  // If there exists some completed buffer, pop it, then apply the
   // specified closure to all its elements, nulling out those elements
   // processed.  If all elements are processed, returns "true".  If no
   // completed buffers exist, returns false.  If a completed buffer exists,
@@ -149,7 +134,12 @@
 
   // Applies the current closure to all completed buffers,
   // non-consumptively.
-  void apply_closure_to_all_completed_buffers();
+  void apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
+
+  void reset_for_par_iteration() { _cur_par_buffer_node = _completed_buffers_head; }
+  // Applies the current closure to all completed buffers, non-consumptively.
+  // Parallel version.
+  void par_apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl);
 
   DirtyCardQueue* shared_dirty_card_queue() {
     return &_shared_dirty_card_queue;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp
index fdb1a78..a0d9947 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.cpp
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1AllocRegion.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 
 G1CollectedHeap* G1AllocRegion::_g1h = NULL;
 HeapRegion* G1AllocRegion::_dummy_region = NULL;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp
index 050490d..50cc9be 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.hpp
@@ -173,7 +173,7 @@
 
   // Should be called when we want to release the active region which
   // is returned after it's been retired.
-  HeapRegion* release();
+  virtual HeapRegion* release();
 
 #if G1_ALLOC_REGION_TRACING
   void trace(const char* str, size_t word_size = 0, HeapWord* result = NULL);
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.inline.hpp
index c096de3..4d5ff33 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1AllocRegion.inline.hpp
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1ALLOCREGION_INLINE_HPP
 
 #include "gc_implementation/g1/g1AllocRegion.hpp"
+#include "gc_implementation/g1/heapRegion.inline.hpp"
 
 inline HeapWord* G1AllocRegion::allocate(HeapRegion* alloc_region,
                                          size_t word_size,
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp
index ee8969d..fe5f636 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
 #include "memory/space.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
@@ -31,64 +32,37 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
+void G1BlockOffsetSharedArrayMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
+  // Nothing to do. The BOT is hard-wired to be part of the HeapRegion, and we cannot
+  // retrieve it here since this would cause firing of several asserts. The code
+  // executed after commit of a region already needs to do some re-initialization of
+  // the HeapRegion, so we combine that.
+}
+
 //////////////////////////////////////////////////////////////////////
 // G1BlockOffsetSharedArray
 //////////////////////////////////////////////////////////////////////
 
-G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion reserved,
-                                                   size_t init_word_size) :
-  _reserved(reserved), _end(NULL)
-{
-  size_t size = compute_size(reserved.word_size());
-  ReservedSpace rs(ReservedSpace::allocation_align_size_up(size));
-  if (!rs.is_reserved()) {
-    vm_exit_during_initialization("Could not reserve enough space for heap offset array");
-  }
-  if (!_vs.initialize(rs, 0)) {
-    vm_exit_during_initialization("Could not reserve enough space for heap offset array");
-  }
+G1BlockOffsetSharedArray::G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage) :
+  _reserved(), _end(NULL), _listener(), _offset_array(NULL) {
 
-  MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
+  _reserved = heap;
+  _end = NULL;
 
-  _offset_array = (u_char*)_vs.low_boundary();
-  resize(init_word_size);
+  MemRegion bot_reserved = storage->reserved();
+
+  _offset_array = (u_char*)bot_reserved.start();
+  _end = _reserved.end();
+
+  storage->set_mapping_changed_listener(&_listener);
+
   if (TraceBlockOffsetTable) {
     gclog_or_tty->print_cr("G1BlockOffsetSharedArray::G1BlockOffsetSharedArray: ");
     gclog_or_tty->print_cr("  "
                   "  rs.base(): " INTPTR_FORMAT
                   "  rs.size(): " INTPTR_FORMAT
                   "  rs end(): " INTPTR_FORMAT,
-                  rs.base(), rs.size(), rs.base() + rs.size());
-    gclog_or_tty->print_cr("  "
-                  "  _vs.low_boundary(): " INTPTR_FORMAT
-                  "  _vs.high_boundary(): " INTPTR_FORMAT,
-                  _vs.low_boundary(),
-                  _vs.high_boundary());
-  }
-}
-
-void G1BlockOffsetSharedArray::resize(size_t new_word_size) {
-  assert(new_word_size <= _reserved.word_size(), "Resize larger than reserved");
-  size_t new_size = compute_size(new_word_size);
-  size_t old_size = _vs.committed_size();
-  size_t delta;
-  char* high = _vs.high();
-  _end = _reserved.start() + new_word_size;
-  if (new_size > old_size) {
-    delta = ReservedSpace::page_align_size_up(new_size - old_size);
-    assert(delta > 0, "just checking");
-    if (!_vs.expand_by(delta)) {
-      // Do better than this for Merlin
-      vm_exit_out_of_memory(delta, OOM_MMAP_ERROR, "offset table expansion");
-    }
-    assert(_vs.high() == high + delta, "invalid expansion");
-    // Initialization of the contents is left to the
-    // G1BlockOffsetArray that uses it.
-  } else {
-    delta = ReservedSpace::page_align_size_down(old_size - new_size);
-    if (delta == 0) return;
-    _vs.shrink_by(delta);
-    assert(_vs.high() == high - delta, "invalid expansion");
+                  bot_reserved.start(), bot_reserved.byte_size(), bot_reserved.end());
   }
 }
 
@@ -98,6 +72,9 @@
   return (delta & right_n_bits(LogN_words)) == (size_t)NoBits;
 }
 
+void G1BlockOffsetSharedArray::set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
+  set_offset_array(index_for(left), index_for(right -1), offset);
+}
 
 //////////////////////////////////////////////////////////////////////
 // G1BlockOffsetArray
@@ -107,7 +84,7 @@
                                        MemRegion mr, bool init_to_zero) :
   G1BlockOffsetTable(mr.start(), mr.end()),
   _unallocated_block(_bottom),
-  _array(array), _csp(NULL),
+  _array(array), _gsp(NULL),
   _init_to_zero(init_to_zero) {
   assert(_bottom <= _end, "arguments out of order");
   if (!_init_to_zero) {
@@ -117,9 +94,8 @@
   }
 }
 
-void G1BlockOffsetArray::set_space(Space* sp) {
-  _sp = sp;
-  _csp = sp->toContiguousSpace();
+void G1BlockOffsetArray::set_space(G1OffsetTableContigSpace* sp) {
+  _gsp = sp;
 }
 
 // The arguments follow the normal convention of denoting
@@ -378,7 +354,7 @@
   }
   // Otherwise, find the block start using the table.
   HeapWord* q = block_at_or_preceding(addr, false, 0);
-  HeapWord* n = q + _sp->block_size(q);
+  HeapWord* n = q + block_size(q);
   return forward_to_block_containing_addr_const(q, n, addr);
 }
 
@@ -406,31 +382,17 @@
          err_msg("next_boundary is beyond the end of the covered region "
                  " next_boundary " PTR_FORMAT " _array->_end " PTR_FORMAT,
                  next_boundary, _array->_end));
-  if (csp() != NULL) {
-    if (addr >= csp()->top()) return csp()->top();
-    while (next_boundary < addr) {
-      while (n <= next_boundary) {
-        q = n;
-        oop obj = oop(q);
-        if (obj->klass_or_null() == NULL) return q;
-        n += obj->size();
-      }
-      assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
-      // [q, n) is the block that crosses the boundary.
-      alloc_block_work2(&next_boundary, &next_index, q, n);
+  if (addr >= gsp()->top()) return gsp()->top();
+  while (next_boundary < addr) {
+    while (n <= next_boundary) {
+      q = n;
+      oop obj = oop(q);
+      if (obj->klass_or_null() == NULL) return q;
+      n += block_size(q);
     }
-  } else {
-    while (next_boundary < addr) {
-      while (n <= next_boundary) {
-        q = n;
-        oop obj = oop(q);
-        if (obj->klass_or_null() == NULL) return q;
-        n += _sp->block_size(q);
-      }
-      assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
-      // [q, n) is the block that crosses the boundary.
-      alloc_block_work2(&next_boundary, &next_index, q, n);
-    }
+    assert(q <= next_boundary && n > next_boundary, "Consequence of loop");
+    // [q, n) is the block that crosses the boundary.
+    alloc_block_work2(&next_boundary, &next_index, q, n);
   }
   return forward_to_block_containing_addr_const(q, n, addr);
 }
@@ -638,7 +600,7 @@
   assert(_bottom <= addr && addr < _end,
          "addr must be covered by this Array");
   HeapWord* q = block_at_or_preceding(addr, true, _next_offset_index-1);
-  HeapWord* n = q + _sp->block_size(q);
+  HeapWord* n = q + block_size(q);
   return forward_to_block_containing_addr_const(q, n, addr);
 }
 
@@ -651,6 +613,25 @@
   _next_offset_index = 0;
 }
 
+HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold_raw() {
+  assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
+         "just checking");
+  _next_offset_index = _array->index_for_raw(_bottom);
+  _next_offset_index++;
+  _next_offset_threshold =
+    _array->address_for_index_raw(_next_offset_index);
+  return _next_offset_threshold;
+}
+
+void G1BlockOffsetArrayContigSpace::zero_bottom_entry_raw() {
+  assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
+         "just checking");
+  size_t bottom_index = _array->index_for_raw(_bottom);
+  assert(_array->address_for_index_raw(bottom_index) == _bottom,
+         "Precondition of call");
+  _array->set_offset_array_raw(bottom_index, 0);
+}
+
 HeapWord* G1BlockOffsetArrayContigSpace::initialize_threshold() {
   assert(!Universe::heap()->is_in_reserved(_array->_offset_array),
          "just checking");
@@ -675,8 +656,7 @@
   assert(new_top <= _end, "_end should have already been updated");
 
   // The first BOT entry should have offset 0.
-  zero_bottom_entry();
-  initialize_threshold();
+  reset_bot();
   alloc_block(_bottom, new_top);
  }
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp
index 99f3da6..f3c7973 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_HPP
 
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
 #include "memory/memRegion.hpp"
 #include "runtime/virtualspace.hpp"
 #include "utilities/globalDefinitions.hpp"
@@ -52,8 +53,8 @@
 // consolidation.
 
 // Forward declarations
-class ContiguousSpace;
 class G1BlockOffsetSharedArray;
+class G1OffsetTableContigSpace;
 
 class G1BlockOffsetTable VALUE_OBJ_CLASS_SPEC {
   friend class VMStructs;
@@ -106,6 +107,11 @@
   inline HeapWord* block_start_const(const void* addr) const;
 };
 
+class G1BlockOffsetSharedArrayMappingChangedListener : public G1MappingChangedListener {
+ public:
+  virtual void on_commit(uint start_idx, size_t num_regions);
+};
+
 // This implementation of "G1BlockOffsetTable" divides the covered region
 // into "N"-word subregions (where "N" = 2^"LogN".  An array with an entry
 // for each such subregion indicates how far back one must go to find the
@@ -125,6 +131,7 @@
   friend class VMStructs;
 
 private:
+  G1BlockOffsetSharedArrayMappingChangedListener _listener;
   // The reserved region covered by the shared array.
   MemRegion _reserved;
 
@@ -133,16 +140,8 @@
 
   // Array for keeping offsets for retrieving object start fast given an
   // address.
-  VirtualSpace _vs;
   u_char* _offset_array;          // byte array keeping backwards offsets
 
-  void check_index(size_t index, const char* msg) const {
-    assert(index < _vs.committed_size(),
-           err_msg("%s - "
-                   "index: " SIZE_FORMAT ", _vs.committed_size: " SIZE_FORMAT,
-                   msg, index, _vs.committed_size()));
-  }
-
   void check_offset(size_t offset, const char* msg) const {
     assert(offset <= N_words,
            err_msg("%s - "
@@ -152,76 +151,33 @@
 
   // Bounds checking accessors:
   // For performance these have to devolve to array accesses in product builds.
-  u_char offset_array(size_t index) const {
-    check_index(index, "index out of range");
-    return _offset_array[index];
-  }
+  inline u_char offset_array(size_t index) const;
 
-  void set_offset_array(size_t index, u_char offset) {
-    check_index(index, "index out of range");
-    check_offset(offset, "offset too large");
+  void set_offset_array(HeapWord* left, HeapWord* right, u_char offset);
+
+  void set_offset_array_raw(size_t index, u_char offset) {
     _offset_array[index] = offset;
   }
 
-  void set_offset_array(size_t index, HeapWord* high, HeapWord* low) {
-    check_index(index, "index out of range");
-    assert(high >= low, "addresses out of order");
-    check_offset(pointer_delta(high, low), "offset too large");
-    _offset_array[index] = (u_char) pointer_delta(high, low);
-  }
+  inline void set_offset_array(size_t index, u_char offset);
 
-  void set_offset_array(HeapWord* left, HeapWord* right, u_char offset) {
-    check_index(index_for(right - 1), "right address out of range");
-    assert(left  < right, "Heap addresses out of order");
-    size_t num_cards = pointer_delta(right, left) >> LogN_words;
-    if (UseMemSetInBOT) {
-      memset(&_offset_array[index_for(left)], offset, num_cards);
-    } else {
-      size_t i = index_for(left);
-      const size_t end = i + num_cards;
-      for (; i < end; i++) {
-        _offset_array[i] = offset;
-      }
-    }
-  }
+  inline void set_offset_array(size_t index, HeapWord* high, HeapWord* low);
 
-  void set_offset_array(size_t left, size_t right, u_char offset) {
-    check_index(right, "right index out of range");
-    assert(left <= right, "indexes out of order");
-    size_t num_cards = right - left + 1;
-    if (UseMemSetInBOT) {
-      memset(&_offset_array[left], offset, num_cards);
-    } else {
-      size_t i = left;
-      const size_t end = i + num_cards;
-      for (; i < end; i++) {
-        _offset_array[i] = offset;
-      }
-    }
-  }
+  inline void set_offset_array(size_t left, size_t right, u_char offset);
 
-  void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const {
-    check_index(index, "index out of range");
-    assert(high >= low, "addresses out of order");
-    check_offset(pointer_delta(high, low), "offset too large");
-    assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset");
-  }
+  inline void check_offset_array(size_t index, HeapWord* high, HeapWord* low) const;
 
   bool is_card_boundary(HeapWord* p) const;
 
+public:
+
   // Return the number of slots needed for an offset array
   // that covers mem_region_words words.
-  // We always add an extra slot because if an object
-  // ends on a card boundary we put a 0 in the next
-  // offset array slot, so we want that slot always
-  // to be reserved.
-
-  size_t compute_size(size_t mem_region_words) {
-    size_t number_of_slots = (mem_region_words / N_words) + 1;
-    return ReservedSpace::page_align_size_up(number_of_slots);
+  static size_t compute_size(size_t mem_region_words) {
+    size_t number_of_slots = (mem_region_words / N_words);
+    return ReservedSpace::allocation_align_size_up(number_of_slots);
   }
 
-public:
   enum SomePublicConstants {
     LogN = 9,
     LogN_words = LogN - LogHeapWordSize,
@@ -235,25 +191,21 @@
   // least "init_word_size".) The contents of the initial table are
   // undefined; it is the responsibility of the constituent
   // G1BlockOffsetTable(s) to initialize cards.
-  G1BlockOffsetSharedArray(MemRegion reserved, size_t init_word_size);
-
-  // Notes a change in the committed size of the region covered by the
-  // table.  The "new_word_size" may not be larger than the size of the
-  // reserved region this table covers.
-  void resize(size_t new_word_size);
+  G1BlockOffsetSharedArray(MemRegion heap, G1RegionToSpaceMapper* storage);
 
   void set_bottom(HeapWord* new_bottom);
 
-  // Updates all the BlockOffsetArray's sharing this shared array to
-  // reflect the current "top"'s of their spaces.
-  void update_offset_arrays();
-
   // Return the appropriate index into "_offset_array" for "p".
   inline size_t index_for(const void* p) const;
+  inline size_t index_for_raw(const void* p) const;
 
   // Return the address indicating the start of the region corresponding to
   // "index" in "_offset_array".
   inline HeapWord* address_for_index(size_t index) const;
+  // Variant of address_for_index that does not check the index for validity.
+  inline HeapWord* address_for_index_raw(size_t index) const {
+    return _reserved.start() + (index << LogN_words);
+  }
 };
 
 // And here is the G1BlockOffsetTable subtype that uses the array.
@@ -281,11 +233,7 @@
   G1BlockOffsetSharedArray* _array;
 
   // The space that owns this subregion.
-  Space* _sp;
-
-  // If "_sp" is a contiguous space, the field below is the view of "_sp"
-  // as a contiguous space, else NULL.
-  ContiguousSpace* _csp;
+  G1OffsetTableContigSpace* _gsp;
 
   // If true, array entries are initialized to 0; otherwise, they are
   // initialized to point backwards to the beginning of the covered region.
@@ -310,7 +258,9 @@
 
 protected:
 
-  ContiguousSpace* csp() const { return _csp; }
+  G1OffsetTableContigSpace* gsp() const { return _gsp; }
+
+  inline size_t block_size(const HeapWord* p) const;
 
   // Returns the address of a block whose start is at most "addr".
   // If "has_max_index" is true, "assumes "max_index" is the last valid one
@@ -363,7 +313,7 @@
   // "this" to be passed as a parameter to a member constructor for
   // the containing concrete subtype of Space.
   // This would be legal C++, but MS VC++ doesn't allow it.
-  void set_space(Space* sp);
+  void set_space(G1OffsetTableContigSpace* sp);
 
   // Resets the covered region to the given "mr".
   void set_region(MemRegion mr);
@@ -495,6 +445,14 @@
                       blk_start, blk_end);
   }
 
+  // Variant of zero_bottom_entry that does not check for availability of the
+  // memory first.
+  void zero_bottom_entry_raw();
+  // Variant of initialize_threshold that does not check for availability of the
+  // memory first.
+  HeapWord* initialize_threshold_raw();
+  // Zero out the entry for _bottom (offset will be zero).
+  void zero_bottom_entry();
  public:
   G1BlockOffsetArrayContigSpace(G1BlockOffsetSharedArray* array, MemRegion mr);
 
@@ -502,8 +460,10 @@
   // bottom of the covered region.
   HeapWord* initialize_threshold();
 
-  // Zero out the entry for _bottom (offset will be zero).
-  void      zero_bottom_entry();
+  void reset_bot() {
+    zero_bottom_entry_raw();
+    initialize_threshold_raw();
+  }
 
   // Return the next threshold, the point at which the table should be
   // updated.
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
index 5ae3bc1..cd4ebd2 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.inline.hpp
@@ -26,6 +26,8 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1BLOCKOFFSETTABLE_INLINE_HPP
 
 #include "gc_implementation/g1/g1BlockOffsetTable.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "memory/space.hpp"
 
 inline HeapWord* G1BlockOffsetTable::block_start(const void* addr) {
@@ -45,14 +47,69 @@
   }
 }
 
+#define check_index(index, msg)                                                \
+  assert((index) < (_reserved.word_size() >> LogN_words),                      \
+         err_msg("%s - index: "SIZE_FORMAT", _vs.committed_size: "SIZE_FORMAT, \
+                 msg, (index), (_reserved.word_size() >> LogN_words)));        \
+  assert(G1CollectedHeap::heap()->is_in_exact(address_for_index_raw(index)),   \
+         err_msg("Index "SIZE_FORMAT" corresponding to "PTR_FORMAT             \
+                 " (%u) is not in committed area.",                            \
+                 (index),                                                      \
+                 p2i(address_for_index_raw(index)),                            \
+                 G1CollectedHeap::heap()->addr_to_region(address_for_index_raw(index))));
+
+u_char G1BlockOffsetSharedArray::offset_array(size_t index) const {
+  check_index(index, "index out of range");
+  return _offset_array[index];
+}
+
+void G1BlockOffsetSharedArray::set_offset_array(size_t index, u_char offset) {
+  check_index(index, "index out of range");
+  set_offset_array_raw(index, offset);
+}
+
+void G1BlockOffsetSharedArray::set_offset_array(size_t index, HeapWord* high, HeapWord* low) {
+  check_index(index, "index out of range");
+  assert(high >= low, "addresses out of order");
+  size_t offset = pointer_delta(high, low);
+  check_offset(offset, "offset too large");
+  set_offset_array(index, (u_char)offset);
+}
+
+void G1BlockOffsetSharedArray::set_offset_array(size_t left, size_t right, u_char offset) {
+  check_index(right, "right index out of range");
+  assert(left <= right, "indexes out of order");
+  size_t num_cards = right - left + 1;
+  if (UseMemSetInBOT) {
+    memset(&_offset_array[left], offset, num_cards);
+  } else {
+    size_t i = left;
+    const size_t end = i + num_cards;
+    for (; i < end; i++) {
+      _offset_array[i] = offset;
+    }
+  }
+}
+
+void G1BlockOffsetSharedArray::check_offset_array(size_t index, HeapWord* high, HeapWord* low) const {
+  check_index(index, "index out of range");
+  assert(high >= low, "addresses out of order");
+  check_offset(pointer_delta(high, low), "offset too large");
+  assert(_offset_array[index] == pointer_delta(high, low), "Wrong offset");
+}
+
+// Variant of index_for that does not check the index for validity.
+inline size_t G1BlockOffsetSharedArray::index_for_raw(const void* p) const {
+  return pointer_delta((char*)p, _reserved.start(), sizeof(char)) >> LogN;
+}
+
 inline size_t G1BlockOffsetSharedArray::index_for(const void* p) const {
   char* pc = (char*)p;
   assert(pc >= (char*)_reserved.start() &&
          pc <  (char*)_reserved.end(),
          err_msg("p (" PTR_FORMAT ") not in reserved [" PTR_FORMAT ", " PTR_FORMAT ")",
                  p2i(p), p2i(_reserved.start()), p2i(_reserved.end())));
-  size_t delta = pointer_delta(pc, _reserved.start(), sizeof(char));
-  size_t result = delta >> LogN;
+  size_t result = index_for_raw(p);
   check_index(result, "bad index from address");
   return result;
 }
@@ -60,7 +117,7 @@
 inline HeapWord*
 G1BlockOffsetSharedArray::address_for_index(size_t index) const {
   check_index(index, "index out of range");
-  HeapWord* result = _reserved.start() + (index << LogN_words);
+  HeapWord* result = address_for_index_raw(index);
   assert(result >= _reserved.start() && result < _reserved.end(),
          err_msg("bad address from index result " PTR_FORMAT
                  " _reserved.start() " PTR_FORMAT " _reserved.end() "
@@ -69,6 +126,13 @@
   return result;
 }
 
+#undef check_index
+
+inline size_t
+G1BlockOffsetArray::block_size(const HeapWord* p) const {
+  return gsp()->block_size(p);
+}
+
 inline HeapWord*
 G1BlockOffsetArray::block_at_or_preceding(const void* addr,
                                           bool has_max_index,
@@ -88,7 +152,7 @@
     // to go back by.
     size_t n_cards_back = BlockOffsetArray::entry_to_cards_back(offset);
     q -= (N_words * n_cards_back);
-    assert(q >= _sp->bottom(), "Went below bottom!");
+    assert(q >= gsp()->bottom(), "Went below bottom!");
     index -= n_cards_back;
     offset = _array->offset_array(index);
   }
@@ -101,21 +165,12 @@
 G1BlockOffsetArray::
 forward_to_block_containing_addr_const(HeapWord* q, HeapWord* n,
                                        const void* addr) const {
-  if (csp() != NULL) {
-    if (addr >= csp()->top()) return csp()->top();
-    while (n <= addr) {
-      q = n;
-      oop obj = oop(q);
-      if (obj->klass_or_null() == NULL) return q;
-      n += obj->size();
-    }
-  } else {
-    while (n <= addr) {
-      q = n;
-      oop obj = oop(q);
-      if (obj->klass_or_null() == NULL) return q;
-      n += _sp->block_size(q);
-    }
+  if (addr >= gsp()->top()) return gsp()->top();
+  while (n <= addr) {
+    q = n;
+    oop obj = oop(q);
+    if (obj->klass_or_null() == NULL) return q;
+    n += block_size(q);
   }
   assert(q <= n, "wrong order for q and addr");
   assert(addr < n, "wrong order for addr and n");
@@ -126,7 +181,7 @@
 G1BlockOffsetArray::forward_to_block_containing_addr(HeapWord* q,
                                                      const void* addr) {
   if (oop(q)->klass_or_null() == NULL) return q;
-  HeapWord* n = q + _sp->block_size(q);
+  HeapWord* n = q + block_size(q);
   // In the normal case, where the query "addr" is a card boundary, and the
   // offset table chunks are the same size as cards, the block starting at
   // "q" will contain addr, so the test below will fail, and we'll fall
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp
index 5e8cfb5..f9fd47c 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp
@@ -33,31 +33,26 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
+void G1CardCountsMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
+  MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_idx), num_regions * HeapRegion::GrainWords);
+  _counts->clear_range(mr);
+}
+
 void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) {
   if (has_count_table()) {
-    assert(from_card_num >= 0 && from_card_num < _committed_max_card_num,
-           err_msg("from card num out of range: "SIZE_FORMAT, from_card_num));
     assert(from_card_num < to_card_num,
            err_msg("Wrong order? from: " SIZE_FORMAT ", to: "SIZE_FORMAT,
                    from_card_num, to_card_num));
-    assert(to_card_num <= _committed_max_card_num,
-           err_msg("to card num out of range: "
-                   "to: "SIZE_FORMAT ", "
-                   "max: "SIZE_FORMAT,
-                   to_card_num, _committed_max_card_num));
-
-    to_card_num = MIN2(_committed_max_card_num, to_card_num);
-
     Copy::fill_to_bytes(&_card_counts[from_card_num], (to_card_num - from_card_num));
   }
 }
 
 G1CardCounts::G1CardCounts(G1CollectedHeap *g1h):
-  _g1h(g1h), _card_counts(NULL),
-  _reserved_max_card_num(0), _committed_max_card_num(0),
-  _committed_size(0) {}
+  _listener(), _g1h(g1h), _card_counts(NULL), _reserved_max_card_num(0) {
+  _listener.set_cardcounts(this);
+}
 
-void G1CardCounts::initialize() {
+void G1CardCounts::initialize(G1RegionToSpaceMapper* mapper) {
   assert(_g1h->max_capacity() > 0, "initialization order");
   assert(_g1h->capacity() == 0, "initialization order");
 
@@ -70,70 +65,9 @@
     _ct_bs = _g1h->g1_barrier_set();
     _ct_bot = _ct_bs->byte_for_const(_g1h->reserved_region().start());
 
-    // Allocate/Reserve the counts table
-    size_t reserved_bytes = _g1h->max_capacity();
-    _reserved_max_card_num = reserved_bytes >> CardTableModRefBS::card_shift;
-
-    size_t reserved_size = _reserved_max_card_num * sizeof(jbyte);
-    ReservedSpace rs(ReservedSpace::allocation_align_size_up(reserved_size));
-    if (!rs.is_reserved()) {
-      warning("Could not reserve enough space for the card counts table");
-      guarantee(!has_reserved_count_table(), "should be NULL");
-      return;
-    }
-
-    MemTracker::record_virtual_memory_type((address)rs.base(), mtGC);
-
-    _card_counts_storage.initialize(rs, 0);
-    _card_counts = (jubyte*) _card_counts_storage.low();
-  }
-}
-
-void G1CardCounts::resize(size_t heap_capacity) {
-  // Expand the card counts table to handle a heap with the given capacity.
-
-  if (!has_reserved_count_table()) {
-    // Don't expand if we failed to reserve the card counts table.
-    return;
-  }
-
-  assert(_committed_size ==
-         ReservedSpace::allocation_align_size_up(_committed_size),
-         err_msg("Unaligned? committed_size: " SIZE_FORMAT, _committed_size));
-
-  // Verify that the committed space for the card counts matches our
-  // committed max card num. Note for some allocation alignments, the
-  // amount of space actually committed for the counts table will be able
-  // to span more cards than the number spanned by the maximum heap.
-  size_t prev_committed_size = _committed_size;
-  size_t prev_committed_card_num = committed_to_card_num(prev_committed_size);
-
-  assert(prev_committed_card_num == _committed_max_card_num,
-         err_msg("Card mismatch: "
-                 "prev: " SIZE_FORMAT ", "
-                 "committed: "SIZE_FORMAT", "
-                 "reserved: "SIZE_FORMAT,
-                 prev_committed_card_num, _committed_max_card_num, _reserved_max_card_num));
-
-  size_t new_size = (heap_capacity >> CardTableModRefBS::card_shift) * sizeof(jbyte);
-  size_t new_committed_size = ReservedSpace::allocation_align_size_up(new_size);
-  size_t new_committed_card_num = committed_to_card_num(new_committed_size);
-
-  if (_committed_max_card_num < new_committed_card_num) {
-    // we need to expand the backing store for the card counts
-    size_t expand_size = new_committed_size - prev_committed_size;
-
-    if (!_card_counts_storage.expand_by(expand_size)) {
-      warning("Card counts table backing store commit failure");
-      return;
-    }
-    assert(_card_counts_storage.committed_size() == new_committed_size,
-           "expansion commit failure");
-
-    _committed_size = new_committed_size;
-    _committed_max_card_num = new_committed_card_num;
-
-    clear_range(prev_committed_card_num, _committed_max_card_num);
+    _card_counts = (jubyte*) mapper->reserved().start();
+    _reserved_max_card_num = mapper->reserved().byte_size();
+    mapper->set_mapping_changed_listener(&_listener);
   }
 }
 
@@ -149,12 +83,13 @@
   uint count = 0;
   if (has_count_table()) {
     size_t card_num = ptr_2_card_num(card_ptr);
-    if (card_num < _committed_max_card_num) {
-      count = (uint) _card_counts[card_num];
-      if (count < G1ConcRSHotCardLimit) {
-        _card_counts[card_num] =
-          (jubyte)(MIN2((uintx)(_card_counts[card_num] + 1), G1ConcRSHotCardLimit));
-      }
+    assert(card_num < _reserved_max_card_num,
+           err_msg("Card "SIZE_FORMAT" outside of card counts table (max size "SIZE_FORMAT")",
+                   card_num, _reserved_max_card_num));
+    count = (uint) _card_counts[card_num];
+    if (count < G1ConcRSHotCardLimit) {
+      _card_counts[card_num] =
+        (jubyte)(MIN2((uintx)(_card_counts[card_num] + 1), G1ConcRSHotCardLimit));
     }
   }
   return count;
@@ -165,31 +100,23 @@
 }
 
 void G1CardCounts::clear_region(HeapRegion* hr) {
-  assert(!hr->isHumongous(), "Should have been cleared");
+  MemRegion mr(hr->bottom(), hr->end());
+  clear_range(mr);
+}
+
+void G1CardCounts::clear_range(MemRegion mr) {
   if (has_count_table()) {
-    HeapWord* bottom = hr->bottom();
-
-    // We use the last address in hr as hr could be the
-    // last region in the heap. In which case trying to find
-    // the card for hr->end() will be an OOB accesss to the
-    // card table.
-    HeapWord* last = hr->end() - 1;
-    assert(_g1h->g1_committed().contains(last),
-           err_msg("last not in committed: "
-                   "last: " PTR_FORMAT ", "
-                   "committed: [" PTR_FORMAT ", " PTR_FORMAT ")",
-                   last,
-                   _g1h->g1_committed().start(),
-                   _g1h->g1_committed().end()));
-
-    const jbyte* from_card_ptr = _ct_bs->byte_for_const(bottom);
-    const jbyte* last_card_ptr = _ct_bs->byte_for_const(last);
+    const jbyte* from_card_ptr = _ct_bs->byte_for_const(mr.start());
+    // We use the last address in the range as the range could represent the
+    // last region in the heap. In which case trying to find the card will be an
+    // OOB access to the card table.
+    const jbyte* last_card_ptr = _ct_bs->byte_for_const(mr.last());
 
 #ifdef ASSERT
     HeapWord* start_addr = _ct_bs->addr_for(from_card_ptr);
-    assert(start_addr == hr->bottom(), "alignment");
+    assert(start_addr == mr.start(), "MemRegion start must be aligned to a card.");
     HeapWord* last_addr = _ct_bs->addr_for(last_card_ptr);
-    assert((last_addr + CardTableModRefBS::card_size_in_words) == hr->end(), "alignment");
+    assert((last_addr + CardTableModRefBS::card_size_in_words) == mr.end(), "MemRegion end must be aligned to a card.");
 #endif // ASSERT
 
     // Clear the counts for the (exclusive) card range.
@@ -199,14 +126,22 @@
   }
 }
 
+class G1CardCountsClearClosure : public HeapRegionClosure {
+ private:
+  G1CardCounts* _card_counts;
+ public:
+  G1CardCountsClearClosure(G1CardCounts* card_counts) :
+    HeapRegionClosure(), _card_counts(card_counts) { }
+
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    _card_counts->clear_region(r);
+    return false;
+  }
+};
+
 void G1CardCounts::clear_all() {
   assert(SafepointSynchronize::is_at_safepoint(), "don't call this otherwise");
-  clear_range((size_t)0, _committed_max_card_num);
+  G1CardCountsClearClosure cl(this);
+  _g1h->heap_region_iterate(&cl);
 }
-
-G1CardCounts::~G1CardCounts() {
-  if (has_reserved_count_table()) {
-    _card_counts_storage.release();
-  }
-}
-
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp
index ef08479..4252cba 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp
@@ -25,14 +25,26 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1CARDCOUNTS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1CARDCOUNTS_HPP
 
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
 #include "memory/allocation.hpp"
 #include "runtime/virtualspace.hpp"
 #include "utilities/globalDefinitions.hpp"
 
 class CardTableModRefBS;
+class G1CardCounts;
 class G1CollectedHeap;
+class G1RegionToSpaceMapper;
 class HeapRegion;
 
+class G1CardCountsMappingChangedListener : public G1MappingChangedListener {
+ private:
+  G1CardCounts* _counts;
+ public:
+  void set_cardcounts(G1CardCounts* counts) { _counts = counts; }
+
+  virtual void on_commit(uint start_idx, size_t num_regions);
+};
+
 // Table to track the number of times a card has been refined. Once
 // a card has been refined a certain number of times, it is
 // considered 'hot' and its refinement is delayed by inserting the
@@ -41,6 +53,8 @@
 // is 'drained' during the next evacuation pause.
 
 class G1CardCounts: public CHeapObj<mtGC> {
+  G1CardCountsMappingChangedListener _listener;
+
   G1CollectedHeap* _g1h;
 
   // The table of counts
@@ -49,27 +63,18 @@
   // Max capacity of the reserved space for the counts table
   size_t _reserved_max_card_num;
 
-  // Max capacity of the committed space for the counts table
-  size_t _committed_max_card_num;
-
-  // Size of committed space for the counts table
-  size_t _committed_size;
-
   // CardTable bottom.
   const jbyte* _ct_bot;
 
   // Barrier set
   CardTableModRefBS* _ct_bs;
 
-  // The virtual memory backing the counts table
-  VirtualSpace _card_counts_storage;
-
   // Returns true if the card counts table has been reserved.
   bool has_reserved_count_table() { return _card_counts != NULL; }
 
   // Returns true if the card counts table has been reserved and committed.
   bool has_count_table() {
-    return has_reserved_count_table() && _committed_max_card_num > 0;
+    return has_reserved_count_table();
   }
 
   size_t ptr_2_card_num(const jbyte* card_ptr) {
@@ -79,37 +84,24 @@
                    "_ct_bot: " PTR_FORMAT,
                    p2i(card_ptr), p2i(_ct_bot)));
     size_t card_num = pointer_delta(card_ptr, _ct_bot, sizeof(jbyte));
-    assert(card_num >= 0 && card_num < _committed_max_card_num,
+    assert(card_num >= 0 && card_num < _reserved_max_card_num,
            err_msg("card pointer out of range: " PTR_FORMAT, p2i(card_ptr)));
     return card_num;
   }
 
   jbyte* card_num_2_ptr(size_t card_num) {
-    assert(card_num >= 0 && card_num < _committed_max_card_num,
+    assert(card_num >= 0 && card_num < _reserved_max_card_num,
            err_msg("card num out of range: "SIZE_FORMAT, card_num));
     return (jbyte*) (_ct_bot + card_num);
   }
 
-  // Helper routine.
-  // Returns the number of cards that can be counted by the given committed
-  // table size, with a maximum of the number of cards spanned by the max
-  // capacity of the heap.
-  size_t committed_to_card_num(size_t committed_size) {
-    return MIN2(_reserved_max_card_num, committed_size / sizeof(jbyte));
-  }
-
   // Clear the counts table for the given (exclusive) index range.
   void clear_range(size_t from_card_num, size_t to_card_num);
 
  public:
   G1CardCounts(G1CollectedHeap* g1h);
-  ~G1CardCounts();
 
-  void initialize();
-
-  // Resize the committed space for the card counts table in
-  // response to a resize of the committed space for the heap.
-  void resize(size_t heap_capacity);
+  void initialize(G1RegionToSpaceMapper* mapper);
 
   // Increments the refinement count for the given card.
   // Returns the pre-increment count value.
@@ -122,8 +114,10 @@
   // Clears the card counts for the cards spanned by the region
   void clear_region(HeapRegion* hr);
 
+  // Clears the card counts for the cards spanned by the MemRegion
+  void clear_range(MemRegion mr);
+
   // Clear the entire card counts table during GC.
-  // Updates the policy stats with the duration.
   void clear_all();
 };
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp
index fb909d8..159a445 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp
@@ -30,49 +30,73 @@
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
-G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL) {
+G1CodeRootChunk::G1CodeRootChunk() : _top(NULL), _next(NULL), _prev(NULL), _free(NULL) {
   _top = bottom();
 }
 
 void G1CodeRootChunk::reset() {
   _next = _prev = NULL;
+  _free = NULL;
   _top = bottom();
 }
 
 void G1CodeRootChunk::nmethods_do(CodeBlobClosure* cl) {
-  nmethod** cur = bottom();
+  NmethodOrLink* cur = bottom();
   while (cur != _top) {
-    cl->do_code_blob(*cur);
+    if (is_nmethod(cur)) {
+      cl->do_code_blob(cur->_nmethod);
+    }
     cur++;
   }
 }
 
-FreeList<G1CodeRootChunk> G1CodeRootSet::_free_list;
-size_t G1CodeRootSet::_num_chunks_handed_out = 0;
+bool G1CodeRootChunk::remove_lock_free(nmethod* method) {
+  NmethodOrLink* cur = bottom();
 
-G1CodeRootChunk* G1CodeRootSet::new_chunk() {
-  G1CodeRootChunk* result = _free_list.get_chunk_at_head();
-  if (result == NULL) {
-    result = new G1CodeRootChunk();
+  for (NmethodOrLink* cur = bottom(); cur != _top; cur++) {
+    if (cur->_nmethod == method) {
+      bool result = Atomic::cmpxchg_ptr(NULL, &cur->_nmethod, method) == method;
+
+      if (!result) {
+        // Someone else cleared out this entry.
+        return false;
+      }
+
+      // The method was cleared. Time to link it into the free list.
+      NmethodOrLink* prev_free;
+      do {
+        prev_free = (NmethodOrLink*)_free;
+        cur->_link = prev_free;
+      } while (Atomic::cmpxchg_ptr(cur, &_free, prev_free) != prev_free);
+
+      return true;
+    }
   }
-  G1CodeRootSet::_num_chunks_handed_out++;
-  result->reset();
-  return result;
+
+  return false;
 }
 
-void G1CodeRootSet::free_chunk(G1CodeRootChunk* chunk) {
-  _free_list.return_chunk_at_head(chunk);
-  G1CodeRootSet::_num_chunks_handed_out--;
+G1CodeRootChunkManager::G1CodeRootChunkManager() : _free_list(), _num_chunks_handed_out(0) {
+  _free_list.initialize();
+  _free_list.set_size(G1CodeRootChunk::word_size());
 }
 
-void G1CodeRootSet::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
-  G1CodeRootSet::_num_chunks_handed_out -= list->count();
+size_t G1CodeRootChunkManager::fl_mem_size() {
+  return _free_list.count() * _free_list.size();
+}
+
+void G1CodeRootChunkManager::free_all_chunks(FreeList<G1CodeRootChunk>* list) {
+  _num_chunks_handed_out -= list->count();
   _free_list.prepend(list);
 }
 
-void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
-  size_t keep = G1CodeRootSet::_num_chunks_handed_out * keep_ratio / 100;
+void G1CodeRootChunkManager::free_chunk(G1CodeRootChunk* chunk) {
+  _free_list.return_chunk_at_head(chunk);
+  _num_chunks_handed_out--;
+}
 
+void G1CodeRootChunkManager::purge_chunks(size_t keep_ratio) {
+  size_t keep = _num_chunks_handed_out * keep_ratio / 100;
   if (keep >= (size_t)_free_list.count()) {
     return;
   }
@@ -90,20 +114,51 @@
   }
 }
 
-size_t G1CodeRootSet::static_mem_size() {
-  return sizeof(_free_list) + sizeof(_num_chunks_handed_out);
+size_t G1CodeRootChunkManager::static_mem_size() {
+  return sizeof(G1CodeRootChunkManager);
 }
 
-size_t G1CodeRootSet::fl_mem_size() {
-  return _free_list.count() * _free_list.size();
+
+G1CodeRootChunk* G1CodeRootChunkManager::new_chunk() {
+  G1CodeRootChunk* result = _free_list.get_chunk_at_head();
+  if (result == NULL) {
+    result = new G1CodeRootChunk();
+  }
+  _num_chunks_handed_out++;
+  result->reset();
+  return result;
 }
 
-void G1CodeRootSet::initialize() {
-  _free_list.initialize();
-  _free_list.set_size(G1CodeRootChunk::word_size());
+#ifndef PRODUCT
+
+size_t G1CodeRootChunkManager::num_chunks_handed_out() const {
+  return _num_chunks_handed_out;
 }
 
-G1CodeRootSet::G1CodeRootSet() : _list(), _length(0) {
+size_t G1CodeRootChunkManager::num_free_chunks() const {
+  return (size_t)_free_list.count();
+}
+
+#endif
+
+G1CodeRootChunkManager G1CodeRootSet::_default_chunk_manager;
+
+void G1CodeRootSet::purge_chunks(size_t keep_ratio) {
+  _default_chunk_manager.purge_chunks(keep_ratio);
+}
+
+size_t G1CodeRootSet::free_chunks_static_mem_size() {
+  return _default_chunk_manager.static_mem_size();
+}
+
+size_t G1CodeRootSet::free_chunks_mem_size() {
+  return _default_chunk_manager.fl_mem_size();
+}
+
+G1CodeRootSet::G1CodeRootSet(G1CodeRootChunkManager* manager) : _manager(manager), _list(), _length(0) {
+  if (_manager == NULL) {
+    _manager = &_default_chunk_manager;
+  }
   _list.initialize();
   _list.set_size(G1CodeRootChunk::word_size());
 }
@@ -114,34 +169,43 @@
 
 void G1CodeRootSet::add(nmethod* method) {
   if (!contains(method)) {
-    // Try to add the nmethod. If there is not enough space, get a new chunk.
-    if (_list.head() == NULL || _list.head()->is_full()) {
-      G1CodeRootChunk* cur = new_chunk();
+    // Find the first chunk that isn't full.
+    G1CodeRootChunk* cur = _list.head();
+    while (cur != NULL) {
+      if (!cur->is_full()) {
+        break;
+      }
+      cur = cur->next();
+    }
+
+    // All chunks are full, get a new chunk.
+    if (cur == NULL) {
+      cur = new_chunk();
       _list.return_chunk_at_head(cur);
     }
-    bool result = _list.head()->add(method);
+
+    // Add the nmethod.
+    bool result = cur->add(method);
+
     guarantee(result, err_msg("Not able to add nmethod "PTR_FORMAT" to newly allocated chunk.", method));
+
     _length++;
   }
 }
 
-void G1CodeRootSet::remove(nmethod* method) {
+void G1CodeRootSet::remove_lock_free(nmethod* method) {
   G1CodeRootChunk* found = find(method);
   if (found != NULL) {
-    bool result = found->remove(method);
-    guarantee(result, err_msg("could not find nmethod "PTR_FORMAT" during removal although we previously found it", method));
-    // eventually free completely emptied chunk
-    if (found->is_empty()) {
-      _list.remove_chunk(found);
-      free(found);
+    bool result = found->remove_lock_free(method);
+    if (result) {
+      Atomic::dec_ptr((volatile intptr_t*)&_length);
     }
-    _length--;
   }
   assert(!contains(method), err_msg(PTR_FORMAT" still contains nmethod "PTR_FORMAT, this, method));
 }
 
 nmethod* G1CodeRootSet::pop() {
-  do {
+  while (true) {
     G1CodeRootChunk* cur = _list.head();
     if (cur == NULL) {
       assert(_length == 0, "when there are no chunks, there should be no elements");
@@ -154,7 +218,7 @@
     } else {
       free(_list.get_chunk_at_head());
     }
-  } while (true);
+  }
 }
 
 G1CodeRootChunk* G1CodeRootSet::find(nmethod* method) {
@@ -189,28 +253,38 @@
   }
 }
 
+size_t G1CodeRootSet::static_mem_size() {
+  return sizeof(G1CodeRootSet);
+}
+
 size_t G1CodeRootSet::mem_size() {
-  return sizeof(this) + _list.count() * _list.size();
+  return G1CodeRootSet::static_mem_size() + _list.count() * _list.size();
 }
 
 #ifndef PRODUCT
 
 void G1CodeRootSet::test() {
-  initialize();
+  G1CodeRootChunkManager mgr;
 
-  assert(_free_list.count() == 0, "Free List must be empty");
-  assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet");
+  assert(mgr.num_chunks_handed_out() == 0, "Must not have handed out chunks yet");
+
+  assert(G1CodeRootChunkManager::static_mem_size() > sizeof(void*),
+         err_msg("The chunk manager's static memory usage seems too small, is only "SIZE_FORMAT" bytes.", G1CodeRootChunkManager::static_mem_size()));
 
   // The number of chunks that we allocate for purge testing.
   size_t const num_chunks = 10;
+
   {
-    G1CodeRootSet set1;
+    G1CodeRootSet set1(&mgr);
     assert(set1.is_empty(), "Code root set must be initially empty but is not.");
 
+    assert(G1CodeRootSet::static_mem_size() > sizeof(void*),
+           err_msg("The code root set's static memory usage seems too small, is only "SIZE_FORMAT" bytes", G1CodeRootSet::static_mem_size()));
+
     set1.add((nmethod*)1);
-    assert(_num_chunks_handed_out == 1,
+    assert(mgr.num_chunks_handed_out() == 1,
            err_msg("Must have allocated and handed out one chunk, but handed out "
-                   SIZE_FORMAT" chunks", _num_chunks_handed_out));
+                   SIZE_FORMAT" chunks", mgr.num_chunks_handed_out()));
     assert(set1.length() == 1, err_msg("Added exactly one element, but set contains "
                                        SIZE_FORMAT" elements", set1.length()));
 
@@ -219,19 +293,19 @@
     for (uint i = 0; i < G1CodeRootChunk::word_size() + 1; i++) {
       set1.add((nmethod*)1);
     }
-    assert(_num_chunks_handed_out == 1,
+    assert(mgr.num_chunks_handed_out() == 1,
            err_msg("Duplicate detection must have prevented allocation of further "
-                   "chunks but contains "SIZE_FORMAT, _num_chunks_handed_out));
+                   "chunks but allocated "SIZE_FORMAT, mgr.num_chunks_handed_out()));
     assert(set1.length() == 1,
            err_msg("Duplicate detection should not have increased the set size but "
                    "is "SIZE_FORMAT, set1.length()));
 
     size_t num_total_after_add = G1CodeRootChunk::word_size() + 1;
     for (size_t i = 0; i < num_total_after_add - 1; i++) {
-      set1.add((nmethod*)(2 + i));
+      set1.add((nmethod*)(uintptr_t)(2 + i));
     }
-    assert(_num_chunks_handed_out > 1,
-           "After adding more code roots, more than one chunks should have been handed out");
+    assert(mgr.num_chunks_handed_out() > 1,
+           "After adding more code roots, more than one additional chunk should have been handed out");
     assert(set1.length() == num_total_after_add,
            err_msg("After adding in total "SIZE_FORMAT" distinct code roots, they "
                    "need to be in the set, but there are only "SIZE_FORMAT,
@@ -244,27 +318,27 @@
     assert(num_popped == num_total_after_add,
            err_msg("Managed to pop "SIZE_FORMAT" code roots, but only "SIZE_FORMAT" "
                    "were added", num_popped, num_total_after_add));
-    assert(_num_chunks_handed_out == 0,
+    assert(mgr.num_chunks_handed_out() == 0,
            err_msg("After popping all elements, all chunks must have been returned "
-                   "but are still "SIZE_FORMAT, _num_chunks_handed_out));
+                   "but there are still "SIZE_FORMAT" additional", mgr.num_chunks_handed_out()));
 
-    purge_chunks(0);
-    assert(_free_list.count() == 0,
+    mgr.purge_chunks(0);
+    assert(mgr.num_free_chunks() == 0,
            err_msg("After purging everything, the free list must be empty but still "
-                   "contains "SIZE_FORMAT" chunks", _free_list.count()));
+                   "contains "SIZE_FORMAT" chunks", mgr.num_free_chunks()));
 
     // Add some more handed out chunks.
     size_t i = 0;
-    while (_num_chunks_handed_out < num_chunks) {
+    while (mgr.num_chunks_handed_out() < num_chunks) {
       set1.add((nmethod*)i);
       i++;
     }
 
     {
       // Generate chunks on the free list.
-      G1CodeRootSet set2;
+      G1CodeRootSet set2(&mgr);
       size_t i = 0;
-      while (_num_chunks_handed_out < num_chunks * 2) {
+      while (mgr.num_chunks_handed_out() < (num_chunks * 2)) {
         set2.add((nmethod*)i);
         i++;
       }
@@ -272,45 +346,45 @@
       // num_chunks elements on the free list.
     }
 
-    assert(_num_chunks_handed_out == num_chunks,
+    assert(mgr.num_chunks_handed_out() == num_chunks,
            err_msg("Deletion of the second set must have resulted in giving back "
-                   "those, but there is still "SIZE_FORMAT" handed out, expecting "
-                   SIZE_FORMAT, _num_chunks_handed_out, num_chunks));
-    assert((size_t)_free_list.count() == num_chunks,
+                   "those, but there are still "SIZE_FORMAT" additional handed out, expecting "
+                   SIZE_FORMAT, mgr.num_chunks_handed_out(), num_chunks));
+    assert(mgr.num_free_chunks() == num_chunks,
            err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
-                   "but there are only "SIZE_FORMAT, num_chunks, _free_list.count()));
+                   "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
 
     size_t const test_percentage = 50;
-    purge_chunks(test_percentage);
-    assert(_num_chunks_handed_out == num_chunks,
+    mgr.purge_chunks(test_percentage);
+    assert(mgr.num_chunks_handed_out() == num_chunks,
            err_msg("Purging must not hand out chunks but there are "SIZE_FORMAT,
-                   _num_chunks_handed_out));
-    assert((size_t)_free_list.count() == (ssize_t)(num_chunks * test_percentage / 100),
+                   mgr.num_chunks_handed_out()));
+    assert(mgr.num_free_chunks() == (size_t)(mgr.num_chunks_handed_out() * test_percentage / 100),
            err_msg("Must have purged "SIZE_FORMAT" percent of "SIZE_FORMAT" chunks"
-                   "but there are "SSIZE_FORMAT, test_percentage, num_chunks,
-                   _free_list.count()));
+                   "but there are "SIZE_FORMAT, test_percentage, num_chunks,
+                   mgr.num_free_chunks()));
     // Purge the remainder of the chunks on the free list.
-    purge_chunks(0);
-    assert(_free_list.count() == 0, "Free List must be empty");
-    assert(_num_chunks_handed_out == num_chunks,
+    mgr.purge_chunks(0);
+    assert(mgr.num_free_chunks() == 0, "Free List must be empty");
+    assert(mgr.num_chunks_handed_out() == num_chunks,
            err_msg("Expected to be "SIZE_FORMAT" chunks handed out from the first set "
-                   "but there are "SIZE_FORMAT, num_chunks, _num_chunks_handed_out));
+                   "but there are "SIZE_FORMAT, num_chunks, mgr.num_chunks_handed_out()));
 
     // Exit of the scope of the set1 object will call the destructor that generates
     // num_chunks additional elements on the free list.
-  }
+   }
 
-  assert(_num_chunks_handed_out == 0,
+  assert(mgr.num_chunks_handed_out() == 0,
          err_msg("Deletion of the only set must have resulted in no chunks handed "
-                 "out, but there is still "SIZE_FORMAT" handed out", _num_chunks_handed_out));
-  assert((size_t)_free_list.count() == num_chunks,
+                 "out, but there is still "SIZE_FORMAT" handed out", mgr.num_chunks_handed_out()));
+  assert(mgr.num_free_chunks() == num_chunks,
          err_msg("After freeing "SIZE_FORMAT" chunks, they must be on the free list "
-                 "but there are only "SSIZE_FORMAT, num_chunks, _free_list.count()));
+                 "but there are only "SIZE_FORMAT, num_chunks, mgr.num_free_chunks()));
 
   // Restore initial state.
-  purge_chunks(0);
-  assert(_free_list.count() == 0, "Free List must be empty");
-  assert(_num_chunks_handed_out == 0, "No elements must have been handed out yet");
+  mgr.purge_chunks(0);
+  assert(mgr.num_free_chunks() == 0, "Free List must be empty");
+  assert(mgr.num_chunks_handed_out() == 0, "No additional elements must have been handed out yet");
 }
 
 void TestCodeCacheRemSet_test() {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp
index ad8025c..c351330 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp
@@ -31,6 +31,14 @@
 
 class CodeBlobClosure;
 
+// The elements of the G1CodeRootChunk is either:
+//  1) nmethod pointers
+//  2) nodes in an internally chained free list
+typedef union {
+  nmethod* _nmethod;
+  void*    _link;
+} NmethodOrLink;
+
 class G1CodeRootChunk : public CHeapObj<mtGC> {
  private:
   static const int NUM_ENTRIES = 32;
@@ -38,16 +46,28 @@
   G1CodeRootChunk*     _next;
   G1CodeRootChunk*     _prev;
 
-  nmethod** _top;
+  NmethodOrLink*          _top;
+  // First free position within the chunk.
+  volatile NmethodOrLink* _free;
 
-  nmethod* _data[NUM_ENTRIES];
+  NmethodOrLink _data[NUM_ENTRIES];
 
-  nmethod** bottom() const {
-    return (nmethod**) &(_data[0]);
+  NmethodOrLink* bottom() const {
+    return (NmethodOrLink*) &(_data[0]);
   }
 
-  nmethod** end() const {
-    return (nmethod**) &(_data[NUM_ENTRIES]);
+  NmethodOrLink* end() const {
+    return (NmethodOrLink*) &(_data[NUM_ENTRIES]);
+  }
+
+  bool is_link(NmethodOrLink* nmethod_or_link) {
+    return nmethod_or_link->_link == NULL ||
+        (bottom() <= nmethod_or_link->_link
+        && nmethod_or_link->_link < end());
+  }
+
+  bool is_nmethod(NmethodOrLink* nmethod_or_link) {
+    return !is_link(nmethod_or_link);
   }
 
  public:
@@ -85,62 +105,97 @@
   }
 
   bool is_full() const {
-    return _top == (nmethod**)end();
+    return _top == end() && _free == NULL;
   }
 
   bool contains(nmethod* method) {
-    nmethod** cur = bottom();
+    NmethodOrLink* cur = bottom();
     while (cur != _top) {
-      if (*cur == method) return true;
+      if (cur->_nmethod == method) return true;
       cur++;
     }
     return false;
   }
 
   bool add(nmethod* method) {
-    if (is_full()) return false;
-    *_top = method;
-    _top++;
+    if (is_full()) {
+      return false;
+    }
+
+    if (_free != NULL) {
+      // Take from internally chained free list
+      NmethodOrLink* first_free = (NmethodOrLink*)_free;
+      _free = (NmethodOrLink*)_free->_link;
+      first_free->_nmethod = method;
+    } else {
+      // Take from top.
+      _top->_nmethod = method;
+      _top++;
+    }
+
     return true;
   }
 
-  bool remove(nmethod* method) {
-    nmethod** cur = bottom();
-    while (cur != _top) {
-      if (*cur == method) {
-        memmove(cur, cur + 1, (_top - (cur + 1)) * sizeof(nmethod**));
-        _top--;
-        return true;
-      }
-      cur++;
-    }
-    return false;
-  }
+  bool remove_lock_free(nmethod* method);
 
   void nmethods_do(CodeBlobClosure* blk);
 
   nmethod* pop() {
-    if (is_empty()) {
-      return NULL;
+    if (_free != NULL) {
+      // Kill the free list.
+      _free = NULL;
     }
-    _top--;
-    return *_top;
+
+    while (!is_empty()) {
+      _top--;
+      if (is_nmethod(_top)) {
+        return _top->_nmethod;
+      }
+    }
+
+    return NULL;
   }
 };
 
+// Manages free chunks.
+class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC {
+ private:
+  // Global free chunk list management
+  FreeList<G1CodeRootChunk> _free_list;
+  // Total number of chunks handed out
+  size_t _num_chunks_handed_out;
+
+ public:
+  G1CodeRootChunkManager();
+
+  G1CodeRootChunk* new_chunk();
+  void free_chunk(G1CodeRootChunk* chunk);
+  // Free all elements of the given list.
+  void free_all_chunks(FreeList<G1CodeRootChunk>* list);
+
+  void initialize();
+  void purge_chunks(size_t keep_ratio);
+
+  static size_t static_mem_size();
+  size_t fl_mem_size();
+
+#ifndef PRODUCT
+  size_t num_chunks_handed_out() const;
+  size_t num_free_chunks() const;
+#endif
+};
+
 // Implements storage for a set of code roots.
 // All methods that modify the set are not thread-safe except if otherwise noted.
 class G1CodeRootSet VALUE_OBJ_CLASS_SPEC {
  private:
-  // Global free chunk list management
-  static FreeList<G1CodeRootChunk> _free_list;
-  // Total number of chunks handed out
-  static size_t _num_chunks_handed_out;
+  // Global default free chunk manager instance.
+  static G1CodeRootChunkManager _default_chunk_manager;
 
-  static G1CodeRootChunk* new_chunk();
-  static void free_chunk(G1CodeRootChunk* chunk);
+  G1CodeRootChunk* new_chunk() { return _manager->new_chunk(); }
+  void free_chunk(G1CodeRootChunk* chunk) { _manager->free_chunk(chunk); }
   // Free all elements of the given list.
-  static void free_all_chunks(FreeList<G1CodeRootChunk>* list);
+  void free_all_chunks(FreeList<G1CodeRootChunk>* list) { _manager->free_all_chunks(list); }
 
   // Return the chunk that contains the given nmethod, NULL otherwise.
   // Scans the list of chunks backwards, as this method is used to add new
@@ -150,22 +205,24 @@
 
   size_t _length;
   FreeList<G1CodeRootChunk> _list;
+  G1CodeRootChunkManager* _manager;
 
  public:
-  G1CodeRootSet();
+  // If an instance is initialized with a chunk manager of NULL, use the global
+  // default one.
+  G1CodeRootSet(G1CodeRootChunkManager* manager = NULL);
   ~G1CodeRootSet();
 
-  static void initialize();
   static void purge_chunks(size_t keep_ratio);
 
-  static size_t static_mem_size();
-  static size_t fl_mem_size();
+  static size_t free_chunks_static_mem_size();
+  static size_t free_chunks_mem_size();
 
   // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this
   // method is likely to be repeatedly called with the same nmethod.
   void add(nmethod* method);
 
-  void remove(nmethod* method);
+  void remove_lock_free(nmethod* method);
   nmethod* pop();
 
   bool contains(nmethod* method);
@@ -179,6 +236,8 @@
   // Length in elements
   size_t length() const { return _length; }
 
+  // Static data memory size in bytes of this set.
+  static size_t static_mem_size();
   // Memory size in bytes taken by this set.
   size_t mem_size();
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
index 56d30fe..692b9ae 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp
@@ -42,26 +42,29 @@
 #include "gc_implementation/g1/g1Log.hpp"
 #include "gc_implementation/g1/g1MarkSweep.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
+#include "gc_implementation/g1/g1ParScanThreadState.inline.hpp"
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
 #include "gc_implementation/g1/g1RemSet.inline.hpp"
 #include "gc_implementation/g1/g1StringDedup.hpp"
 #include "gc_implementation/g1/g1YCTypes.hpp"
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
-#include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
 #include "gc_implementation/g1/vm_operations_g1.hpp"
 #include "gc_implementation/shared/gcHeapSummary.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcTraceTime.hpp"
 #include "gc_implementation/shared/isGCActiveMark.hpp"
+#include "memory/allocation.hpp"
 #include "memory/gcLocker.inline.hpp"
 #include "memory/generationSpec.hpp"
 #include "memory/iterator.hpp"
 #include "memory/referenceProcessor.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.pcgc.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/vmThread.hpp"
-#include "utilities/ticks.hpp"
 
 size_t G1CollectedHeap::_humongous_object_threshold_in_words = 0;
 
@@ -86,66 +89,64 @@
 // G1ParVerifyTask uses heap_region_par_iterate_chunked() for parallelism.
 // The number of GC workers is passed to heap_region_par_iterate_chunked().
 // It does use run_task() which sets _n_workers in the task.
-// G1ParTask executes g1_process_strong_roots() ->
-// SharedHeap::process_strong_roots() which calls eventually to
+// G1ParTask executes g1_process_roots() ->
+// SharedHeap::process_roots() which calls eventually to
 // CardTableModRefBS::par_non_clean_card_iterate_work() which uses
-// SequentialSubTasksDone.  SharedHeap::process_strong_roots() also
+// SequentialSubTasksDone.  SharedHeap::process_roots() also
 // directly uses SubTasksDone (_process_strong_tasks field in SharedHeap).
 //
 
 // Local to this file.
 
 class RefineCardTableEntryClosure: public CardTableEntryClosure {
-  SuspendibleThreadSet* _sts;
-  G1RemSet* _g1rs;
-  ConcurrentG1Refine* _cg1r;
   bool _concurrent;
 public:
-  RefineCardTableEntryClosure(SuspendibleThreadSet* sts,
-                              G1RemSet* g1rs,
-                              ConcurrentG1Refine* cg1r) :
-    _sts(sts), _g1rs(g1rs), _cg1r(cg1r), _concurrent(true)
-  {}
+  RefineCardTableEntryClosure() : _concurrent(true) { }
+
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    bool oops_into_cset = _g1rs->refine_card(card_ptr, worker_i, false);
+    bool oops_into_cset = G1CollectedHeap::heap()->g1_rem_set()->refine_card(card_ptr, worker_i, false);
     // This path is executed by the concurrent refine or mutator threads,
     // concurrently, and so we do not care if card_ptr contains references
     // that point into the collection set.
     assert(!oops_into_cset, "should be");
 
-    if (_concurrent && _sts->should_yield()) {
+    if (_concurrent && SuspendibleThreadSet::should_yield()) {
       // Caller will actually yield.
       return false;
     }
     // Otherwise, we finished successfully; return true.
     return true;
   }
+
   void set_concurrent(bool b) { _concurrent = b; }
 };
 
 
 class ClearLoggedCardTableEntryClosure: public CardTableEntryClosure {
-  int _calls;
-  G1CollectedHeap* _g1h;
+  size_t _num_processed;
   CardTableModRefBS* _ctbs;
   int _histo[256];
-public:
+
+ public:
   ClearLoggedCardTableEntryClosure() :
-    _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set())
+    _num_processed(0), _ctbs(G1CollectedHeap::heap()->g1_barrier_set())
   {
     for (int i = 0; i < 256; i++) _histo[i] = 0;
   }
+
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
-      _calls++;
-      unsigned char* ujb = (unsigned char*)card_ptr;
-      int ind = (int)(*ujb);
-      _histo[ind]++;
-      *card_ptr = -1;
-    }
+    unsigned char* ujb = (unsigned char*)card_ptr;
+    int ind = (int)(*ujb);
+    _histo[ind]++;
+
+    *card_ptr = (jbyte)CardTableModRefBS::clean_card_val();
+    _num_processed++;
+
     return true;
   }
-  int calls() { return _calls; }
+
+  size_t num_processed() { return _num_processed; }
+
   void print_histo() {
     gclog_or_tty->print_cr("Card table value histogram:");
     for (int i = 0; i < 256; i++) {
@@ -156,22 +157,20 @@
   }
 };
 
-class RedirtyLoggedCardTableEntryClosure: public CardTableEntryClosure {
-  int _calls;
-  G1CollectedHeap* _g1h;
-  CardTableModRefBS* _ctbs;
-public:
-  RedirtyLoggedCardTableEntryClosure() :
-    _calls(0), _g1h(G1CollectedHeap::heap()), _ctbs(_g1h->g1_barrier_set()) {}
+class RedirtyLoggedCardTableEntryClosure : public CardTableEntryClosure {
+ private:
+  size_t _num_processed;
+
+ public:
+  RedirtyLoggedCardTableEntryClosure() : CardTableEntryClosure(), _num_processed(0) { }
 
   bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    if (_g1h->is_in_reserved(_ctbs->addr_for(card_ptr))) {
-      _calls++;
-      *card_ptr = 0;
-    }
+    *card_ptr = CardTableModRefBS::dirty_card_val();
+    _num_processed++;
     return true;
   }
-  int calls() { return _calls; }
+
+  size_t num_processed() const { return _num_processed; }
 };
 
 YoungList::YoungList(G1CollectedHeap* g1h) :
@@ -379,6 +378,14 @@
   gclog_or_tty->cr();
 }
 
+void G1RegionMappingChangedListener::reset_from_card_cache(uint start_idx, size_t num_regions) {
+  OtherRegionsTable::invalidate(start_idx, num_regions);
+}
+
+void G1RegionMappingChangedListener::on_commit(uint start_idx, size_t num_regions) {
+  reset_from_card_cache(start_idx, num_regions);
+}
+
 void G1CollectedHeap::push_dirty_cards_region(HeapRegion* hr)
 {
   // Claim the right to put the region on the dirty cards region list
@@ -444,24 +451,18 @@
 // implementation of is_scavengable() for G1 will indicate that
 // all nmethods must be scanned during a partial collection.
 bool G1CollectedHeap::is_in_partial_collection(const void* p) {
-  HeapRegion* hr = heap_region_containing(p);
-  return hr != NULL && hr->in_collection_set();
+  if (p == NULL) {
+    return false;
+  }
+  return heap_region_containing(p)->in_collection_set();
 }
 #endif
 
 // Returns true if the reference points to an object that
 // can move in an incremental collection.
 bool G1CollectedHeap::is_scavengable(const void* p) {
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  G1CollectorPolicy* g1p = g1h->g1_policy();
   HeapRegion* hr = heap_region_containing(p);
-  if (hr == NULL) {
-     // null
-     assert(p == NULL, err_msg("Not NULL " PTR_FORMAT ,p));
-     return false;
-  } else {
-    return !hr->isHumongous();
-  }
+  return !hr->isHumongous();
 }
 
 void G1CollectedHeap::check_ct_logs_at_safepoint() {
@@ -475,9 +476,8 @@
 
   // First clear the logged cards.
   ClearLoggedCardTableEntryClosure clear;
-  dcqs.set_closure(&clear);
-  dcqs.apply_closure_to_all_completed_buffers();
-  dcqs.iterate_closure_all_threads(false);
+  dcqs.apply_closure_to_all_completed_buffers(&clear);
+  dcqs.iterate_closure_all_threads(&clear, false);
   clear.print_histo();
 
   // Now ensure that there's no dirty cards.
@@ -490,13 +490,13 @@
   guarantee(count2.n() == 0, "Card table should be clean.");
 
   RedirtyLoggedCardTableEntryClosure redirty;
-  JavaThread::dirty_card_queue_set().set_closure(&redirty);
-  dcqs.apply_closure_to_all_completed_buffers();
-  dcqs.iterate_closure_all_threads(false);
+  dcqs.apply_closure_to_all_completed_buffers(&redirty);
+  dcqs.iterate_closure_all_threads(&redirty, false);
   gclog_or_tty->print_cr("Log entries = %d, dirty cards = %d.",
-                         clear.calls(), orig_count);
-  guarantee(redirty.calls() == clear.calls(),
-            "Or else mechanism is broken.");
+                         clear.num_processed(), orig_count);
+  guarantee(redirty.num_processed() == clear.num_processed(),
+            err_msg("Redirtied "SIZE_FORMAT" cards, bug cleared "SIZE_FORMAT,
+                    redirty.num_processed(), clear.num_processed()));
 
   CountNonCleanMemRegionClosure count3(this);
   ct_bs->mod_card_iterate(&count3);
@@ -505,8 +505,6 @@
                            orig_count, count3.n());
     guarantee(count3.n() >= orig_count, "Should have restored them all.");
   }
-
-  JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
 }
 
 // Private class members.
@@ -530,9 +528,9 @@
       // again to allocate from it.
       append_secondary_free_list();
 
-      assert(!_free_list.is_empty(), "if the secondary_free_list was not "
+      assert(_hrs.num_free_regions() > 0, "if the secondary_free_list was not "
              "empty we should have moved at least one entry to the free_list");
-      HeapRegion* res = _free_list.remove_region(is_old);
+      HeapRegion* res = _hrs.allocate_free_region(is_old);
       if (G1ConcRegionFreeingVerbose) {
         gclog_or_tty->print_cr("G1ConcRegionFreeing [region alloc] : "
                                "allocated "HR_FORMAT" from secondary_free_list",
@@ -573,7 +571,7 @@
     }
   }
 
-  res = _free_list.remove_region(is_old);
+  res = _hrs.allocate_free_region(is_old);
 
   if (res == NULL) {
     if (G1ConcRegionFreeingVerbose) {
@@ -598,8 +596,8 @@
       // Given that expand() succeeded in expanding the heap, and we
       // always expand the heap by an amount aligned to the heap
       // region size, the free list should in theory not be empty.
-      // In either case remove_region() will check for NULL.
-      res = _free_list.remove_region(is_old);
+      // In either case allocate_free_region() will check for NULL.
+      res = _hrs.allocate_free_region(is_old);
     } else {
       _expand_heap_after_alloc_failure = false;
     }
@@ -607,55 +605,11 @@
   return res;
 }
 
-uint G1CollectedHeap::humongous_obj_allocate_find_first(uint num_regions,
-                                                        size_t word_size) {
-  assert(isHumongous(word_size), "word_size should be humongous");
-  assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition");
-
-  uint first = G1_NULL_HRS_INDEX;
-  if (num_regions == 1) {
-    // Only one region to allocate, no need to go through the slower
-    // path. The caller will attempt the expansion if this fails, so
-    // let's not try to expand here too.
-    HeapRegion* hr = new_region(word_size, true /* is_old */, false /* do_expand */);
-    if (hr != NULL) {
-      first = hr->hrs_index();
-    } else {
-      first = G1_NULL_HRS_INDEX;
-    }
-  } else {
-    // We can't allocate humongous regions while cleanupComplete() is
-    // running, since some of the regions we find to be empty might not
-    // yet be added to the free list and it is not straightforward to
-    // know which list they are on so that we can remove them. Note
-    // that we only need to do this if we need to allocate more than
-    // one region to satisfy the current humongous allocation
-    // request. If we are only allocating one region we use the common
-    // region allocation code (see above).
-    wait_while_free_regions_coming();
-    append_secondary_free_list_if_not_empty_with_lock();
-
-    if (free_regions() >= num_regions) {
-      first = _hrs.find_contiguous(num_regions);
-      if (first != G1_NULL_HRS_INDEX) {
-        for (uint i = first; i < first + num_regions; ++i) {
-          HeapRegion* hr = region_at(i);
-          assert(hr->is_empty(), "sanity");
-          assert(is_on_master_free_list(hr), "sanity");
-          hr->set_pending_removal(true);
-        }
-        _free_list.remove_all_pending(num_regions);
-      }
-    }
-  }
-  return first;
-}
-
 HeapWord*
 G1CollectedHeap::humongous_obj_allocate_initialize_regions(uint first,
                                                            uint num_regions,
                                                            size_t word_size) {
-  assert(first != G1_NULL_HRS_INDEX, "pre-condition");
+  assert(first != G1_NO_HRS_INDEX, "pre-condition");
   assert(isHumongous(word_size), "word_size should be humongous");
   assert(num_regions * HeapRegion::GrainWords >= word_size, "pre-condition");
 
@@ -776,6 +730,7 @@
   // match new_top.
   assert(hr == NULL ||
          (hr->end() == new_end && hr->top() == new_top), "sanity");
+  check_bitmaps("Humongous Region Allocation", first_hr);
 
   assert(first_hr->used() == word_size * HeapWordSize, "invariant");
   _summary_bytes_used += first_hr->used();
@@ -792,42 +747,70 @@
 
   verify_region_sets_optional();
 
-  size_t word_size_rounded = round_to(word_size, HeapRegion::GrainWords);
-  uint num_regions = (uint) (word_size_rounded / HeapRegion::GrainWords);
-  uint x_num = expansion_regions();
-  uint fs = _hrs.free_suffix();
-  uint first = humongous_obj_allocate_find_first(num_regions, word_size);
-  if (first == G1_NULL_HRS_INDEX) {
-    // The only thing we can do now is attempt expansion.
-    if (fs + x_num >= num_regions) {
-      // If the number of regions we're trying to allocate for this
-      // object is at most the number of regions in the free suffix,
-      // then the call to humongous_obj_allocate_find_first() above
-      // should have succeeded and we wouldn't be here.
-      //
-      // We should only be trying to expand when the free suffix is
-      // not sufficient for the object _and_ we have some expansion
-      // room available.
-      assert(num_regions > fs, "earlier allocation should have succeeded");
+  uint first = G1_NO_HRS_INDEX;
+  uint obj_regions = (uint)(align_size_up_(word_size, HeapRegion::GrainWords) / HeapRegion::GrainWords);
 
+  if (obj_regions == 1) {
+    // Only one region to allocate, try to use a fast path by directly allocating
+    // from the free lists. Do not try to expand here, we will potentially do that
+    // later.
+    HeapRegion* hr = new_region(word_size, true /* is_old */, false /* do_expand */);
+    if (hr != NULL) {
+      first = hr->hrs_index();
+    }
+  } else {
+    // We can't allocate humongous regions spanning more than one region while
+    // cleanupComplete() is running, since some of the regions we find to be
+    // empty might not yet be added to the free list. It is not straightforward
+    // to know in which list they are on so that we can remove them. We only
+    // need to do this if we need to allocate more than one region to satisfy the
+    // current humongous allocation request. If we are only allocating one region
+    // we use the one-region region allocation code (see above), that already
+    // potentially waits for regions from the secondary free list.
+    wait_while_free_regions_coming();
+    append_secondary_free_list_if_not_empty_with_lock();
+
+    // Policy: Try only empty regions (i.e. already committed first). Maybe we
+    // are lucky enough to find some.
+    first = _hrs.find_contiguous_only_empty(obj_regions);
+    if (first != G1_NO_HRS_INDEX) {
+      _hrs.allocate_free_regions_starting_at(first, obj_regions);
+    }
+  }
+
+  if (first == G1_NO_HRS_INDEX) {
+    // Policy: We could not find enough regions for the humongous object in the
+    // free list. Look through the heap to find a mix of free and uncommitted regions.
+    // If so, try expansion.
+    first = _hrs.find_contiguous_empty_or_unavailable(obj_regions);
+    if (first != G1_NO_HRS_INDEX) {
+      // We found something. Make sure these regions are committed, i.e. expand
+      // the heap. Alternatively we could do a defragmentation GC.
       ergo_verbose1(ErgoHeapSizing,
                     "attempt heap expansion",
                     ergo_format_reason("humongous allocation request failed")
                     ergo_format_byte("allocation request"),
                     word_size * HeapWordSize);
-      if (expand((num_regions - fs) * HeapRegion::GrainBytes)) {
-        // Even though the heap was expanded, it might not have
-        // reached the desired size. So, we cannot assume that the
-        // allocation will succeed.
-        first = humongous_obj_allocate_find_first(num_regions, word_size);
+
+      _hrs.expand_at(first, obj_regions);
+      g1_policy()->record_new_heap_size(num_regions());
+
+#ifdef ASSERT
+      for (uint i = first; i < first + obj_regions; ++i) {
+        HeapRegion* hr = region_at(i);
+        assert(hr->is_empty(), "sanity");
+        assert(is_on_master_free_list(hr), "sanity");
       }
+#endif
+      _hrs.allocate_free_regions_starting_at(first, obj_regions);
+    } else {
+      // Policy: Potentially trigger a defragmentation GC.
     }
   }
 
   HeapWord* result = NULL;
-  if (first != G1_NULL_HRS_INDEX) {
-    result =
-      humongous_obj_allocate_initialize_regions(first, num_regions, word_size);
+  if (first != G1_NO_HRS_INDEX) {
+    result = humongous_obj_allocate_initialize_regions(first, obj_regions, word_size);
     assert(result != NULL, "it should always return a valid result");
 
     // A successful humongous object allocation changes the used space
@@ -1305,7 +1288,7 @@
     TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
 
     {
-      GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL);
+      GCTraceTime t(GCCauseString("Full GC", gc_cause()), G1Log::fine(), true, NULL, gc_tracer->gc_id());
       TraceCollectorStats tcs(g1mm()->full_collection_counters());
       TraceMemoryManagerStats tms(true /* fullGC */, gc_cause());
 
@@ -1334,6 +1317,7 @@
 
       verify_before_gc();
 
+      check_bitmaps("Full GC Start");
       pre_full_gc_dump(gc_timer);
 
       COMPILER2_PRESENT(DerivedPointerTable::clear());
@@ -1389,7 +1373,7 @@
         G1MarkSweep::invoke_at_safepoint(ref_processor_stw(), do_clear_all_soft_refs);
       }
 
-      assert(free_regions() == 0, "we should not have added any free regions");
+      assert(num_free_regions() == 0, "we should not have added any free regions");
       rebuild_region_sets(false /* free_list_only */);
 
       // Enqueue any discovered reference objects that have
@@ -1507,13 +1491,22 @@
 
       verify_after_gc();
 
+      // Clear the previous marking bitmap, if needed for bitmap verification.
+      // Note we cannot do this when we clear the next marking bitmap in
+      // ConcurrentMark::abort() above since VerifyDuringGC verifies the
+      // objects marked during a full GC against the previous bitmap.
+      // But we need to clear it before calling check_bitmaps below since
+      // the full GC has compacted objects and updated TAMS but not updated
+      // the prev bitmap.
+      if (G1VerifyBitmaps) {
+        ((CMBitMap*) concurrent_mark()->prevMarkBitMap())->clearAll();
+      }
+      check_bitmaps("Full GC End");
+
       // Start a new incremental collection set for the next pause
       assert(g1_policy()->collection_set() == NULL, "must be");
       g1_policy()->start_incremental_cset_building();
 
-      // Clear the _cset_fast_test bitmap in anticipation of adding
-      // regions to the incremental collection set for the next
-      // evacuation pause.
       clear_cset_fast_test();
 
       init_mutator_alloc_region();
@@ -1745,21 +1738,6 @@
   return NULL;
 }
 
-void G1CollectedHeap::update_committed_space(HeapWord* old_end,
-                                             HeapWord* new_end) {
-  assert(old_end != new_end, "don't call this otherwise");
-  assert((HeapWord*) _g1_storage.high() == new_end, "invariant");
-
-  // Update the committed mem region.
-  _g1_committed.set_end(new_end);
-  // Tell the card table about the update.
-  Universe::heap()->barrier_set()->resize_covered_region(_g1_committed);
-  // Tell the BOT about the update.
-  _bot_shared->resize(_g1_committed.word_size());
-  // Tell the hot card cache about the update
-  _cg1r->hot_card_cache()->resize_card_counts(capacity());
-}
-
 bool G1CollectedHeap::expand(size_t expand_bytes) {
   size_t aligned_expand_bytes = ReservedSpace::page_align_size_up(expand_bytes);
   aligned_expand_bytes = align_size_up(aligned_expand_bytes,
@@ -1770,55 +1748,22 @@
                 ergo_format_byte("attempted expansion amount"),
                 expand_bytes, aligned_expand_bytes);
 
-  if (_g1_storage.uncommitted_size() == 0) {
+  if (is_maximal_no_gc()) {
     ergo_verbose0(ErgoHeapSizing,
                       "did not expand the heap",
                       ergo_format_reason("heap already fully expanded"));
     return false;
   }
 
-  // First commit the memory.
-  HeapWord* old_end = (HeapWord*) _g1_storage.high();
-  bool successful = _g1_storage.expand_by(aligned_expand_bytes);
-  if (successful) {
-    // Then propagate this update to the necessary data structures.
-    HeapWord* new_end = (HeapWord*) _g1_storage.high();
-    update_committed_space(old_end, new_end);
+  uint regions_to_expand = (uint)(aligned_expand_bytes / HeapRegion::GrainBytes);
+  assert(regions_to_expand > 0, "Must expand by at least one region");
 
-    FreeRegionList expansion_list("Local Expansion List");
-    MemRegion mr = _hrs.expand_by(old_end, new_end, &expansion_list);
-    assert(mr.start() == old_end, "post-condition");
-    // mr might be a smaller region than what was requested if
-    // expand_by() was unable to allocate the HeapRegion instances
-    assert(mr.end() <= new_end, "post-condition");
+  uint expanded_by = _hrs.expand_by(regions_to_expand);
 
-    size_t actual_expand_bytes = mr.byte_size();
+  if (expanded_by > 0) {
+    size_t actual_expand_bytes = expanded_by * HeapRegion::GrainBytes;
     assert(actual_expand_bytes <= aligned_expand_bytes, "post-condition");
-    assert(actual_expand_bytes == expansion_list.total_capacity_bytes(),
-           "post-condition");
-    if (actual_expand_bytes < aligned_expand_bytes) {
-      // We could not expand _hrs to the desired size. In this case we
-      // need to shrink the committed space accordingly.
-      assert(mr.end() < new_end, "invariant");
-
-      size_t diff_bytes = aligned_expand_bytes - actual_expand_bytes;
-      // First uncommit the memory.
-      _g1_storage.shrink_by(diff_bytes);
-      // Then propagate this update to the necessary data structures.
-      update_committed_space(new_end, mr.end());
-    }
-    _free_list.add_as_tail(&expansion_list);
-
-    if (_hr_printer.is_active()) {
-      HeapWord* curr = mr.start();
-      while (curr < mr.end()) {
-        HeapWord* curr_end = curr + HeapRegion::GrainWords;
-        _hr_printer.commit(curr, curr_end);
-        curr = curr_end;
-      }
-      assert(curr == mr.end(), "post-condition");
-    }
-    g1_policy()->record_new_heap_size(n_regions());
+    g1_policy()->record_new_heap_size(num_regions());
   } else {
     ergo_verbose0(ErgoHeapSizing,
                   "did not expand the heap",
@@ -1826,12 +1771,12 @@
     // The expansion of the virtual storage space was unsuccessful.
     // Let's see if it was because we ran out of swap.
     if (G1ExitOnExpansionFailure &&
-        _g1_storage.uncommitted_size() >= aligned_expand_bytes) {
+        _hrs.available() >= regions_to_expand) {
       // We had head room...
       vm_exit_out_of_memory(aligned_expand_bytes, OOM_MMAP_ERROR, "G1 heap expansion");
     }
   }
-  return successful;
+  return regions_to_expand > 0;
 }
 
 void G1CollectedHeap::shrink_helper(size_t shrink_bytes) {
@@ -1842,7 +1787,6 @@
   uint num_regions_to_remove = (uint)(shrink_bytes / HeapRegion::GrainBytes);
 
   uint num_regions_removed = _hrs.shrink_by(num_regions_to_remove);
-  HeapWord* old_end = (HeapWord*) _g1_storage.high();
   size_t shrunk_bytes = num_regions_removed * HeapRegion::GrainBytes;
 
   ergo_verbose3(ErgoHeapSizing,
@@ -1852,22 +1796,7 @@
                 ergo_format_byte("attempted shrinking amount"),
                 shrink_bytes, aligned_shrink_bytes, shrunk_bytes);
   if (num_regions_removed > 0) {
-    _g1_storage.shrink_by(shrunk_bytes);
-    HeapWord* new_end = (HeapWord*) _g1_storage.high();
-
-    if (_hr_printer.is_active()) {
-      HeapWord* curr = old_end;
-      while (curr > new_end) {
-        HeapWord* curr_end = curr;
-        curr -= HeapRegion::GrainWords;
-        _hr_printer.uncommit(curr, curr_end);
-      }
-    }
-
-    _expansion_regions += num_regions_removed;
-    update_committed_space(old_end, new_end);
-    HeapRegionRemSet::shrink_heap(n_regions());
-    g1_policy()->record_new_heap_size(n_regions());
+    g1_policy()->record_new_heap_size(num_regions());
   } else {
     ergo_verbose0(ErgoHeapSizing,
                   "did not shrink the heap",
@@ -1918,10 +1847,11 @@
   _g1mm(NULL),
   _refine_cte_cl(NULL),
   _full_collection(false),
-  _free_list("Master Free List", new MasterFreeRegionListMtSafeChecker()),
   _secondary_free_list("Secondary Free List", new SecondaryFreeRegionListMtSafeChecker()),
   _old_set("Old Set", false /* humongous */, new OldRegionSetMtSafeChecker()),
   _humongous_set("Master Humongous Set", true /* humongous */, new HumongousRegionSetMtSafeChecker()),
+  _humongous_is_live(),
+  _has_humongous_reclaim_candidates(false),
   _free_regions_coming(false),
   _young_list(new YoungList(this)),
   _gc_time_stamp(0),
@@ -1933,8 +1863,7 @@
   _old_marking_cycles_started(0),
   _old_marking_cycles_completed(0),
   _concurrent_cycle_started(false),
-  _in_cset_fast_test(NULL),
-  _in_cset_fast_test_base(NULL),
+  _in_cset_fast_test(),
   _dirty_cards_region_list(NULL),
   _worker_cset_start_region(NULL),
   _worker_cset_start_region_time_stamp(NULL),
@@ -2004,7 +1933,9 @@
   Universe::check_alignment(max_byte_size, HeapRegion::GrainBytes, "g1 heap");
   Universe::check_alignment(max_byte_size, heap_alignment, "g1 heap");
 
-  _cg1r = new ConcurrentG1Refine(this);
+  _refine_cte_cl = new RefineCardTableEntryClosure();
+
+  _cg1r = new ConcurrentG1Refine(this, _refine_cte_cl);
 
   // Reserve the maximum.
 
@@ -2029,8 +1960,6 @@
   _reserved.set_start((HeapWord*)heap_rs.base());
   _reserved.set_end((HeapWord*)(heap_rs.base() + heap_rs.size()));
 
-  _expansion_regions = (uint) (max_byte_size / HeapRegion::GrainBytes);
-
   // Create the gen rem set (and barrier set) for the entire reserved region.
   _rem_set = collector_policy()->create_rem_set(_reserved, 2);
   set_barrier_set(rem_set()->bs());
@@ -2044,20 +1973,65 @@
 
   // Carve out the G1 part of the heap.
 
-  ReservedSpace g1_rs   = heap_rs.first_part(max_byte_size);
-  _g1_reserved = MemRegion((HeapWord*)g1_rs.base(),
-                           g1_rs.size()/HeapWordSize);
+  ReservedSpace g1_rs = heap_rs.first_part(max_byte_size);
+  G1RegionToSpaceMapper* heap_storage =
+    G1RegionToSpaceMapper::create_mapper(g1_rs,
+                                         UseLargePages ? os::large_page_size() : os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         1,
+                                         mtJavaHeap);
+  heap_storage->set_mapping_changed_listener(&_listener);
 
-  _g1_storage.initialize(g1_rs, 0);
-  _g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0);
-  _hrs.initialize((HeapWord*) _g1_reserved.start(),
-                  (HeapWord*) _g1_reserved.end());
-  assert(_hrs.max_length() == _expansion_regions,
-         err_msg("max length: %u expansion regions: %u",
-                 _hrs.max_length(), _expansion_regions));
+  // Reserve space for the block offset table. We do not support automatic uncommit
+  // for the card table at this time. BOT only.
+  ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize));
+  G1RegionToSpaceMapper* bot_storage =
+    G1RegionToSpaceMapper::create_mapper(bot_rs,
+                                         os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         G1BlockOffsetSharedArray::N_bytes,
+                                         mtGC);
 
-  // Do later initialization work for concurrent refinement.
-  _cg1r->init();
+  ReservedSpace cardtable_rs(G1SATBCardTableLoggingModRefBS::compute_size(g1_rs.size() / HeapWordSize));
+  G1RegionToSpaceMapper* cardtable_storage =
+    G1RegionToSpaceMapper::create_mapper(cardtable_rs,
+                                         os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         G1BlockOffsetSharedArray::N_bytes,
+                                         mtGC);
+
+  // Reserve space for the card counts table.
+  ReservedSpace card_counts_rs(G1BlockOffsetSharedArray::compute_size(g1_rs.size() / HeapWordSize));
+  G1RegionToSpaceMapper* card_counts_storage =
+    G1RegionToSpaceMapper::create_mapper(card_counts_rs,
+                                         os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         G1BlockOffsetSharedArray::N_bytes,
+                                         mtGC);
+
+  // Reserve space for prev and next bitmap.
+  size_t bitmap_size = CMBitMap::compute_size(g1_rs.size());
+
+  ReservedSpace prev_bitmap_rs(ReservedSpace::allocation_align_size_up(bitmap_size));
+  G1RegionToSpaceMapper* prev_bitmap_storage =
+    G1RegionToSpaceMapper::create_mapper(prev_bitmap_rs,
+                                         os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         CMBitMap::mark_distance(),
+                                         mtGC);
+
+  ReservedSpace next_bitmap_rs(ReservedSpace::allocation_align_size_up(bitmap_size));
+  G1RegionToSpaceMapper* next_bitmap_storage =
+    G1RegionToSpaceMapper::create_mapper(next_bitmap_rs,
+                                         os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         CMBitMap::mark_distance(),
+                                         mtGC);
+
+  _hrs.initialize(heap_storage, prev_bitmap_storage, next_bitmap_storage, bot_storage, cardtable_storage, card_counts_storage);
+  g1_barrier_set()->initialize(cardtable_storage);
+   // Do later initialization work for concurrent refinement.
+  _cg1r->init(card_counts_storage);
 
   // 6843694 - ensure that the maximum region index can fit
   // in the remembered set structures.
@@ -2071,29 +2045,16 @@
 
   FreeRegionList::set_unrealistically_long_length(max_regions() + 1);
 
-  _bot_shared = new G1BlockOffsetSharedArray(_reserved,
-                                             heap_word_size(init_byte_size));
+  _bot_shared = new G1BlockOffsetSharedArray(_reserved, bot_storage);
 
   _g1h = this;
 
-  _in_cset_fast_test_length = max_regions();
-  _in_cset_fast_test_base =
-                   NEW_C_HEAP_ARRAY(bool, (size_t) _in_cset_fast_test_length, mtGC);
-
-  // We're biasing _in_cset_fast_test to avoid subtracting the
-  // beginning of the heap every time we want to index; basically
-  // it's the same with what we do with the card table.
-  _in_cset_fast_test = _in_cset_fast_test_base -
-               ((uintx) _g1_reserved.start() >> HeapRegion::LogOfHRGrainBytes);
-
-  // Clear the _cset_fast_test bitmap in anticipation of adding
-  // regions to the incremental collection set for the first
-  // evacuation pause.
-  clear_cset_fast_test();
+  _in_cset_fast_test.initialize(_hrs.reserved().start(), _hrs.reserved().end(), HeapRegion::GrainBytes);
+  _humongous_is_live.initialize(_hrs.reserved().start(), _hrs.reserved().end(), HeapRegion::GrainBytes);
 
   // Create the ConcurrentMark data structure and thread.
   // (Must do this late, so that "max_regions" is defined.)
-  _cm = new ConcurrentMark(this, heap_rs);
+  _cm = new ConcurrentMark(this, prev_bitmap_storage, next_bitmap_storage);
   if (_cm == NULL || !_cm->completed_initialization()) {
     vm_shutdown_during_initialization("Could not create/initialize ConcurrentMark");
     return JNI_ENOMEM;
@@ -2112,25 +2073,21 @@
   // Perform any initialization actions delegated to the policy.
   g1_policy()->init();
 
-  _refine_cte_cl =
-    new RefineCardTableEntryClosure(ConcurrentG1RefineThread::sts(),
-                                    g1_rem_set(),
-                                    concurrent_g1_refine());
-  JavaThread::dirty_card_queue_set().set_closure(_refine_cte_cl);
-
   JavaThread::satb_mark_queue_set().initialize(SATB_Q_CBL_mon,
                                                SATB_Q_FL_lock,
                                                G1SATBProcessCompletedThreshold,
                                                Shared_SATB_Q_lock);
 
-  JavaThread::dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
+  JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl,
+                                                DirtyCardQ_CBL_mon,
                                                 DirtyCardQ_FL_lock,
                                                 concurrent_g1_refine()->yellow_zone(),
                                                 concurrent_g1_refine()->red_zone(),
                                                 Shared_DirtyCardQ_lock);
 
   if (G1DeferredRSUpdate) {
-    dirty_card_queue_set().initialize(DirtyCardQ_CBL_mon,
+    dirty_card_queue_set().initialize(NULL, // Should never be called by the Java code
+                                      DirtyCardQ_CBL_mon,
                                       DirtyCardQ_FL_lock,
                                       -1, // never trigger processing
                                       -1, // no limit on length
@@ -2140,7 +2097,8 @@
 
   // Initialize the card queue set used to hold cards containing
   // references into the collection set.
-  _into_cset_dirty_card_queue_set.initialize(DirtyCardQ_CBL_mon,
+  _into_cset_dirty_card_queue_set.initialize(NULL, // Should never be called by the Java code
+                                             DirtyCardQ_CBL_mon,
                                              DirtyCardQ_FL_lock,
                                              -1, // never trigger processing
                                              -1, // no limit on length
@@ -2151,12 +2109,10 @@
   // counts and that mechanism.
   SpecializationStats::clear();
 
-  // Here we allocate the dummy full region that is required by the
-  // G1AllocRegion class. If we don't pass an address in the reserved
-  // space here, lots of asserts fire.
+  // Here we allocate the dummy HeapRegion that is required by the
+  // G1AllocRegion class.
+  HeapRegion* dummy_region = _hrs.get_dummy_region();
 
-  HeapRegion* dummy_region = new_heap_region(0 /* index of bottom region */,
-                                             _g1_reserved.start());
   // We'll re-use the same region whether the alloc region will
   // require BOT updates or not and, if it doesn't, then a non-young
   // region will complain that it cannot support allocations without
@@ -2188,6 +2144,11 @@
   }
 }
 
+void G1CollectedHeap::clear_humongous_is_live_table() {
+  guarantee(G1ReclaimDeadHumongousObjectsAtYoungGC, "Should only be called if true");
+  _humongous_is_live.clear();
+}
+
 size_t G1CollectedHeap::conservative_max_heap_alignment() {
   return HeapRegion::max_region_size();
 }
@@ -2267,7 +2228,7 @@
 }
 
 size_t G1CollectedHeap::capacity() const {
-  return _g1_committed.byte_size();
+  return _hrs.length() * HeapRegion::GrainBytes;
 }
 
 void G1CollectedHeap::reset_gc_time_stamps(HeapRegion* hr) {
@@ -2375,25 +2336,6 @@
   return blk.result();
 }
 
-size_t G1CollectedHeap::unsafe_max_alloc() {
-  if (free_regions() > 0) return HeapRegion::GrainBytes;
-  // otherwise, is there space in the current allocation region?
-
-  // We need to store the current allocation region in a local variable
-  // here. The problem is that this method doesn't take any locks and
-  // there may be other threads which overwrite the current allocation
-  // region field. attempt_allocation(), for example, sets it to NULL
-  // and this can happen *after* the NULL check here but before the call
-  // to free(), resulting in a SIGSEGV. Note that this doesn't appear
-  // to be a problem in the optimized build, since the two loads of the
-  // current allocation region field are optimized away.
-  HeapRegion* hr = _mutator_alloc_region.get();
-  if (hr == NULL) {
-    return 0;
-  }
-  return hr->free();
-}
-
 bool G1CollectedHeap::should_do_concurrent_full_gc(GCCause::Cause cause) {
   switch (cause) {
     case GCCause::_gc_locker:               return GCLockerInvokesConcurrent;
@@ -2570,7 +2512,7 @@
         }
       }
     } else {
-      if (cause == GCCause::_gc_locker
+      if (cause == GCCause::_gc_locker || cause == GCCause::_wb_young_gc
           DEBUG_ONLY(|| cause == GCCause::_scavenge_alot)) {
 
         // Schedule a standard evacuation pause. We're setting word_size
@@ -2591,8 +2533,8 @@
 }
 
 bool G1CollectedHeap::is_in(const void* p) const {
-  if (_g1_committed.contains(p)) {
-    // Given that we know that p is in the committed space,
+  if (_hrs.reserved().contains(p)) {
+    // Given that we know that p is in the reserved space,
     // heap_region_containing_raw() should successfully
     // return the containing region.
     HeapRegion* hr = heap_region_containing_raw(p);
@@ -2602,17 +2544,26 @@
   }
 }
 
+#ifdef ASSERT
+bool G1CollectedHeap::is_in_exact(const void* p) const {
+  bool contains = reserved_region().contains(p);
+  bool available = _hrs.is_available(addr_to_region((HeapWord*)p));
+  if (contains && available) {
+    return true;
+  } else {
+    return false;
+  }
+}
+#endif
+
 // Iteration functions.
 
-// Iterates an OopClosure over all ref-containing fields of objects
-// within a HeapRegion.
+// Applies an ExtendedOopClosure onto all references of objects within a HeapRegion.
 
 class IterateOopClosureRegionClosure: public HeapRegionClosure {
-  MemRegion _mr;
   ExtendedOopClosure* _cl;
 public:
-  IterateOopClosureRegionClosure(MemRegion mr, ExtendedOopClosure* cl)
-    : _mr(mr), _cl(cl) {}
+  IterateOopClosureRegionClosure(ExtendedOopClosure* cl) : _cl(cl) {}
   bool doHeapRegion(HeapRegion* r) {
     if (!r->continuesHumongous()) {
       r->oop_iterate(_cl);
@@ -2622,12 +2573,7 @@
 };
 
 void G1CollectedHeap::oop_iterate(ExtendedOopClosure* cl) {
-  IterateOopClosureRegionClosure blk(_g1_committed, cl);
-  heap_region_iterate(&blk);
-}
-
-void G1CollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  IterateOopClosureRegionClosure blk(mr, cl);
+  IterateOopClosureRegionClosure blk(cl);
   heap_region_iterate(&blk);
 }
 
@@ -2674,83 +2620,9 @@
 void
 G1CollectedHeap::heap_region_par_iterate_chunked(HeapRegionClosure* cl,
                                                  uint worker_id,
-                                                 uint no_of_par_workers,
-                                                 jint claim_value) {
-  const uint regions = n_regions();
-  const uint max_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
-                             no_of_par_workers :
-                             1);
-  assert(UseDynamicNumberOfGCThreads ||
-         no_of_par_workers == workers()->total_workers(),
-         "Non dynamic should use fixed number of workers");
-  // try to spread out the starting points of the workers
-  const HeapRegion* start_hr =
-                        start_region_for_worker(worker_id, no_of_par_workers);
-  const uint start_index = start_hr->hrs_index();
-
-  // each worker will actually look at all regions
-  for (uint count = 0; count < regions; ++count) {
-    const uint index = (start_index + count) % regions;
-    assert(0 <= index && index < regions, "sanity");
-    HeapRegion* r = region_at(index);
-    // we'll ignore "continues humongous" regions (we'll process them
-    // when we come across their corresponding "start humongous"
-    // region) and regions already claimed
-    if (r->claim_value() == claim_value || r->continuesHumongous()) {
-      continue;
-    }
-    // OK, try to claim it
-    if (r->claimHeapRegion(claim_value)) {
-      // success!
-      assert(!r->continuesHumongous(), "sanity");
-      if (r->startsHumongous()) {
-        // If the region is "starts humongous" we'll iterate over its
-        // "continues humongous" first; in fact we'll do them
-        // first. The order is important. In on case, calling the
-        // closure on the "starts humongous" region might de-allocate
-        // and clear all its "continues humongous" regions and, as a
-        // result, we might end up processing them twice. So, we'll do
-        // them first (notice: most closures will ignore them anyway) and
-        // then we'll do the "starts humongous" region.
-        for (uint ch_index = index + 1; ch_index < regions; ++ch_index) {
-          HeapRegion* chr = region_at(ch_index);
-
-          // if the region has already been claimed or it's not
-          // "continues humongous" we're done
-          if (chr->claim_value() == claim_value ||
-              !chr->continuesHumongous()) {
-            break;
-          }
-
-          // No one should have claimed it directly. We can given
-          // that we claimed its "starts humongous" region.
-          assert(chr->claim_value() != claim_value, "sanity");
-          assert(chr->humongous_start_region() == r, "sanity");
-
-          if (chr->claimHeapRegion(claim_value)) {
-            // we should always be able to claim it; no one else should
-            // be trying to claim this region
-
-            bool res2 = cl->doHeapRegion(chr);
-            assert(!res2, "Should not abort");
-
-            // Right now, this holds (i.e., no closure that actually
-            // does something with "continues humongous" regions
-            // clears them). We might have to weaken it in the future,
-            // but let's leave these two asserts here for extra safety.
-            assert(chr->continuesHumongous(), "should still be the case");
-            assert(chr->humongous_start_region() == r, "sanity");
-          } else {
-            guarantee(false, "we should not reach here");
-          }
-        }
-      }
-
-      assert(!r->continuesHumongous(), "sanity");
-      bool res = cl->doHeapRegion(r);
-      assert(!res, "Should not abort");
-    }
-  }
+                                                 uint num_workers,
+                                                 jint claim_value) const {
+  _hrs.par_iterate(cl, worker_id, num_workers, claim_value);
 }
 
 class ResetClaimValuesClosure: public HeapRegionClosure {
@@ -2928,17 +2800,6 @@
   return result;
 }
 
-HeapRegion* G1CollectedHeap::start_region_for_worker(uint worker_i,
-                                                     uint no_of_par_workers) {
-  uint worker_num =
-           G1CollectedHeap::use_parallel_gc_threads() ? no_of_par_workers : 1U;
-  assert(UseDynamicNumberOfGCThreads ||
-         no_of_par_workers == workers()->total_workers(),
-         "Non dynamic should use fixed number of workers");
-  const uint start_index = n_regions() * worker_i / worker_num;
-  return region_at(start_index);
-}
-
 void G1CollectedHeap::collection_set_iterate(HeapRegionClosure* cl) {
   HeapRegion* r = g1_policy()->collection_set();
   while (r != NULL) {
@@ -2980,27 +2841,25 @@
   }
 }
 
-CompactibleSpace* G1CollectedHeap::first_compactible_space() {
-  return n_regions() > 0 ? region_at(0) : NULL;
+HeapRegion* G1CollectedHeap::next_compaction_region(const HeapRegion* from) const {
+  HeapRegion* result = _hrs.next_region_in_heap(from);
+  while (result != NULL && result->isHumongous()) {
+    result = _hrs.next_region_in_heap(result);
+  }
+  return result;
 }
 
-
 Space* G1CollectedHeap::space_containing(const void* addr) const {
-  Space* res = heap_region_containing(addr);
-  return res;
+  return heap_region_containing(addr);
 }
 
 HeapWord* G1CollectedHeap::block_start(const void* addr) const {
   Space* sp = space_containing(addr);
-  if (sp != NULL) {
-    return sp->block_start(addr);
-  }
-  return NULL;
+  return sp->block_start(addr);
 }
 
 size_t G1CollectedHeap::block_size(const HeapWord* addr) const {
   Space* sp = space_containing(addr);
-  assert(sp != NULL, "block_size of address outside of heap");
   return sp->block_size(addr);
 }
 
@@ -3045,7 +2904,7 @@
 }
 
 size_t G1CollectedHeap::max_capacity() const {
-  return _g1_reserved.byte_size();
+  return _hrs.reserved().byte_size();
 }
 
 jlong G1CollectedHeap::millis_since_last_gc() {
@@ -3414,25 +3273,20 @@
 
     if (!silent) { gclog_or_tty->print("Roots "); }
     VerifyRootsClosure rootsCl(vo);
-    G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo);
-    G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl);
     VerifyKlassClosure klassCl(this, &rootsCl);
+    CLDToKlassAndOopClosure cldCl(&klassCl, &rootsCl, false);
 
     // We apply the relevant closures to all the oops in the
-    // system dictionary, the string table and the code cache.
-    const int so = SO_AllClasses | SO_Strings | SO_CodeCache;
+    // system dictionary, class loader data graph, the string table
+    // and the nmethods in the code cache.
+    G1VerifyCodeRootOopClosure codeRootsCl(this, &rootsCl, vo);
+    G1VerifyCodeRootBlobClosure blobsCl(&codeRootsCl);
 
-    // Need cleared claim bits for the strong roots processing
-    ClassLoaderDataGraph::clear_claimed_marks();
-
-    process_strong_roots(true,      // activate StrongRootsScope
-                         false,     // we set "is scavenging" to false,
-                                    // so we don't reset the dirty cards.
-                         ScanningOption(so),  // roots scanning options
-                         &rootsCl,
-                         &blobsCl,
-                         &klassCl
-                         );
+    process_all_roots(true,            // activate StrongRootsScope
+                      SO_AllCodeCache, // roots scanning options
+                      &rootsCl,
+                      &cldCl,
+                      &blobsCl);
 
     bool failures = rootsCl.failures() || codeRootsCl.failures();
 
@@ -3579,9 +3433,9 @@
   st->print(" total " SIZE_FORMAT "K, used " SIZE_FORMAT "K",
             capacity()/K, used_unlocked()/K);
   st->print(" [" INTPTR_FORMAT ", " INTPTR_FORMAT ", " INTPTR_FORMAT ")",
-            _g1_storage.low_boundary(),
-            _g1_storage.high(),
-            _g1_storage.high_boundary());
+            _hrs.reserved().start(),
+            _hrs.reserved().start() + _hrs.length() + HeapRegion::GrainWords,
+            _hrs.reserved().end());
   st->cr();
   st->print("  region size " SIZE_FORMAT "K, ", HeapRegion::GrainBytes / K);
   uint young_regions = _young_list->length();
@@ -3804,6 +3658,61 @@
   return g1_rem_set()->cardsScanned();
 }
 
+bool G1CollectedHeap::humongous_region_is_always_live(uint index) {
+  HeapRegion* region = region_at(index);
+  assert(region->startsHumongous(), "Must start a humongous object");
+  return oop(region->bottom())->is_objArray() || !region->rem_set()->is_empty();
+}
+
+class RegisterHumongousWithInCSetFastTestClosure : public HeapRegionClosure {
+ private:
+  size_t _total_humongous;
+  size_t _candidate_humongous;
+ public:
+  RegisterHumongousWithInCSetFastTestClosure() : _total_humongous(0), _candidate_humongous(0) {
+  }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    if (!r->startsHumongous()) {
+      return false;
+    }
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+    uint region_idx = r->hrs_index();
+    bool is_candidate = !g1h->humongous_region_is_always_live(region_idx);
+    // Is_candidate already filters out humongous regions with some remembered set.
+    // This will not lead to humongous object that we mistakenly keep alive because
+    // during young collection the remembered sets will only be added to.
+    if (is_candidate) {
+      g1h->register_humongous_region_with_in_cset_fast_test(region_idx);
+      _candidate_humongous++;
+    }
+    _total_humongous++;
+
+    return false;
+  }
+
+  size_t total_humongous() const { return _total_humongous; }
+  size_t candidate_humongous() const { return _candidate_humongous; }
+};
+
+void G1CollectedHeap::register_humongous_regions_with_in_cset_fast_test() {
+  if (!G1ReclaimDeadHumongousObjectsAtYoungGC) {
+    g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(0, 0);
+    return;
+  }
+
+  RegisterHumongousWithInCSetFastTestClosure cl;
+  heap_region_iterate(&cl);
+  g1_policy()->phase_times()->record_fast_reclaim_humongous_stats(cl.total_humongous(),
+                                                                  cl.candidate_humongous());
+  _has_humongous_reclaim_candidates = cl.candidate_humongous() > 0;
+
+  if (_has_humongous_reclaim_candidates) {
+    clear_humongous_is_live_table();
+  }
+}
+
 void
 G1CollectedHeap::setup_surviving_young_words() {
   assert(_surviving_young_words == NULL, "pre-condition");
@@ -3893,8 +3802,7 @@
     return;
   }
 
-  gclog_or_tty->date_stamp(PrintGCDateStamps);
-  gclog_or_tty->stamp(PrintGCTimeStamps);
+  gclog_or_tty->gclog_stamp(_gc_tracer_stw->gc_id());
 
   GCCauseString gc_cause_str = GCCauseString("GC pause", gc_cause())
     .append(g1_policy()->gcs_are_young() ? "(young)" : "(mixed)")
@@ -4015,6 +3923,7 @@
       increment_gc_time_stamp();
 
       verify_before_gc();
+      check_bitmaps("GC Start");
 
       COMPILER2_PRESENT(DerivedPointerTable::clear());
 
@@ -4090,6 +3999,8 @@
 
         g1_policy()->finalize_cset(target_pause_time_ms, evacuation_info);
 
+        register_humongous_regions_with_in_cset_fast_test();
+
         _cm->note_start_of_gc();
         // We should not verify the per-thread SATB buffers given that
         // we have not filtered them yet (we'll do so during the
@@ -4140,6 +4051,9 @@
                                  true  /* verify_fingers */);
 
         free_collection_set(g1_policy()->collection_set(), evacuation_info);
+
+        eagerly_reclaim_humongous_regions();
+
         g1_policy()->clear_collection_set();
 
         cleanup_surviving_young_words();
@@ -4147,9 +4061,6 @@
         // Start a new incremental collection set for the next pause.
         g1_policy()->start_incremental_cset_building();
 
-        // Clear the _cset_fast_test bitmap in anticipation of adding
-        // regions to the incremental collection set for the next
-        // evacuation pause.
         clear_cset_fast_test();
 
         _young_list->reset_sampled_info();
@@ -4214,10 +4125,7 @@
             // No need for an ergo verbose message here,
             // expansion_amount() does this when it returns a value > 0.
             if (!expand(expand_bytes)) {
-              // We failed to expand the heap so let's verify that
-              // committed/uncommitted amount match the backing store
-              assert(capacity() == _g1_storage.committed_size(), "committed size mismatch");
-              assert(max_capacity() == _g1_storage.reserved_size(), "reserved size mismatch");
+              // We failed to expand the heap. Cannot do anything about it.
             }
           }
         }
@@ -4263,6 +4171,7 @@
         increment_gc_time_stamp();
 
         verify_after_gc();
+        check_bitmaps("GC End");
 
         assert(!ref_processor_stw()->discovery_enabled(), "Postcondition");
         ref_processor_stw()->verify_no_references_recorded();
@@ -4276,10 +4185,6 @@
       // RETIRE events are generated before the end GC event.
       _hr_printer.end_gc(false /* full */, (size_t) total_collections());
 
-      if (mark_in_progress()) {
-        concurrent_mark()->update_g1_committed();
-      }
-
 #ifdef TRACESPINNING
       ParallelTaskTerminator::print_termination_counts();
 #endif
@@ -4326,7 +4231,7 @@
     // this point does not assume that we are the only GC thread
     // running. Note: of course, the actual marking work will
     // not start until the safepoint itself is released in
-    // ConcurrentGCThread::safepoint_desynchronize().
+    // SuspendibleThreadSet::desynchronize().
     doConcurrentMark();
   }
 
@@ -4366,11 +4271,7 @@
   assert(_mutator_alloc_region.get() == NULL, "post-condition");
 }
 
-void G1CollectedHeap::init_gc_alloc_regions(EvacuationInfo& evacuation_info) {
-  assert_at_safepoint(true /* should_be_vm_thread */);
-
-  _survivor_gc_alloc_region.init();
-  _old_gc_alloc_region.init();
+void G1CollectedHeap::use_retained_old_gc_alloc_region(EvacuationInfo& evacuation_info) {
   HeapRegion* retained_region = _retained_old_gc_alloc_region;
   _retained_old_gc_alloc_region = NULL;
 
@@ -4388,7 +4289,7 @@
       !(retained_region->top() == retained_region->end()) &&
       !retained_region->is_empty() &&
       !retained_region->isHumongous()) {
-    retained_region->set_saved_mark();
+    retained_region->record_top_and_timestamp();
     // The retained region was added to the old region set when it was
     // retired. We have to remove it now, since we don't allow regions
     // we allocate to in the region sets. We'll re-add it later, when
@@ -4402,6 +4303,15 @@
   }
 }
 
+void G1CollectedHeap::init_gc_alloc_regions(EvacuationInfo& evacuation_info) {
+  assert_at_safepoint(true /* should_be_vm_thread */);
+
+  _survivor_gc_alloc_region.init();
+  _old_gc_alloc_region.init();
+
+  use_retained_old_gc_alloc_region(evacuation_info);
+}
+
 void G1CollectedHeap::release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info) {
   evacuation_info.set_allocation_regions(_survivor_gc_alloc_region.count() +
                                          _old_gc_alloc_region.count());
@@ -4593,153 +4503,22 @@
 }
 
 G1ParGCAllocBuffer::G1ParGCAllocBuffer(size_t gclab_word_size) :
-  ParGCAllocBuffer(gclab_word_size), _retired(false) { }
-
-G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
-  : _g1h(g1h),
-    _refs(g1h->task_queue(queue_num)),
-    _dcq(&g1h->dirty_card_queue_set()),
-    _ct_bs(g1h->g1_barrier_set()),
-    _g1_rem(g1h->g1_rem_set()),
-    _hash_seed(17), _queue_num(queue_num),
-    _term_attempts(0),
-    _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)),
-    _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)),
-    _age_table(false), _scanner(g1h, this, rp),
-    _strong_roots_time(0), _term_time(0),
-    _alloc_buffer_waste(0), _undo_waste(0) {
-  // we allocate G1YoungSurvRateNumRegions plus one entries, since
-  // we "sacrifice" entry 0 to keep track of surviving bytes for
-  // non-young regions (where the age is -1)
-  // We also add a few elements at the beginning and at the end in
-  // an attempt to eliminate cache contention
-  uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
-  uint array_length = PADDING_ELEM_NUM +
-                      real_length +
-                      PADDING_ELEM_NUM;
-  _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
-  if (_surviving_young_words_base == NULL)
-    vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
-                          "Not enough space for young surv histo.");
-  _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
-  memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
-
-  _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer;
-  _alloc_buffers[GCAllocForTenured]  = &_tenured_alloc_buffer;
-
-  _start = os::elapsedTime();
-}
-
-void
-G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st)
-{
-  st->print_raw_cr("GC Termination Stats");
-  st->print_raw_cr("     elapsed  --strong roots-- -------termination-------"
-                   " ------waste (KiB)------");
-  st->print_raw_cr("thr     ms        ms      %        ms      %    attempts"
-                   "  total   alloc    undo");
-  st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"
-                   " ------- ------- -------");
-}
-
-void
-G1ParScanThreadState::print_termination_stats(int i,
-                                              outputStream* const st) const
-{
-  const double elapsed_ms = elapsed_time() * 1000.0;
-  const double s_roots_ms = strong_roots_time() * 1000.0;
-  const double term_ms    = term_time() * 1000.0;
-  st->print_cr("%3d %9.2f %9.2f %6.2f "
-               "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
-               SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
-               i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
-               term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
-               (alloc_buffer_waste() + undo_waste()) * HeapWordSize / K,
-               alloc_buffer_waste() * HeapWordSize / K,
-               undo_waste() * HeapWordSize / K);
-}
-
-#ifdef ASSERT
-bool G1ParScanThreadState::verify_ref(narrowOop* ref) const {
-  assert(ref != NULL, "invariant");
-  assert(UseCompressedOops, "sanity");
-  assert(!has_partial_array_mask(ref), err_msg("ref=" PTR_FORMAT, ref));
-  oop p = oopDesc::load_decode_heap_oop(ref);
-  assert(_g1h->is_in_g1_reserved(p),
-         err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, (void *)p));
-  return true;
-}
-
-bool G1ParScanThreadState::verify_ref(oop* ref) const {
-  assert(ref != NULL, "invariant");
-  if (has_partial_array_mask(ref)) {
-    // Must be in the collection set--it's already been copied.
-    oop p = clear_partial_array_mask(ref);
-    assert(_g1h->obj_in_cs(p),
-           err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, (void *)p));
-  } else {
-    oop p = oopDesc::load_decode_heap_oop(ref);
-    assert(_g1h->is_in_g1_reserved(p),
-           err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, ref, (void *)p));
-  }
-  return true;
-}
-
-bool G1ParScanThreadState::verify_task(StarTask ref) const {
-  if (ref.is_narrow()) {
-    return verify_ref((narrowOop*) ref);
-  } else {
-    return verify_ref((oop*) ref);
-  }
-}
-#endif // ASSERT
-
-void G1ParScanThreadState::trim_queue() {
-  assert(_evac_failure_cl != NULL, "not set");
-
-  StarTask ref;
-  do {
-    // Drain the overflow stack first, so other threads can steal.
-    while (refs()->pop_overflow(ref)) {
-      deal_with_reference(ref);
-    }
-
-    while (refs()->pop_local(ref)) {
-      deal_with_reference(ref);
-    }
-  } while (!refs()->is_empty());
-}
-
-G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1,
-                                     G1ParScanThreadState* par_scan_state) :
-  _g1(g1), _par_scan_state(par_scan_state),
-  _worker_id(par_scan_state->queue_num()) { }
+  ParGCAllocBuffer(gclab_word_size), _retired(true) { }
 
 void G1ParCopyHelper::mark_object(oop obj) {
-#ifdef ASSERT
-  HeapRegion* hr = _g1->heap_region_containing(obj);
-  assert(hr != NULL, "sanity");
-  assert(!hr->in_collection_set(), "should not mark objects in the CSet");
-#endif // ASSERT
+  assert(!_g1->heap_region_containing(obj)->in_collection_set(), "should not mark objects in the CSet");
 
   // We know that the object is not moving so it's safe to read its size.
   _cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
 }
 
 void G1ParCopyHelper::mark_forwarded_object(oop from_obj, oop to_obj) {
-#ifdef ASSERT
   assert(from_obj->is_forwarded(), "from obj should be forwarded");
   assert(from_obj->forwardee() == to_obj, "to obj should be the forwardee");
   assert(from_obj != to_obj, "should not be self-forwarded");
 
-  HeapRegion* from_hr = _g1->heap_region_containing(from_obj);
-  assert(from_hr != NULL, "sanity");
-  assert(from_hr->in_collection_set(), "from obj should be in the CSet");
-
-  HeapRegion* to_hr = _g1->heap_region_containing(to_obj);
-  assert(to_hr != NULL, "sanity");
-  assert(!to_hr->in_collection_set(), "should not mark objects in the CSet");
-#endif // ASSERT
+  assert(_g1->heap_region_containing(from_obj)->in_collection_set(), "from obj should be in the CSet");
+  assert(!_g1->heap_region_containing(to_obj)->in_collection_set(), "should not mark objects in the CSet");
 
   // The object might be in the process of being copied by another
   // worker so we cannot trust that its to-space image is
@@ -4748,107 +4527,6 @@
   _cm->grayRoot(to_obj, (size_t) from_obj->size(), _worker_id);
 }
 
-oop G1ParScanThreadState::copy_to_survivor_space(oop const old) {
-  size_t word_sz = old->size();
-  HeapRegion* from_region = _g1h->heap_region_containing_raw(old);
-  // +1 to make the -1 indexes valid...
-  int       young_index = from_region->young_index_in_cset()+1;
-  assert( (from_region->is_young() && young_index >  0) ||
-         (!from_region->is_young() && young_index == 0), "invariant" );
-  G1CollectorPolicy* g1p = _g1h->g1_policy();
-  markOop m = old->mark();
-  int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age()
-                                           : m->age();
-  GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age,
-                                                             word_sz);
-  HeapWord* obj_ptr = allocate(alloc_purpose, word_sz);
-#ifndef PRODUCT
-  // Should this evacuation fail?
-  if (_g1h->evacuation_should_fail()) {
-    if (obj_ptr != NULL) {
-      undo_allocation(alloc_purpose, obj_ptr, word_sz);
-      obj_ptr = NULL;
-    }
-  }
-#endif // !PRODUCT
-
-  if (obj_ptr == NULL) {
-    // This will either forward-to-self, or detect that someone else has
-    // installed a forwarding pointer.
-    return _g1h->handle_evacuation_failure_par(this, old);
-  }
-
-  oop obj = oop(obj_ptr);
-
-  // We're going to allocate linearly, so might as well prefetch ahead.
-  Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes);
-
-  oop forward_ptr = old->forward_to_atomic(obj);
-  if (forward_ptr == NULL) {
-    Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
-
-    // alloc_purpose is just a hint to allocate() above, recheck the type of region
-    // we actually allocated from and update alloc_purpose accordingly
-    HeapRegion* to_region = _g1h->heap_region_containing_raw(obj_ptr);
-    alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured;
-
-    if (g1p->track_object_age(alloc_purpose)) {
-      // We could simply do obj->incr_age(). However, this causes a
-      // performance issue. obj->incr_age() will first check whether
-      // the object has a displaced mark by checking its mark word;
-      // getting the mark word from the new location of the object
-      // stalls. So, given that we already have the mark word and we
-      // are about to install it anyway, it's better to increase the
-      // age on the mark word, when the object does not have a
-      // displaced mark word. We're not expecting many objects to have
-      // a displaced marked word, so that case is not optimized
-      // further (it could be...) and we simply call obj->incr_age().
-
-      if (m->has_displaced_mark_helper()) {
-        // in this case, we have to install the mark word first,
-        // otherwise obj looks to be forwarded (the old mark word,
-        // which contains the forward pointer, was copied)
-        obj->set_mark(m);
-        obj->incr_age();
-      } else {
-        m = m->incr_age();
-        obj->set_mark(m);
-      }
-      age_table()->add(obj, word_sz);
-    } else {
-      obj->set_mark(m);
-    }
-
-    if (G1StringDedup::is_enabled()) {
-      G1StringDedup::enqueue_from_evacuation(from_region->is_young(),
-                                             to_region->is_young(),
-                                             queue_num(),
-                                             obj);
-    }
-
-    size_t* surv_young_words = surviving_young_words();
-    surv_young_words[young_index] += word_sz;
-
-    if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
-      // We keep track of the next start index in the length field of
-      // the to-space object. The actual length can be found in the
-      // length field of the from-space object.
-      arrayOop(obj)->set_length(0);
-      oop* old_p = set_partial_array_mask(old);
-      push_on_queue(old_p);
-    } else {
-      // No point in using the slower heap_region_containing() method,
-      // given that we know obj is in the heap.
-      _scanner.set_region(_g1h->heap_region_containing_raw(obj));
-      obj->oop_iterate_backwards(&_scanner);
-    }
-  } else {
-    undo_allocation(alloc_purpose, obj_ptr, word_sz);
-    obj = forward_ptr;
-  }
-  return obj;
-}
-
 template <class T>
 void G1ParCopyHelper::do_klass_barrier(T* p, oop new_obj) {
   if (_g1->heap_region_containing_raw(new_obj)->is_young()) {
@@ -4856,7 +4534,7 @@
   }
 }
 
-template <G1Barrier barrier, bool do_mark_object>
+template <G1Barrier barrier, G1Mark do_mark_object>
 template <class T>
 void G1ParCopyClosure<barrier, do_mark_object>::do_oop_work(T* p) {
   T heap_oop = oopDesc::load_heap_oop(p);
@@ -4869,7 +4547,9 @@
 
   assert(_worker_id == _par_scan_state->queue_num(), "sanity");
 
-  if (_g1->in_cset_fast_test(obj)) {
+  G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj);
+
+  if (state == G1CollectedHeap::InCSet) {
     oop forwardee;
     if (obj->is_forwarded()) {
       forwardee = obj->forwardee();
@@ -4878,7 +4558,7 @@
     }
     assert(forwardee != NULL, "forwardee should not be NULL");
     oopDesc::encode_store_heap_oop(p, forwardee);
-    if (do_mark_object && forwardee != obj) {
+    if (do_mark_object != G1MarkNone && forwardee != obj) {
       // If the object is self-forwarded we don't need to explicitly
       // mark it, the evacuation failure protocol will do so.
       mark_forwarded_object(obj, forwardee);
@@ -4888,10 +4568,12 @@
       do_klass_barrier(p, forwardee);
     }
   } else {
+    if (state == G1CollectedHeap::IsHumongous) {
+      _g1->set_humongous_is_live(obj);
+    }
     // The object is not in collection set. If we're a root scanning
-    // closure during an initial mark pause (i.e. do_mark_object will
-    // be true) then attempt to mark the object.
-    if (do_mark_object) {
+    // closure during an initial mark pause then attempt to mark the object.
+    if (do_mark_object == G1MarkFromRoot) {
       mark_object(obj);
     }
   }
@@ -4901,8 +4583,8 @@
   }
 }
 
-template void G1ParCopyClosure<G1BarrierEvac, false>::do_oop_work(oop* p);
-template void G1ParCopyClosure<G1BarrierEvac, false>::do_oop_work(narrowOop* p);
+template void G1ParCopyClosure<G1BarrierEvac, G1MarkNone>::do_oop_work(oop* p);
+template void G1ParCopyClosure<G1BarrierEvac, G1MarkNone>::do_oop_work(narrowOop* p);
 
 class G1ParEvacuateFollowersClosure : public VoidClosure {
 protected:
@@ -4938,27 +4620,11 @@
 }
 
 void G1ParEvacuateFollowersClosure::do_void() {
-  StarTask stolen_task;
   G1ParScanThreadState* const pss = par_scan_state();
   pss->trim_queue();
-
   do {
-    while (queues()->steal(pss->queue_num(), pss->hash_seed(), stolen_task)) {
-      assert(pss->verify_task(stolen_task), "sanity");
-      if (stolen_task.is_narrow()) {
-        pss->deal_with_reference((narrowOop*) stolen_task);
-      } else {
-        pss->deal_with_reference((oop*) stolen_task);
-      }
-
-      // We've just processed a reference and we might have made
-      // available new entries on the queues. So we have to make sure
-      // we drain the queues as necessary.
-      pss->trim_queue();
-    }
+    pss->steal_and_trim_queue(queues());
   } while (!offer_termination());
-
-  pss->retire_alloc_buffers();
 }
 
 class G1KlassScanClosure : public KlassClosure {
@@ -4997,14 +4663,8 @@
   Mutex _stats_lock;
   Mutex* stats_lock() { return &_stats_lock; }
 
-  size_t getNCards() {
-    return (_g1h->capacity() + G1BlockOffsetSharedArray::N_bytes - 1)
-      / G1BlockOffsetSharedArray::N_bytes;
-  }
-
 public:
-  G1ParTask(G1CollectedHeap* g1h,
-            RefToScanQueueSet *task_queues)
+  G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues)
     : AbstractGangTask("G1 collection"),
       _g1h(g1h),
       _queues(task_queues),
@@ -5032,6 +4692,51 @@
     _n_workers = active_workers;
   }
 
+  // Helps out with CLD processing.
+  //
+  // During InitialMark we need to:
+  // 1) Scavenge all CLDs for the young GC.
+  // 2) Mark all objects directly reachable from strong CLDs.
+  template <G1Mark do_mark_object>
+  class G1CLDClosure : public CLDClosure {
+    G1ParCopyClosure<G1BarrierNone,  do_mark_object>* _oop_closure;
+    G1ParCopyClosure<G1BarrierKlass, do_mark_object>  _oop_in_klass_closure;
+    G1KlassScanClosure                                _klass_in_cld_closure;
+    bool                                              _claim;
+
+   public:
+    G1CLDClosure(G1ParCopyClosure<G1BarrierNone, do_mark_object>* oop_closure,
+                 bool only_young, bool claim)
+        : _oop_closure(oop_closure),
+          _oop_in_klass_closure(oop_closure->g1(),
+                                oop_closure->pss(),
+                                oop_closure->rp()),
+          _klass_in_cld_closure(&_oop_in_klass_closure, only_young),
+          _claim(claim) {
+
+    }
+
+    void do_cld(ClassLoaderData* cld) {
+      cld->oops_do(_oop_closure, &_klass_in_cld_closure, _claim);
+    }
+  };
+
+  class G1CodeBlobClosure: public CodeBlobClosure {
+    OopClosure* _f;
+
+   public:
+    G1CodeBlobClosure(OopClosure* f) : _f(f) {}
+    void do_code_blob(CodeBlob* blob) {
+      nmethod* that = blob->as_nmethod_or_null();
+      if (that != NULL) {
+        if (!that->test_set_oops_do_mark()) {
+          that->oops_do(_f);
+          that->fix_oop_relocations();
+        }
+      }
+    }
+  };
+
   void work(uint worker_id) {
     if (worker_id >= _n_workers) return;  // no work needed this round
 
@@ -5049,40 +4754,67 @@
 
       pss.set_evac_failure_closure(&evac_failure_cl);
 
-      G1ParScanExtRootClosure        only_scan_root_cl(_g1h, &pss, rp);
-      G1ParScanMetadataClosure       only_scan_metadata_cl(_g1h, &pss, rp);
+      bool only_young = _g1h->g1_policy()->gcs_are_young();
 
-      G1ParScanAndMarkExtRootClosure scan_mark_root_cl(_g1h, &pss, rp);
-      G1ParScanAndMarkMetadataClosure scan_mark_metadata_cl(_g1h, &pss, rp);
+      // Non-IM young GC.
+      G1ParCopyClosure<G1BarrierNone, G1MarkNone>             scan_only_root_cl(_g1h, &pss, rp);
+      G1CLDClosure<G1MarkNone>                                scan_only_cld_cl(&scan_only_root_cl,
+                                                                               only_young, // Only process dirty klasses.
+                                                                               false);     // No need to claim CLDs.
+      // IM young GC.
+      //    Strong roots closures.
+      G1ParCopyClosure<G1BarrierNone, G1MarkFromRoot>         scan_mark_root_cl(_g1h, &pss, rp);
+      G1CLDClosure<G1MarkFromRoot>                            scan_mark_cld_cl(&scan_mark_root_cl,
+                                                                               false, // Process all klasses.
+                                                                               true); // Need to claim CLDs.
+      //    Weak roots closures.
+      G1ParCopyClosure<G1BarrierNone, G1MarkPromotedFromRoot> scan_mark_weak_root_cl(_g1h, &pss, rp);
+      G1CLDClosure<G1MarkPromotedFromRoot>                    scan_mark_weak_cld_cl(&scan_mark_weak_root_cl,
+                                                                                    false, // Process all klasses.
+                                                                                    true); // Need to claim CLDs.
 
-      bool only_young                 = _g1h->g1_policy()->gcs_are_young();
-      G1KlassScanClosure              scan_mark_klasses_cl_s(&scan_mark_metadata_cl, false);
-      G1KlassScanClosure              only_scan_klasses_cl_s(&only_scan_metadata_cl, only_young);
+      G1CodeBlobClosure scan_only_code_cl(&scan_only_root_cl);
+      G1CodeBlobClosure scan_mark_code_cl(&scan_mark_root_cl);
+      // IM Weak code roots are handled later.
 
-      OopClosure*                    scan_root_cl = &only_scan_root_cl;
-      G1KlassScanClosure*            scan_klasses_cl = &only_scan_klasses_cl_s;
+      OopClosure* strong_root_cl;
+      OopClosure* weak_root_cl;
+      CLDClosure* strong_cld_cl;
+      CLDClosure* weak_cld_cl;
+      CodeBlobClosure* strong_code_cl;
 
       if (_g1h->g1_policy()->during_initial_mark_pause()) {
         // We also need to mark copied objects.
-        scan_root_cl = &scan_mark_root_cl;
-        scan_klasses_cl = &scan_mark_klasses_cl_s;
+        strong_root_cl = &scan_mark_root_cl;
+        strong_cld_cl  = &scan_mark_cld_cl;
+        strong_code_cl = &scan_mark_code_cl;
+        if (ClassUnloadingWithConcurrentMark) {
+          weak_root_cl = &scan_mark_weak_root_cl;
+          weak_cld_cl  = &scan_mark_weak_cld_cl;
+        } else {
+          weak_root_cl = &scan_mark_root_cl;
+          weak_cld_cl  = &scan_mark_cld_cl;
+        }
+      } else {
+        strong_root_cl = &scan_only_root_cl;
+        weak_root_cl   = &scan_only_root_cl;
+        strong_cld_cl  = &scan_only_cld_cl;
+        weak_cld_cl    = &scan_only_cld_cl;
+        strong_code_cl = &scan_only_code_cl;
       }
 
-      G1ParPushHeapRSClosure          push_heap_rs_cl(_g1h, &pss);
 
-      // Don't scan the scavengable methods in the code cache as part
-      // of strong root scanning. The code roots that point into a
-      // region in the collection set are scanned when we scan the
-      // region's RSet.
-      int so = SharedHeap::SO_AllClasses | SharedHeap::SO_Strings;
+      G1ParPushHeapRSClosure  push_heap_rs_cl(_g1h, &pss);
 
       pss.start_strong_roots();
-      _g1h->g1_process_strong_roots(/* is scavenging */ true,
-                                    SharedHeap::ScanningOption(so),
-                                    scan_root_cl,
-                                    &push_heap_rs_cl,
-                                    scan_klasses_cl,
-                                    worker_id);
+      _g1h->g1_process_roots(strong_root_cl,
+                             weak_root_cl,
+                             &push_heap_rs_cl,
+                             strong_cld_cl,
+                             weak_cld_cl,
+                             strong_code_cl,
+                             worker_id);
+
       pss.end_strong_roots();
 
       {
@@ -5102,7 +4834,7 @@
         pss.print_termination_stats(worker_id);
       }
 
-      assert(pss.refs()->is_empty(), "should be empty");
+      assert(pss.queue_is_empty(), "should be empty");
 
       // Close the inner scope so that the ResourceMark and HandleMark
       // destructors are executed here and are included as part of the
@@ -5120,30 +4852,32 @@
 
 void
 G1CollectedHeap::
-g1_process_strong_roots(bool is_scavenging,
-                        ScanningOption so,
-                        OopClosure* scan_non_heap_roots,
-                        OopsInHeapRegionClosure* scan_rs,
-                        G1KlassScanClosure* scan_klasses,
-                        uint worker_i) {
+g1_process_roots(OopClosure* scan_non_heap_roots,
+                 OopClosure* scan_non_heap_weak_roots,
+                 OopsInHeapRegionClosure* scan_rs,
+                 CLDClosure* scan_strong_clds,
+                 CLDClosure* scan_weak_clds,
+                 CodeBlobClosure* scan_strong_code,
+                 uint worker_i) {
 
-  // First scan the strong roots
+  // First scan the shared roots.
   double ext_roots_start = os::elapsedTime();
   double closure_app_time_sec = 0.0;
 
+  bool during_im = _g1h->g1_policy()->during_initial_mark_pause();
+  bool trace_metadata = during_im && ClassUnloadingWithConcurrentMark;
+
   BufferingOopClosure buf_scan_non_heap_roots(scan_non_heap_roots);
+  BufferingOopClosure buf_scan_non_heap_weak_roots(scan_non_heap_weak_roots);
 
-  assert(so & SO_CodeCache || scan_rs != NULL, "must scan code roots somehow");
-  // Walk the code cache/strong code roots w/o buffering, because StarTask
-  // cannot handle unaligned oop locations.
-  CodeBlobToOopClosure eager_scan_code_roots(scan_non_heap_roots, true /* do_marking */);
-
-  process_strong_roots(false, // no scoping; this is parallel code
-                       is_scavenging, so,
-                       &buf_scan_non_heap_roots,
-                       &eager_scan_code_roots,
-                       scan_klasses
-                       );
+  process_roots(false, // no scoping; this is parallel code
+                SharedHeap::SO_None,
+                &buf_scan_non_heap_roots,
+                &buf_scan_non_heap_weak_roots,
+                scan_strong_clds,
+                // Unloading Initial Marks handle the weak CLDs separately.
+                (trace_metadata ? NULL : scan_weak_clds),
+                scan_strong_code);
 
   // Now the CM ref_processor roots.
   if (!_process_strong_tasks->is_task_claimed(G1H_PS_refProcessor_oops_do)) {
@@ -5154,10 +4888,21 @@
     ref_processor_cm()->weak_oops_do(&buf_scan_non_heap_roots);
   }
 
+  if (trace_metadata) {
+    // Barrier to make sure all workers passed
+    // the strong CLD and strong nmethods phases.
+    active_strong_roots_scope()->wait_until_all_workers_done_with_threads(n_par_threads());
+
+    // Now take the complement of the strong CLDs.
+    ClassLoaderDataGraph::roots_cld_do(NULL, scan_weak_clds);
+  }
+
   // Finish up any enqueued closure apps (attributed as object copy time).
   buf_scan_non_heap_roots.done();
+  buf_scan_non_heap_weak_roots.done();
 
-  double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds();
+  double obj_copy_time_sec = buf_scan_non_heap_roots.closure_app_seconds()
+      + buf_scan_non_heap_weak_roots.closure_app_seconds();
 
   g1_policy()->phase_times()->record_obj_copy_time(worker_i, obj_copy_time_sec * 1000.0);
 
@@ -5181,30 +4926,12 @@
   }
   g1_policy()->phase_times()->record_satb_filtering_time(worker_i, satb_filtering_ms);
 
-  // If this is an initial mark pause, and we're not scanning
-  // the entire code cache, we need to mark the oops in the
-  // strong code root lists for the regions that are not in
-  // the collection set.
-  // Note all threads participate in this set of root tasks.
-  double mark_strong_code_roots_ms = 0.0;
-  if (g1_policy()->during_initial_mark_pause() && !(so & SO_CodeCache)) {
-    double mark_strong_roots_start = os::elapsedTime();
-    mark_strong_code_roots(worker_i);
-    mark_strong_code_roots_ms = (os::elapsedTime() - mark_strong_roots_start) * 1000.0;
-  }
-  g1_policy()->phase_times()->record_strong_code_root_mark_time(worker_i, mark_strong_code_roots_ms);
-
   // Now scan the complement of the collection set.
-  if (scan_rs != NULL) {
-    g1_rem_set()->oops_into_collection_set_do(scan_rs, &eager_scan_code_roots, worker_i);
-  }
-  _process_strong_tasks->all_tasks_completed();
-}
+  MarkingCodeBlobClosure scavenge_cs_nmethods(scan_non_heap_weak_roots, CodeBlobToOopClosure::FixRelocations);
 
-void
-G1CollectedHeap::g1_process_weak_roots(OopClosure* root_closure) {
-  CodeBlobToOopClosure roots_in_blobs(root_closure, /*do_marking=*/ false);
-  SharedHeap::process_weak_roots(root_closure, &roots_in_blobs);
+  g1_rem_set()->oops_into_collection_set_do(scan_rs, &scavenge_cs_nmethods, worker_i);
+
+  _process_strong_tasks->all_tasks_completed();
 }
 
 class G1StringSymbolTableUnlinkTask : public AbstractGangTask {
@@ -5224,7 +4951,8 @@
   bool _do_in_parallel;
 public:
   G1StringSymbolTableUnlinkTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols) :
-    AbstractGangTask("Par String/Symbol table unlink"), _is_alive(is_alive),
+    AbstractGangTask("String/Symbol Unlinking"),
+    _is_alive(is_alive),
     _do_in_parallel(G1CollectedHeap::use_parallel_gc_threads()),
     _process_strings(process_strings), _strings_processed(0), _strings_removed(0),
     _process_symbols(process_symbols), _symbols_processed(0), _symbols_removed(0) {
@@ -5246,6 +4974,14 @@
     guarantee(!_process_symbols || !_do_in_parallel || SymbolTable::parallel_claimed_index() >= _initial_symbol_table_size,
               err_msg("claim value "INT32_FORMAT" after unlink less than initial symbol table size "INT32_FORMAT,
                       SymbolTable::parallel_claimed_index(), _initial_symbol_table_size));
+
+    if (G1TraceStringSymbolTableScrubbing) {
+      gclog_or_tty->print_cr("Cleaned string and symbol table, "
+                             "strings: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed, "
+                             "symbols: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed",
+                             strings_processed(), strings_removed(),
+                             symbols_processed(), symbols_removed());
+    }
   }
 
   void work(uint worker_id) {
@@ -5281,12 +5017,279 @@
   size_t symbols_removed()   const { return (size_t)_symbols_removed; }
 };
 
-void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive,
-                                                     bool process_strings, bool process_symbols) {
-  uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
-                   _g1h->workers()->active_workers() : 1);
+class G1CodeCacheUnloadingTask VALUE_OBJ_CLASS_SPEC {
+private:
+  static Monitor* _lock;
 
-  G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols);
+  BoolObjectClosure* const _is_alive;
+  const bool               _unloading_occurred;
+  const uint               _num_workers;
+
+  // Variables used to claim nmethods.
+  nmethod* _first_nmethod;
+  volatile nmethod* _claimed_nmethod;
+
+  // The list of nmethods that need to be processed by the second pass.
+  volatile nmethod* _postponed_list;
+  volatile uint     _num_entered_barrier;
+
+ public:
+  G1CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred) :
+      _is_alive(is_alive),
+      _unloading_occurred(unloading_occurred),
+      _num_workers(num_workers),
+      _first_nmethod(NULL),
+      _claimed_nmethod(NULL),
+      _postponed_list(NULL),
+      _num_entered_barrier(0)
+  {
+    nmethod::increase_unloading_clock();
+    _first_nmethod = CodeCache::alive_nmethod(CodeCache::first());
+    _claimed_nmethod = (volatile nmethod*)_first_nmethod;
+  }
+
+  ~G1CodeCacheUnloadingTask() {
+    CodeCache::verify_clean_inline_caches();
+
+    CodeCache::set_needs_cache_clean(false);
+    guarantee(CodeCache::scavenge_root_nmethods() == NULL, "Must be");
+
+    CodeCache::verify_icholder_relocations();
+  }
+
+ private:
+  void add_to_postponed_list(nmethod* nm) {
+      nmethod* old;
+      do {
+        old = (nmethod*)_postponed_list;
+        nm->set_unloading_next(old);
+      } while ((nmethod*)Atomic::cmpxchg_ptr(nm, &_postponed_list, old) != old);
+  }
+
+  void clean_nmethod(nmethod* nm) {
+    bool postponed = nm->do_unloading_parallel(_is_alive, _unloading_occurred);
+
+    if (postponed) {
+      // This nmethod referred to an nmethod that has not been cleaned/unloaded yet.
+      add_to_postponed_list(nm);
+    }
+
+    // Mark that this thread has been cleaned/unloaded.
+    // After this call, it will be safe to ask if this nmethod was unloaded or not.
+    nm->set_unloading_clock(nmethod::global_unloading_clock());
+  }
+
+  void clean_nmethod_postponed(nmethod* nm) {
+    nm->do_unloading_parallel_postponed(_is_alive, _unloading_occurred);
+  }
+
+  static const int MaxClaimNmethods = 16;
+
+  void claim_nmethods(nmethod** claimed_nmethods, int *num_claimed_nmethods) {
+    nmethod* first;
+    nmethod* last;
+
+    do {
+      *num_claimed_nmethods = 0;
+
+      first = last = (nmethod*)_claimed_nmethod;
+
+      if (first != NULL) {
+        for (int i = 0; i < MaxClaimNmethods; i++) {
+          last = CodeCache::alive_nmethod(CodeCache::next(last));
+
+          if (last == NULL) {
+            break;
+          }
+
+          claimed_nmethods[i] = last;
+          (*num_claimed_nmethods)++;
+        }
+      }
+
+    } while ((nmethod*)Atomic::cmpxchg_ptr(last, &_claimed_nmethod, first) != first);
+  }
+
+  nmethod* claim_postponed_nmethod() {
+    nmethod* claim;
+    nmethod* next;
+
+    do {
+      claim = (nmethod*)_postponed_list;
+      if (claim == NULL) {
+        return NULL;
+      }
+
+      next = claim->unloading_next();
+
+    } while ((nmethod*)Atomic::cmpxchg_ptr(next, &_postponed_list, claim) != claim);
+
+    return claim;
+  }
+
+ public:
+  // Mark that we're done with the first pass of nmethod cleaning.
+  void barrier_mark(uint worker_id) {
+    MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+    _num_entered_barrier++;
+    if (_num_entered_barrier == _num_workers) {
+      ml.notify_all();
+    }
+  }
+
+  // See if we have to wait for the other workers to
+  // finish their first-pass nmethod cleaning work.
+  void barrier_wait(uint worker_id) {
+    if (_num_entered_barrier < _num_workers) {
+      MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+      while (_num_entered_barrier < _num_workers) {
+          ml.wait(Mutex::_no_safepoint_check_flag, 0, false);
+      }
+    }
+  }
+
+  // Cleaning and unloading of nmethods. Some work has to be postponed
+  // to the second pass, when we know which nmethods survive.
+  void work_first_pass(uint worker_id) {
+    // The first nmethods is claimed by the first worker.
+    if (worker_id == 0 && _first_nmethod != NULL) {
+      clean_nmethod(_first_nmethod);
+      _first_nmethod = NULL;
+    }
+
+    int num_claimed_nmethods;
+    nmethod* claimed_nmethods[MaxClaimNmethods];
+
+    while (true) {
+      claim_nmethods(claimed_nmethods, &num_claimed_nmethods);
+
+      if (num_claimed_nmethods == 0) {
+        break;
+      }
+
+      for (int i = 0; i < num_claimed_nmethods; i++) {
+        clean_nmethod(claimed_nmethods[i]);
+      }
+    }
+  }
+
+  void work_second_pass(uint worker_id) {
+    nmethod* nm;
+    // Take care of postponed nmethods.
+    while ((nm = claim_postponed_nmethod()) != NULL) {
+      clean_nmethod_postponed(nm);
+    }
+  }
+};
+
+Monitor* G1CodeCacheUnloadingTask::_lock = new Monitor(Mutex::leaf, "Code Cache Unload lock");
+
+class G1KlassCleaningTask : public StackObj {
+  BoolObjectClosure*                      _is_alive;
+  volatile jint                           _clean_klass_tree_claimed;
+  ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator;
+
+ public:
+  G1KlassCleaningTask(BoolObjectClosure* is_alive) :
+      _is_alive(is_alive),
+      _clean_klass_tree_claimed(0),
+      _klass_iterator() {
+  }
+
+ private:
+  bool claim_clean_klass_tree_task() {
+    if (_clean_klass_tree_claimed) {
+      return false;
+    }
+
+    return Atomic::cmpxchg(1, (jint*)&_clean_klass_tree_claimed, 0) == 0;
+  }
+
+  InstanceKlass* claim_next_klass() {
+    Klass* klass;
+    do {
+      klass =_klass_iterator.next_klass();
+    } while (klass != NULL && !klass->oop_is_instance());
+
+    return (InstanceKlass*)klass;
+  }
+
+public:
+
+  void clean_klass(InstanceKlass* ik) {
+    ik->clean_implementors_list(_is_alive);
+    ik->clean_method_data(_is_alive);
+
+    // G1 specific cleanup work that has
+    // been moved here to be done in parallel.
+    ik->clean_dependent_nmethods();
+  }
+
+  void work() {
+    ResourceMark rm;
+
+    // One worker will clean the subklass/sibling klass tree.
+    if (claim_clean_klass_tree_task()) {
+      Klass::clean_subklass_tree(_is_alive);
+    }
+
+    // All workers will help cleaning the classes,
+    InstanceKlass* klass;
+    while ((klass = claim_next_klass()) != NULL) {
+      clean_klass(klass);
+    }
+  }
+};
+
+// To minimize the remark pause times, the tasks below are done in parallel.
+class G1ParallelCleaningTask : public AbstractGangTask {
+private:
+  G1StringSymbolTableUnlinkTask _string_symbol_task;
+  G1CodeCacheUnloadingTask      _code_cache_task;
+  G1KlassCleaningTask           _klass_cleaning_task;
+
+public:
+  // The constructor is run in the VMThread.
+  G1ParallelCleaningTask(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, uint num_workers, bool unloading_occurred) :
+      AbstractGangTask("Parallel Cleaning"),
+      _string_symbol_task(is_alive, process_strings, process_symbols),
+      _code_cache_task(num_workers, is_alive, unloading_occurred),
+      _klass_cleaning_task(is_alive) {
+  }
+
+  // The parallel work done by all worker threads.
+  void work(uint worker_id) {
+    // Do first pass of code cache cleaning.
+    _code_cache_task.work_first_pass(worker_id);
+
+    // Let the threads mark that the first pass is done.
+    _code_cache_task.barrier_mark(worker_id);
+
+    // Clean the Strings and Symbols.
+    _string_symbol_task.work(worker_id);
+
+    // Wait for all workers to finish the first code cache cleaning pass.
+    _code_cache_task.barrier_wait(worker_id);
+
+    // Do the second code cache cleaning work, which realize on
+    // the liveness information gathered during the first pass.
+    _code_cache_task.work_second_pass(worker_id);
+
+    // Clean all klasses that were not unloaded.
+    _klass_cleaning_task.work();
+  }
+};
+
+
+void G1CollectedHeap::parallel_cleaning(BoolObjectClosure* is_alive,
+                                        bool process_strings,
+                                        bool process_symbols,
+                                        bool class_unloading_occurred) {
+  uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
+                    workers()->active_workers() : 1);
+
+  G1ParallelCleaningTask g1_unlink_task(is_alive, process_strings, process_symbols,
+                                        n_workers, class_unloading_occurred);
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     set_par_threads(n_workers);
     workers()->run_task(&g1_unlink_task);
@@ -5294,12 +5297,21 @@
   } else {
     g1_unlink_task.work(0);
   }
-  if (G1TraceStringSymbolTableScrubbing) {
-    gclog_or_tty->print_cr("Cleaned string and symbol table, "
-                           "strings: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed, "
-                           "symbols: "SIZE_FORMAT" processed, "SIZE_FORMAT" removed",
-                           g1_unlink_task.strings_processed(), g1_unlink_task.strings_removed(),
-                           g1_unlink_task.symbols_processed(), g1_unlink_task.symbols_removed());
+}
+
+void G1CollectedHeap::unlink_string_and_symbol_table(BoolObjectClosure* is_alive,
+                                                     bool process_strings, bool process_symbols) {
+  {
+    uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
+                     _g1h->workers()->active_workers() : 1);
+    G1StringSymbolTableUnlinkTask g1_unlink_task(is_alive, process_strings, process_symbols);
+    if (G1CollectedHeap::use_parallel_gc_threads()) {
+      set_par_threads(n_workers);
+      workers()->run_task(&g1_unlink_task);
+      set_par_threads(0);
+    } else {
+      g1_unlink_task.work(0);
+    }
   }
 
   if (G1StringDedup::is_enabled()) {
@@ -5307,11 +5319,25 @@
   }
 }
 
-class RedirtyLoggedCardTableEntryFastClosure : public CardTableEntryClosure {
-public:
-  bool do_card_ptr(jbyte* card_ptr, uint worker_i) {
-    *card_ptr = CardTableModRefBS::dirty_card_val();
-    return true;
+class G1RedirtyLoggedCardsTask : public AbstractGangTask {
+ private:
+  DirtyCardQueueSet* _queue;
+ public:
+  G1RedirtyLoggedCardsTask(DirtyCardQueueSet* queue) : AbstractGangTask("Redirty Cards"), _queue(queue) { }
+
+  virtual void work(uint worker_id) {
+    double start_time = os::elapsedTime();
+
+    RedirtyLoggedCardTableEntryClosure cl;
+    if (G1CollectedHeap::heap()->use_parallel_gc_threads()) {
+      _queue->par_apply_closure_to_all_completed_buffers(&cl);
+    } else {
+      _queue->apply_closure_to_all_completed_buffers(&cl);
+    }
+
+    G1GCPhaseTimes* timer = G1CollectedHeap::heap()->g1_policy()->phase_times();
+    timer->record_redirty_logged_cards_time_ms(worker_id, (os::elapsedTime() - start_time) * 1000.0);
+    timer->record_redirty_logged_cards_processed_cards(worker_id, cl.num_processed());
   }
 };
 
@@ -5319,9 +5345,18 @@
   guarantee(G1DeferredRSUpdate, "Must only be called when using deferred RS updates.");
   double redirty_logged_cards_start = os::elapsedTime();
 
-  RedirtyLoggedCardTableEntryFastClosure redirty;
-  dirty_card_queue_set().set_closure(&redirty);
-  dirty_card_queue_set().apply_closure_to_all_completed_buffers();
+  uint n_workers = (G1CollectedHeap::use_parallel_gc_threads() ?
+                   _g1h->workers()->active_workers() : 1);
+
+  G1RedirtyLoggedCardsTask redirty_task(&dirty_card_queue_set());
+  dirty_card_queue_set().reset_for_par_iteration();
+  if (use_parallel_gc_threads()) {
+    set_par_threads(n_workers);
+    workers()->run_task(&redirty_task);
+    set_par_threads(0);
+  } else {
+    redirty_task.work(0);
+  }
 
   DirtyCardQueueSet& dcq = JavaThread::dirty_card_queue_set();
   dcq.merge_bufferlists(&dirty_card_queue_set());
@@ -5360,12 +5395,21 @@
 public:
   G1KeepAliveClosure(G1CollectedHeap* g1) : _g1(g1) {}
   void do_oop(narrowOop* p) { guarantee(false, "Not needed"); }
-  void do_oop(      oop* p) {
+  void do_oop(oop* p) {
     oop obj = *p;
 
-    if (_g1->obj_in_cs(obj)) {
+    G1CollectedHeap::in_cset_state_t cset_state = _g1->in_cset_state(obj);
+    if (obj == NULL || cset_state == G1CollectedHeap::InNeither) {
+      return;
+    }
+    if (cset_state == G1CollectedHeap::InCSet) {
       assert( obj->is_forwarded(), "invariant" );
       *p = obj->forwardee();
+    } else {
+      assert(!obj->is_forwarded(), "invariant" );
+      assert(cset_state == G1CollectedHeap::IsHumongous,
+             err_msg("Only allowed InCSet state is IsHumongous, but is %d", cset_state));
+      _g1->set_humongous_is_live(obj);
     }
   }
 };
@@ -5378,17 +5422,14 @@
 class G1CopyingKeepAliveClosure: public OopClosure {
   G1CollectedHeap*         _g1h;
   OopClosure*              _copy_non_heap_obj_cl;
-  OopsInHeapRegionClosure* _copy_metadata_obj_cl;
   G1ParScanThreadState*    _par_scan_state;
 
 public:
   G1CopyingKeepAliveClosure(G1CollectedHeap* g1h,
                             OopClosure* non_heap_obj_cl,
-                            OopsInHeapRegionClosure* metadata_obj_cl,
                             G1ParScanThreadState* pss):
     _g1h(g1h),
     _copy_non_heap_obj_cl(non_heap_obj_cl),
-    _copy_metadata_obj_cl(metadata_obj_cl),
     _par_scan_state(pss)
   {}
 
@@ -5398,7 +5439,7 @@
   template <class T> void do_oop_work(T* p) {
     oop obj = oopDesc::load_decode_heap_oop(p);
 
-    if (_g1h->obj_in_cs(obj)) {
+    if (_g1h->is_in_cset_or_humongous(obj)) {
       // If the referent object has been forwarded (either copied
       // to a new location or to itself in the event of an
       // evacuation failure) then we need to update the reference
@@ -5421,12 +5462,12 @@
         _par_scan_state->push_on_queue(p);
       } else {
         assert(!Metaspace::contains((const void*)p),
-               err_msg("Otherwise need to call _copy_metadata_obj_cl->do_oop(p) "
+               err_msg("Unexpectedly found a pointer from metadata: "
                               PTR_FORMAT, p));
-          _copy_non_heap_obj_cl->do_oop(p);
-        }
+        _copy_non_heap_obj_cl->do_oop(p);
       }
     }
+  }
 };
 
 // Serial drain queue closure. Called as the 'complete_gc'
@@ -5516,22 +5557,18 @@
     pss.set_evac_failure_closure(&evac_failure_cl);
 
     G1ParScanExtRootClosure        only_copy_non_heap_cl(_g1h, &pss, NULL);
-    G1ParScanMetadataClosure       only_copy_metadata_cl(_g1h, &pss, NULL);
 
     G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, &pss, NULL);
-    G1ParScanAndMarkMetadataClosure copy_mark_metadata_cl(_g1h, &pss, NULL);
 
     OopClosure*                    copy_non_heap_cl = &only_copy_non_heap_cl;
-    OopsInHeapRegionClosure*       copy_metadata_cl = &only_copy_metadata_cl;
 
     if (_g1h->g1_policy()->during_initial_mark_pause()) {
       // We also need to mark copied objects.
       copy_non_heap_cl = &copy_mark_non_heap_cl;
-      copy_metadata_cl = &copy_mark_metadata_cl;
     }
 
     // Keep alive closure.
-    G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, copy_metadata_cl, &pss);
+    G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, &pss);
 
     // Complete GC closure
     G1ParEvacuateFollowersClosure drain_queue(_g1h, &pss, _task_queues, _terminator);
@@ -5622,22 +5659,17 @@
 
     pss.set_evac_failure_closure(&evac_failure_cl);
 
-    assert(pss.refs()->is_empty(), "both queue and overflow should be empty");
-
+    assert(pss.queue_is_empty(), "both queue and overflow should be empty");
 
     G1ParScanExtRootClosure        only_copy_non_heap_cl(_g1h, &pss, NULL);
-    G1ParScanMetadataClosure       only_copy_metadata_cl(_g1h, &pss, NULL);
 
     G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(_g1h, &pss, NULL);
-    G1ParScanAndMarkMetadataClosure copy_mark_metadata_cl(_g1h, &pss, NULL);
 
     OopClosure*                    copy_non_heap_cl = &only_copy_non_heap_cl;
-    OopsInHeapRegionClosure*       copy_metadata_cl = &only_copy_metadata_cl;
 
     if (_g1h->g1_policy()->during_initial_mark_pause()) {
       // We also need to mark copied objects.
       copy_non_heap_cl = &copy_mark_non_heap_cl;
-      copy_metadata_cl = &copy_mark_metadata_cl;
     }
 
     // Is alive closure
@@ -5645,7 +5677,7 @@
 
     // Copying keep alive closure. Applied to referent objects that need
     // to be copied.
-    G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, copy_metadata_cl, &pss);
+    G1CopyingKeepAliveClosure keep_alive(_g1h, copy_non_heap_cl, &pss);
 
     ReferenceProcessor* rp = _g1h->ref_processor_cm();
 
@@ -5681,7 +5713,7 @@
     G1ParEvacuateFollowersClosure drain_queue(_g1h, &pss, _queues, &_terminator);
     drain_queue.do_void();
     // Allocation buffers were retired at the end of G1ParEvacuateFollowersClosure
-    assert(pss.refs()->is_empty(), "should be");
+    assert(pss.queue_is_empty(), "should be");
   }
 };
 
@@ -5748,25 +5780,21 @@
 
   pss.set_evac_failure_closure(&evac_failure_cl);
 
-  assert(pss.refs()->is_empty(), "pre-condition");
+  assert(pss.queue_is_empty(), "pre-condition");
 
   G1ParScanExtRootClosure        only_copy_non_heap_cl(this, &pss, NULL);
-  G1ParScanMetadataClosure       only_copy_metadata_cl(this, &pss, NULL);
 
   G1ParScanAndMarkExtRootClosure copy_mark_non_heap_cl(this, &pss, NULL);
-  G1ParScanAndMarkMetadataClosure copy_mark_metadata_cl(this, &pss, NULL);
 
   OopClosure*                    copy_non_heap_cl = &only_copy_non_heap_cl;
-  OopsInHeapRegionClosure*       copy_metadata_cl = &only_copy_metadata_cl;
 
   if (_g1h->g1_policy()->during_initial_mark_pause()) {
     // We also need to mark copied objects.
     copy_non_heap_cl = &copy_mark_non_heap_cl;
-    copy_metadata_cl = &copy_mark_metadata_cl;
   }
 
   // Keep alive closure.
-  G1CopyingKeepAliveClosure keep_alive(this, copy_non_heap_cl, copy_metadata_cl, &pss);
+  G1CopyingKeepAliveClosure keep_alive(this, copy_non_heap_cl, &pss);
 
   // Serial Complete GC closure
   G1STWDrainQueueClosure drain_queue(this, &pss);
@@ -5781,7 +5809,8 @@
                                               &keep_alive,
                                               &drain_queue,
                                               NULL,
-                                              _gc_timer_stw);
+                                              _gc_timer_stw,
+                                              _gc_tracer_stw->gc_id());
   } else {
     // Parallel reference processing
     assert(rp->num_q() == no_of_gc_workers, "sanity");
@@ -5792,15 +5821,14 @@
                                               &keep_alive,
                                               &drain_queue,
                                               &par_task_executor,
-                                              _gc_timer_stw);
+                                              _gc_timer_stw,
+                                              _gc_tracer_stw->gc_id());
   }
 
   _gc_tracer_stw->report_gc_reference_stats(stats);
-  // We have completed copying any necessary live referent objects
-  // (that were not copied during the actual pause) so we can
-  // retire any active alloc buffers
-  pss.retire_alloc_buffers();
-  assert(pss.refs()->is_empty(), "both queue and overflow should be empty");
+
+  // We have completed copying any necessary live referent objects.
+  assert(pss.queue_is_empty(), "both queue and overflow should be empty");
 
   double ref_proc_time = os::elapsedTime() - ref_proc_start;
   g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0);
@@ -5885,6 +5913,10 @@
 
   {
     StrongRootsScope srs(this);
+    // InitialMark needs claim bits to keep track of the marked-through CLDs.
+    if (g1_policy()->during_initial_mark_pause()) {
+      ClassLoaderDataGraph::clear_claimed_marks();
+    }
 
     if (G1CollectedHeap::use_parallel_gc_threads()) {
       // The individual threads will set their evac-failure closures.
@@ -5987,8 +6019,14 @@
                                   bool locked) {
   assert(!hr->isHumongous(), "this is only for non-humongous regions");
   assert(!hr->is_empty(), "the region should not be empty");
+  assert(_hrs.is_available(hr->hrs_index()), "region should be committed");
   assert(free_list != NULL, "pre-condition");
 
+  if (G1VerifyBitmaps) {
+    MemRegion mr(hr->bottom(), hr->end());
+    concurrent_mark()->clearRangePrevBitmap(mr);
+  }
+
   // Clear the card counts for this region.
   // Note: we only need to do this if the region is not young
   // (since we don't refine cards in young regions).
@@ -6036,7 +6074,7 @@
   assert(list != NULL, "list can't be null");
   if (!list->is_empty()) {
     MutexLockerEx x(FreeList_lock, Mutex::_no_safepoint_check_flag);
-    _free_list.add_ordered(list);
+    _hrs.insert_list_into_free_list(list);
   }
 }
 
@@ -6123,7 +6161,87 @@
 void G1CollectedHeap::verify_dirty_young_regions() {
   verify_dirty_young_list(_young_list->first_region());
 }
-#endif
+
+bool G1CollectedHeap::verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap,
+                                               HeapWord* tams, HeapWord* end) {
+  guarantee(tams <= end,
+            err_msg("tams: "PTR_FORMAT" end: "PTR_FORMAT, tams, end));
+  HeapWord* result = bitmap->getNextMarkedWordAddress(tams, end);
+  if (result < end) {
+    gclog_or_tty->cr();
+    gclog_or_tty->print_cr("## wrong marked address on %s bitmap: "PTR_FORMAT,
+                           bitmap_name, result);
+    gclog_or_tty->print_cr("## %s tams: "PTR_FORMAT" end: "PTR_FORMAT,
+                           bitmap_name, tams, end);
+    return false;
+  }
+  return true;
+}
+
+bool G1CollectedHeap::verify_bitmaps(const char* caller, HeapRegion* hr) {
+  CMBitMapRO* prev_bitmap = concurrent_mark()->prevMarkBitMap();
+  CMBitMapRO* next_bitmap = (CMBitMapRO*) concurrent_mark()->nextMarkBitMap();
+
+  HeapWord* bottom = hr->bottom();
+  HeapWord* ptams  = hr->prev_top_at_mark_start();
+  HeapWord* ntams  = hr->next_top_at_mark_start();
+  HeapWord* end    = hr->end();
+
+  bool res_p = verify_no_bits_over_tams("prev", prev_bitmap, ptams, end);
+
+  bool res_n = true;
+  // We reset mark_in_progress() before we reset _cmThread->in_progress() and in this window
+  // we do the clearing of the next bitmap concurrently. Thus, we can not verify the bitmap
+  // if we happen to be in that state.
+  if (mark_in_progress() || !_cmThread->in_progress()) {
+    res_n = verify_no_bits_over_tams("next", next_bitmap, ntams, end);
+  }
+  if (!res_p || !res_n) {
+    gclog_or_tty->print_cr("#### Bitmap verification failed for "HR_FORMAT,
+                           HR_FORMAT_PARAMS(hr));
+    gclog_or_tty->print_cr("#### Caller: %s", caller);
+    return false;
+  }
+  return true;
+}
+
+void G1CollectedHeap::check_bitmaps(const char* caller, HeapRegion* hr) {
+  if (!G1VerifyBitmaps) return;
+
+  guarantee(verify_bitmaps(caller, hr), "bitmap verification");
+}
+
+class G1VerifyBitmapClosure : public HeapRegionClosure {
+private:
+  const char* _caller;
+  G1CollectedHeap* _g1h;
+  bool _failures;
+
+public:
+  G1VerifyBitmapClosure(const char* caller, G1CollectedHeap* g1h) :
+    _caller(caller), _g1h(g1h), _failures(false) { }
+
+  bool failures() { return _failures; }
+
+  virtual bool doHeapRegion(HeapRegion* hr) {
+    if (hr->continuesHumongous()) return false;
+
+    bool result = _g1h->verify_bitmaps(_caller, hr);
+    if (!result) {
+      _failures = true;
+    }
+    return false;
+  }
+};
+
+void G1CollectedHeap::check_bitmaps(const char* caller) {
+  if (!G1VerifyBitmaps) return;
+
+  G1VerifyBitmapClosure cl(caller, this);
+  heap_region_iterate(&cl);
+  guarantee(!cl.failures(), "bitmap verification");
+}
+#endif // PRODUCT
 
 void G1CollectedHeap::cleanUpCardTable() {
   G1SATBCardTableModRefBS* ct_bs = g1_barrier_set();
@@ -6272,6 +6390,154 @@
   policy->phase_times()->record_non_young_free_cset_time_ms(non_young_time_ms);
 }
 
+class G1FreeHumongousRegionClosure : public HeapRegionClosure {
+ private:
+  FreeRegionList* _free_region_list;
+  HeapRegionSet* _proxy_set;
+  HeapRegionSetCount _humongous_regions_removed;
+  size_t _freed_bytes;
+ public:
+
+  G1FreeHumongousRegionClosure(FreeRegionList* free_region_list) :
+    _free_region_list(free_region_list), _humongous_regions_removed(), _freed_bytes(0) {
+  }
+
+  virtual bool doHeapRegion(HeapRegion* r) {
+    if (!r->startsHumongous()) {
+      return false;
+    }
+
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+
+    oop obj = (oop)r->bottom();
+    CMBitMap* next_bitmap = g1h->concurrent_mark()->nextMarkBitMap();
+
+    // The following checks whether the humongous object is live are sufficient.
+    // The main additional check (in addition to having a reference from the roots
+    // or the young gen) is whether the humongous object has a remembered set entry.
+    //
+    // A humongous object cannot be live if there is no remembered set for it
+    // because:
+    // - there can be no references from within humongous starts regions referencing
+    // the object because we never allocate other objects into them.
+    // (I.e. there are no intra-region references that may be missed by the
+    // remembered set)
+    // - as soon there is a remembered set entry to the humongous starts region
+    // (i.e. it has "escaped" to an old object) this remembered set entry will stay
+    // until the end of a concurrent mark.
+    //
+    // It is not required to check whether the object has been found dead by marking
+    // or not, in fact it would prevent reclamation within a concurrent cycle, as
+    // all objects allocated during that time are considered live.
+    // SATB marking is even more conservative than the remembered set.
+    // So if at this point in the collection there is no remembered set entry,
+    // nobody has a reference to it.
+    // At the start of collection we flush all refinement logs, and remembered sets
+    // are completely up-to-date wrt to references to the humongous object.
+    //
+    // Other implementation considerations:
+    // - never consider object arrays: while they are a valid target, they have not
+    // been observed to be used as temporary objects.
+    // - they would also pose considerable effort for cleaning up the the remembered
+    // sets.
+    // While this cleanup is not strictly necessary to be done (or done instantly),
+    // given that their occurrence is very low, this saves us this additional
+    // complexity.
+    uint region_idx = r->hrs_index();
+    if (g1h->humongous_is_live(region_idx) ||
+        g1h->humongous_region_is_always_live(region_idx)) {
+
+      if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
+        gclog_or_tty->print_cr("Live humongous %d region %d with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
+                               r->isHumongous(),
+                               region_idx,
+                               r->rem_set()->occupied(),
+                               r->rem_set()->strong_code_roots_list_length(),
+                               next_bitmap->isMarked(r->bottom()),
+                               g1h->humongous_is_live(region_idx),
+                               obj->is_objArray()
+                              );
+      }
+
+      return false;
+    }
+
+    guarantee(!obj->is_objArray(),
+              err_msg("Eagerly reclaiming object arrays is not supported, but the object "PTR_FORMAT" is.",
+                      r->bottom()));
+
+    if (G1TraceReclaimDeadHumongousObjectsAtYoungGC) {
+      gclog_or_tty->print_cr("Reclaim humongous region %d start "PTR_FORMAT" region %d length "UINT32_FORMAT" with remset "SIZE_FORMAT" code roots "SIZE_FORMAT" is marked %d live-other %d obj array %d",
+                             r->isHumongous(),
+                             r->bottom(),
+                             region_idx,
+                             r->region_num(),
+                             r->rem_set()->occupied(),
+                             r->rem_set()->strong_code_roots_list_length(),
+                             next_bitmap->isMarked(r->bottom()),
+                             g1h->humongous_is_live(region_idx),
+                             obj->is_objArray()
+                            );
+    }
+    // Need to clear mark bit of the humongous object if already set.
+    if (next_bitmap->isMarked(r->bottom())) {
+      next_bitmap->clear(r->bottom());
+    }
+    _freed_bytes += r->used();
+    r->set_containing_set(NULL);
+    _humongous_regions_removed.increment(1u, r->capacity());
+    g1h->free_humongous_region(r, _free_region_list, false);
+
+    return false;
+  }
+
+  HeapRegionSetCount& humongous_free_count() {
+    return _humongous_regions_removed;
+  }
+
+  size_t bytes_freed() const {
+    return _freed_bytes;
+  }
+
+  size_t humongous_reclaimed() const {
+    return _humongous_regions_removed.length();
+  }
+};
+
+void G1CollectedHeap::eagerly_reclaim_humongous_regions() {
+  assert_at_safepoint(true);
+
+  if (!G1ReclaimDeadHumongousObjectsAtYoungGC || !_has_humongous_reclaim_candidates) {
+    g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms(0.0, 0);
+    return;
+  }
+
+  double start_time = os::elapsedTime();
+
+  FreeRegionList local_cleanup_list("Local Humongous Cleanup List");
+
+  G1FreeHumongousRegionClosure cl(&local_cleanup_list);
+  heap_region_iterate(&cl);
+
+  HeapRegionSetCount empty_set;
+  remove_from_old_sets(empty_set, cl.humongous_free_count());
+
+  G1HRPrinter* hr_printer = _g1h->hr_printer();
+  if (hr_printer->is_active()) {
+    FreeRegionListIterator iter(&local_cleanup_list);
+    while (iter.more_available()) {
+      HeapRegion* hr = iter.get_next();
+      hr_printer->cleanup(hr);
+    }
+  }
+
+  prepend_to_freelist(&local_cleanup_list);
+  decrement_summary_bytes(cl.bytes_freed());
+
+  g1_policy()->phase_times()->record_fast_reclaim_humongous_time_ms((os::elapsedTime() - start_time) * 1000.0,
+                                                                    cl.humongous_reclaimed());
+}
+
 // This routine is similar to the above but does not record
 // any policy statistics or update free lists; we are abandoning
 // the current incremental collection set in preparation of a
@@ -6416,22 +6682,22 @@
     // this is that during a full GC string deduplication needs to know if
     // a collected region was young or old when the full GC was initiated.
   }
-  _free_list.remove_all();
+  _hrs.remove_all_free_regions();
 }
 
 class RebuildRegionSetsClosure : public HeapRegionClosure {
 private:
   bool            _free_list_only;
   HeapRegionSet*   _old_set;
-  FreeRegionList* _free_list;
+  HeapRegionSeq*   _hrs;
   size_t          _total_used;
 
 public:
   RebuildRegionSetsClosure(bool free_list_only,
-                           HeapRegionSet* old_set, FreeRegionList* free_list) :
+                           HeapRegionSet* old_set, HeapRegionSeq* hrs) :
     _free_list_only(free_list_only),
-    _old_set(old_set), _free_list(free_list), _total_used(0) {
-    assert(_free_list->is_empty(), "pre-condition");
+    _old_set(old_set), _hrs(hrs), _total_used(0) {
+    assert(_hrs->num_free_regions() == 0, "pre-condition");
     if (!free_list_only) {
       assert(_old_set->is_empty(), "pre-condition");
     }
@@ -6444,7 +6710,7 @@
 
     if (r->is_empty()) {
       // Add free regions to the free list
-      _free_list->add_as_tail(r);
+      _hrs->insert_into_free_list(r);
     } else if (!_free_list_only) {
       assert(!r->is_young(), "we should not come across young regions");
 
@@ -6472,7 +6738,7 @@
     _young_list->empty_list();
   }
 
-  RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_free_list);
+  RebuildRegionSetsClosure cl(free_list_only, &_old_set, &_hrs);
   heap_region_iterate(&cl);
 
   if (!free_list_only) {
@@ -6490,11 +6756,7 @@
 
 bool G1CollectedHeap::is_in_closed_subset(const void* p) const {
   HeapRegion* hr = heap_region_containing(p);
-  if (hr == NULL) {
-    return false;
-  } else {
-    return hr->is_in(p);
-  }
+  return hr->is_in(p);
 }
 
 // Methods for the mutator alloc region
@@ -6512,6 +6774,7 @@
     if (new_alloc_region != NULL) {
       set_region_short_lived_locked(new_alloc_region);
       _hr_printer.alloc(new_alloc_region, G1HRPrinter::Eden, young_list_full);
+      check_bitmaps("Mutator Region Allocation", new_alloc_region);
       return new_alloc_region;
     }
   }
@@ -6574,12 +6837,14 @@
       // We really only need to do this for old regions given that we
       // should never scan survivors. But it doesn't hurt to do it
       // for survivors too.
-      new_alloc_region->set_saved_mark();
+      new_alloc_region->record_top_and_timestamp();
       if (survivor) {
         new_alloc_region->set_survivor();
         _hr_printer.alloc(new_alloc_region, G1HRPrinter::Survivor);
+        check_bitmaps("Survivor Region Allocation", new_alloc_region);
       } else {
         _hr_printer.alloc(new_alloc_region, G1HRPrinter::Old);
+        check_bitmaps("Old Region Allocation", new_alloc_region);
       }
       bool during_im = g1_policy()->during_initial_mark_pause();
       new_alloc_region->note_start_of_copying(during_im);
@@ -6628,13 +6893,42 @@
   _g1h->retire_gc_alloc_region(alloc_region, allocated_bytes,
                                GCAllocForTenured);
 }
+
+HeapRegion* OldGCAllocRegion::release() {
+  HeapRegion* cur = get();
+  if (cur != NULL) {
+    // Determine how far we are from the next card boundary. If it is smaller than
+    // the minimum object size we can allocate into, expand into the next card.
+    HeapWord* top = cur->top();
+    HeapWord* aligned_top = (HeapWord*)align_ptr_up(top, G1BlockOffsetSharedArray::N_bytes);
+
+    size_t to_allocate_words = pointer_delta(aligned_top, top, HeapWordSize);
+
+    if (to_allocate_words != 0) {
+      // We are not at a card boundary. Fill up, possibly into the next, taking the
+      // end of the region and the minimum object size into account.
+      to_allocate_words = MIN2(pointer_delta(cur->end(), cur->top(), HeapWordSize),
+                               MAX2(to_allocate_words, G1CollectedHeap::min_fill_size()));
+
+      // Skip allocation if there is not enough space to allocate even the smallest
+      // possible object. In this case this region will not be retained, so the
+      // original problem cannot occur.
+      if (to_allocate_words >= G1CollectedHeap::min_fill_size()) {
+        HeapWord* dummy = attempt_allocation(to_allocate_words, true /* bot_updates */);
+        CollectedHeap::fill_with_object(dummy, to_allocate_words);
+      }
+    }
+  }
+  return G1AllocRegion::release();
+}
+
 // Heap region set verification
 
 class VerifyRegionListsClosure : public HeapRegionClosure {
 private:
   HeapRegionSet*   _old_set;
   HeapRegionSet*   _humongous_set;
-  FreeRegionList*  _free_list;
+  HeapRegionSeq*   _hrs;
 
 public:
   HeapRegionSetCount _old_count;
@@ -6643,8 +6937,8 @@
 
   VerifyRegionListsClosure(HeapRegionSet* old_set,
                            HeapRegionSet* humongous_set,
-                           FreeRegionList* free_list) :
-    _old_set(old_set), _humongous_set(humongous_set), _free_list(free_list),
+                           HeapRegionSeq* hrs) :
+    _old_set(old_set), _humongous_set(humongous_set), _hrs(hrs),
     _old_count(), _humongous_count(), _free_count(){ }
 
   bool doHeapRegion(HeapRegion* hr) {
@@ -6655,19 +6949,19 @@
     if (hr->is_young()) {
       // TODO
     } else if (hr->startsHumongous()) {
-      assert(hr->containing_set() == _humongous_set, err_msg("Heap region %u is starts humongous but not in humongous set.", hr->region_num()));
+      assert(hr->containing_set() == _humongous_set, err_msg("Heap region %u is starts humongous but not in humongous set.", hr->hrs_index()));
       _humongous_count.increment(1u, hr->capacity());
     } else if (hr->is_empty()) {
-      assert(hr->containing_set() == _free_list, err_msg("Heap region %u is empty but not on the free list.", hr->region_num()));
+      assert(_hrs->is_free(hr), err_msg("Heap region %u is empty but not on the free list.", hr->hrs_index()));
       _free_count.increment(1u, hr->capacity());
     } else {
-      assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->region_num()));
+      assert(hr->containing_set() == _old_set, err_msg("Heap region %u is old but not in the old set.", hr->hrs_index()));
       _old_count.increment(1u, hr->capacity());
     }
     return false;
   }
 
-  void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, FreeRegionList* free_list) {
+  void verify_counts(HeapRegionSet* old_set, HeapRegionSet* humongous_set, HeapRegionSeq* free_list) {
     guarantee(old_set->length() == _old_count.length(), err_msg("Old set count mismatch. Expected %u, actual %u.", old_set->length(), _old_count.length()));
     guarantee(old_set->total_capacity_bytes() == _old_count.capacity(), err_msg("Old set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
         old_set->total_capacity_bytes(), _old_count.capacity()));
@@ -6676,26 +6970,17 @@
     guarantee(humongous_set->total_capacity_bytes() == _humongous_count.capacity(), err_msg("Hum set capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
         humongous_set->total_capacity_bytes(), _humongous_count.capacity()));
 
-    guarantee(free_list->length() == _free_count.length(), err_msg("Free list count mismatch. Expected %u, actual %u.", free_list->length(), _free_count.length()));
+    guarantee(free_list->num_free_regions() == _free_count.length(), err_msg("Free list count mismatch. Expected %u, actual %u.", free_list->num_free_regions(), _free_count.length()));
     guarantee(free_list->total_capacity_bytes() == _free_count.capacity(), err_msg("Free list capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
         free_list->total_capacity_bytes(), _free_count.capacity()));
   }
 };
 
-HeapRegion* G1CollectedHeap::new_heap_region(uint hrs_index,
-                                             HeapWord* bottom) {
-  HeapWord* end = bottom + HeapRegion::GrainWords;
-  MemRegion mr(bottom, end);
-  assert(_g1_reserved.contains(mr), "invariant");
-  // This might return NULL if the allocation fails
-  return new HeapRegion(hrs_index, _bot_shared, mr);
-}
-
 void G1CollectedHeap::verify_region_sets() {
   assert_heap_locked_or_at_safepoint(true /* should_be_vm_thread */);
 
   // First, check the explicit lists.
-  _free_list.verify_list();
+  _hrs.verify();
   {
     // Given that a concurrent operation might be adding regions to
     // the secondary free list we have to take the lock before
@@ -6726,9 +7011,9 @@
   // Finally, make sure that the region accounting in the lists is
   // consistent with what we see in the heap.
 
-  VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_free_list);
+  VerifyRegionListsClosure cl(&_old_set, &_humongous_set, &_hrs);
   heap_region_iterate(&cl);
-  cl.verify_counts(&_old_set, &_humongous_set, &_free_list);
+  cl.verify_counts(&_old_set, &_humongous_set, &_hrs);
 }
 
 // Optimized nmethod scanning
@@ -6836,106 +7121,6 @@
   g1_policy()->phase_times()->record_strong_code_root_purge_time(purge_time_ms);
 }
 
-// Mark all the code roots that point into regions *not* in the
-// collection set.
-//
-// Note we do not want to use a "marking" CodeBlobToOopClosure while
-// walking the the code roots lists of regions not in the collection
-// set. Suppose we have an nmethod (M) that points to objects in two
-// separate regions - one in the collection set (R1) and one not (R2).
-// Using a "marking" CodeBlobToOopClosure here would result in "marking"
-// nmethod M when walking the code roots for R1. When we come to scan
-// the code roots for R2, we would see that M is already marked and it
-// would be skipped and the objects in R2 that are referenced from M
-// would not be evacuated.
-
-class MarkStrongCodeRootCodeBlobClosure: public CodeBlobClosure {
-
-  class MarkStrongCodeRootOopClosure: public OopClosure {
-    ConcurrentMark* _cm;
-    HeapRegion* _hr;
-    uint _worker_id;
-
-    template <class T> void do_oop_work(T* p) {
-      T heap_oop = oopDesc::load_heap_oop(p);
-      if (!oopDesc::is_null(heap_oop)) {
-        oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-        // Only mark objects in the region (which is assumed
-        // to be not in the collection set).
-        if (_hr->is_in(obj)) {
-          _cm->grayRoot(obj, (size_t) obj->size(), _worker_id);
-        }
-      }
-    }
-
-  public:
-    MarkStrongCodeRootOopClosure(ConcurrentMark* cm, HeapRegion* hr, uint worker_id) :
-      _cm(cm), _hr(hr), _worker_id(worker_id) {
-      assert(!_hr->in_collection_set(), "sanity");
-    }
-
-    void do_oop(narrowOop* p) { do_oop_work(p); }
-    void do_oop(oop* p)       { do_oop_work(p); }
-  };
-
-  MarkStrongCodeRootOopClosure _oop_cl;
-
-public:
-  MarkStrongCodeRootCodeBlobClosure(ConcurrentMark* cm, HeapRegion* hr, uint worker_id):
-    _oop_cl(cm, hr, worker_id) {}
-
-  void do_code_blob(CodeBlob* cb) {
-    nmethod* nm = (cb == NULL) ? NULL : cb->as_nmethod_or_null();
-    if (nm != NULL) {
-      nm->oops_do(&_oop_cl);
-    }
-  }
-};
-
-class MarkStrongCodeRootsHRClosure: public HeapRegionClosure {
-  G1CollectedHeap* _g1h;
-  uint _worker_id;
-
-public:
-  MarkStrongCodeRootsHRClosure(G1CollectedHeap* g1h, uint worker_id) :
-    _g1h(g1h), _worker_id(worker_id) {}
-
-  bool doHeapRegion(HeapRegion *hr) {
-    HeapRegionRemSet* hrrs = hr->rem_set();
-    if (hr->continuesHumongous()) {
-      // Code roots should never be attached to a continuation of a humongous region
-      assert(hrrs->strong_code_roots_list_length() == 0,
-             err_msg("code roots should never be attached to continuations of humongous region "HR_FORMAT
-                     " starting at "HR_FORMAT", but has "SIZE_FORMAT,
-                     HR_FORMAT_PARAMS(hr), HR_FORMAT_PARAMS(hr->humongous_start_region()),
-                     hrrs->strong_code_roots_list_length()));
-      return false;
-    }
-
-    if (hr->in_collection_set()) {
-      // Don't mark code roots into regions in the collection set here.
-      // They will be marked when we scan them.
-      return false;
-    }
-
-    MarkStrongCodeRootCodeBlobClosure cb_cl(_g1h->concurrent_mark(), hr, _worker_id);
-    hr->strong_code_roots_do(&cb_cl);
-    return false;
-  }
-};
-
-void G1CollectedHeap::mark_strong_code_roots(uint worker_id) {
-  MarkStrongCodeRootsHRClosure cl(this, worker_id);
-  if (G1CollectedHeap::use_parallel_gc_threads()) {
-    heap_region_par_iterate_chunked(&cl,
-                                    worker_id,
-                                    workers()->active_workers(),
-                                    HeapRegion::ParMarkRootClaimValue);
-  } else {
-    heap_region_iterate(&cl);
-  }
-}
-
 class RebuildStrongCodeRootClosure: public CodeBlobClosure {
   G1CollectedHeap* _g1h;
 
@@ -6949,7 +7134,7 @@
       return;
     }
 
-    if (ScavengeRootsInCode && nm->detect_scavenge_root_oops()) {
+    if (ScavengeRootsInCode) {
       _g1h->register_nmethod(nm);
     }
   }
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
index cc8b875..4d884a5 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp
@@ -28,9 +28,9 @@
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/evacuationInfo.hpp"
 #include "gc_implementation/g1/g1AllocRegion.hpp"
+#include "gc_implementation/g1/g1BiasedArray.hpp"
 #include "gc_implementation/g1/g1HRPrinter.hpp"
 #include "gc_implementation/g1/g1MonitoringSupport.hpp"
-#include "gc_implementation/g1/g1RemSet.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/g1YCTypes.hpp"
 #include "gc_implementation/g1/heapRegionSeq.hpp"
@@ -183,6 +183,13 @@
 public:
   OldGCAllocRegion()
   : G1AllocRegion("Old GC Alloc Region", true /* bot_updates */) { }
+
+  // This specialization of release() makes sure that the last card that has been
+  // allocated into has been completely filled by a dummy object.
+  // This avoids races when remembered set scanning wants to update the BOT of the
+  // last card in the retained old gc alloc region, and allocation threads
+  // allocating into that card at the same time.
+  virtual HeapRegion* release();
 };
 
 // The G1 STW is alive closure.
@@ -199,7 +206,15 @@
 
 class RefineCardTableEntryClosure;
 
+class G1RegionMappingChangedListener : public G1MappingChangedListener {
+ private:
+  void reset_from_card_cache(uint start_idx, size_t num_regions);
+ public:
+  virtual void on_commit(uint start_idx, size_t num_regions);
+};
+
 class G1CollectedHeap : public SharedHeap {
+  friend class VM_CollectForMetadataAllocation;
   friend class VM_G1CollectForAllocation;
   friend class VM_G1CollectFull;
   friend class VM_G1IncCollectionPause;
@@ -209,7 +224,7 @@
   friend class OldGCAllocRegion;
 
   // Closures used in implementation.
-  template <G1Barrier barrier, bool do_mark_object>
+  template <G1Barrier barrier, G1Mark do_mark_object>
   friend class G1ParCopyClosure;
   friend class G1IsAliveClosure;
   friend class G1EvacuateFollowersClosure;
@@ -226,6 +241,7 @@
   friend class EvacPopObjClosure;
   friend class G1ParCleanupCTTask;
 
+  friend class G1FreeHumongousRegionClosure;
   // Other related classes.
   friend class G1MarkSweep;
 
@@ -235,19 +251,9 @@
 
   static size_t _humongous_object_threshold_in_words;
 
-  // Storage for the G1 heap.
-  VirtualSpace _g1_storage;
-  MemRegion    _g1_reserved;
-
-  // The part of _g1_storage that is currently committed.
-  MemRegion _g1_committed;
-
-  // The master free list. It will satisfy all new region allocations.
-  FreeRegionList _free_list;
-
   // The secondary free list which contains regions that have been
-  // freed up during the cleanup process. This will be appended to the
-  // master free list when appropriate.
+  // freed up during the cleanup process. This will be appended to
+  // the master free list when appropriate.
   FreeRegionList _secondary_free_list;
 
   // It keeps track of the old regions.
@@ -256,6 +262,9 @@
   // It keeps track of the humongous regions.
   HeapRegionSet _humongous_set;
 
+  void clear_humongous_is_live_table();
+  void eagerly_reclaim_humongous_regions();
+
   // The number of regions we could create by expansion.
   uint _expansion_regions;
 
@@ -278,6 +287,9 @@
   // after heap shrinking (free_list_only == true).
   void rebuild_region_sets(bool free_list_only);
 
+  // Callback for region mapping changed events.
+  G1RegionMappingChangedListener _listener;
+
   // The sequence of all heap regions in the heap.
   HeapRegionSeq _hrs;
 
@@ -336,6 +348,9 @@
   // It initializes the GC alloc regions at the start of a GC.
   void init_gc_alloc_regions(EvacuationInfo& evacuation_info);
 
+  // Setup the retained old gc alloc region as the currrent old gc alloc region.
+  void use_retained_old_gc_alloc_region(EvacuationInfo& evacuation_info);
+
   // It releases the GC alloc regions at the end of a GC.
   void release_gc_alloc_regions(uint no_of_gc_workers, EvacuationInfo& evacuation_info);
 
@@ -353,26 +368,25 @@
   // than the current allocation region.
   size_t _summary_bytes_used;
 
-  // This is used for a quick test on whether a reference points into
-  // the collection set or not. Basically, we have an array, with one
-  // byte per region, and that byte denotes whether the corresponding
-  // region is in the collection set or not. The entry corresponding
-  // the bottom of the heap, i.e., region 0, is pointed to by
-  // _in_cset_fast_test_base.  The _in_cset_fast_test field has been
-  // biased so that it actually points to address 0 of the address
-  // space, to make the test as fast as possible (we can simply shift
-  // the address to address into it, instead of having to subtract the
-  // bottom of the heap from the address before shifting it; basically
-  // it works in the same way the card table works).
-  bool* _in_cset_fast_test;
+  // Records whether the region at the given index is kept live by roots or
+  // references from the young generation.
+  class HumongousIsLiveBiasedMappedArray : public G1BiasedMappedArray<bool> {
+   protected:
+    bool default_value() const { return false; }
+   public:
+    void clear() { G1BiasedMappedArray<bool>::clear(); }
+    void set_live(uint region) {
+      set_by_index(region, true);
+    }
+    bool is_live(uint region) {
+      return get_by_index(region);
+    }
+  };
 
-  // The allocated array used for the fast test on whether a reference
-  // points into the collection set or not. This field is also used to
-  // free the array.
-  bool* _in_cset_fast_test_base;
-
-  // The length of the _in_cset_fast_test_base array.
-  uint _in_cset_fast_test_length;
+  HumongousIsLiveBiasedMappedArray _humongous_is_live;
+  // Stores whether during humongous object registration we found candidate regions.
+  // If not, we can skip a few steps.
+  bool _has_humongous_reclaim_candidates;
 
   volatile unsigned _gc_time_stamp;
 
@@ -506,14 +520,6 @@
   // humongous object, set is_old to true. If not, to false.
   HeapRegion* new_region(size_t word_size, bool is_old, bool do_expand);
 
-  // Attempt to satisfy a humongous allocation request of the given
-  // size by finding a contiguous set of free regions of num_regions
-  // length and remove them from the master free list. Return the
-  // index of the first region or G1_NULL_HRS_INDEX if the search
-  // was unsuccessful.
-  uint humongous_obj_allocate_find_first(uint num_regions,
-                                         size_t word_size);
-
   // Initialize a contiguous set of free regions of length num_regions
   // and starting at index first so that they appear as a single
   // humongous region.
@@ -692,15 +698,24 @@
   virtual void gc_prologue(bool full);
   virtual void gc_epilogue(bool full);
 
+  inline void set_humongous_is_live(oop obj);
+
+  bool humongous_is_live(uint region) {
+    return _humongous_is_live.is_live(region);
+  }
+
+  // Returns whether the given region (which must be a humongous (start) region)
+  // is to be considered conservatively live regardless of any other conditions.
+  bool humongous_region_is_always_live(uint index);
+  // Register the given region to be part of the collection set.
+  inline void register_humongous_region_with_in_cset_fast_test(uint index);
+  // Register regions with humongous objects (actually on the start region) in
+  // the in_cset_fast_test table.
+  void register_humongous_regions_with_in_cset_fast_test();
   // We register a region with the fast "in collection set" test. We
   // simply set to true the array slot corresponding to this region.
   void register_region_with_in_cset_fast_test(HeapRegion* r) {
-    assert(_in_cset_fast_test_base != NULL, "sanity");
-    assert(r->in_collection_set(), "invariant");
-    uint index = r->hrs_index();
-    assert(index < _in_cset_fast_test_length, "invariant");
-    assert(!_in_cset_fast_test_base[index], "invariant");
-    _in_cset_fast_test_base[index] = true;
+    _in_cset_fast_test.set_in_cset(r->hrs_index());
   }
 
   // This is a fast test on whether a reference points into the
@@ -709,9 +724,7 @@
   inline bool in_cset_fast_test(oop obj);
 
   void clear_cset_fast_test() {
-    assert(_in_cset_fast_test_base != NULL, "sanity");
-    memset(_in_cset_fast_test_base, false,
-           (size_t) _in_cset_fast_test_length * sizeof(bool));
+    _in_cset_fast_test.clear();
   }
 
   // This is called at the start of either a concurrent cycle or a Full
@@ -840,22 +853,13 @@
   // param is for use with parallel roots processing, and should be
   // the "i" of the calling parallel worker thread's work(i) function.
   // In the sequential case this param will be ignored.
-  void g1_process_strong_roots(bool is_scavenging,
-                               ScanningOption so,
-                               OopClosure* scan_non_heap_roots,
-                               OopsInHeapRegionClosure* scan_rs,
-                               G1KlassScanClosure* scan_klasses,
-                               uint worker_i);
-
-  // Apply "blk" to all the weak roots of the system.  These include
-  // JNI weak roots, the code cache, system dictionary, symbol table,
-  // string table, and referents of reachable weak refs.
-  void g1_process_weak_roots(OopClosure* root_closure);
-
-  // Notifies all the necessary spaces that the committed space has
-  // been updated (either expanded or shrunk). It should be called
-  // after _g1_storage is updated.
-  void update_committed_space(HeapWord* old_end, HeapWord* new_end);
+  void g1_process_roots(OopClosure* scan_non_heap_roots,
+                        OopClosure* scan_non_heap_weak_roots,
+                        OopsInHeapRegionClosure* scan_rs,
+                        CLDClosure* scan_strong_clds,
+                        CLDClosure* scan_weak_clds,
+                        CodeBlobClosure* scan_strong_code,
+                        uint worker_i);
 
   // The concurrent marker (and the thread it runs in.)
   ConcurrentMark* _cm;
@@ -1043,7 +1047,7 @@
   // of G1CollectedHeap::_gc_time_stamp.
   unsigned int* _worker_cset_start_region_time_stamp;
 
-  enum G1H_process_strong_roots_tasks {
+  enum G1H_process_roots_tasks {
     G1H_PS_filter_satb_buffers,
     G1H_PS_refProcessor_oops_do,
     // Leave this one last.
@@ -1124,20 +1128,11 @@
     return _gc_time_stamp;
   }
 
-  void reset_gc_time_stamp() {
-    _gc_time_stamp = 0;
-    OrderAccess::fence();
-    // Clear the cached CSet starting regions and time stamps.
-    // Their validity is dependent on the GC timestamp.
-    clear_cset_start_regions();
-  }
+  inline void reset_gc_time_stamp();
 
   void check_gc_time_stamps() PRODUCT_RETURN;
 
-  void increment_gc_time_stamp() {
-    ++_gc_time_stamp;
-    OrderAccess::fence();
-  }
+  inline void increment_gc_time_stamp();
 
   // Reset the given region's GC timestamp. If it's starts humongous,
   // also reset the GC timestamp of its corresponding
@@ -1175,43 +1170,51 @@
   // end fields defining the extent of the contiguous allocation region.)
   // But G1CollectedHeap doesn't yet support this.
 
-  // Return an estimate of the maximum allocation that could be performed
-  // without triggering any collection or expansion activity.  In a
-  // generational collector, for example, this is probably the largest
-  // allocation that could be supported (without expansion) in the youngest
-  // generation.  It is "unsafe" because no locks are taken; the result
-  // should be treated as an approximation, not a guarantee, for use in
-  // heuristic resizing decisions.
-  virtual size_t unsafe_max_alloc();
-
   virtual bool is_maximal_no_gc() const {
-    return _g1_storage.uncommitted_size() == 0;
+    return _hrs.available() == 0;
   }
 
-  // The total number of regions in the heap.
-  uint n_regions() { return _hrs.length(); }
+  // The current number of regions in the heap.
+  uint num_regions() const { return _hrs.length(); }
 
   // The max number of regions in the heap.
-  uint max_regions() { return _hrs.max_length(); }
+  uint max_regions() const { return _hrs.max_length(); }
 
   // The number of regions that are completely free.
-  uint free_regions() { return _free_list.length(); }
+  uint num_free_regions() const { return _hrs.num_free_regions(); }
 
   // The number of regions that are not completely free.
-  uint used_regions() { return n_regions() - free_regions(); }
-
-  // The number of regions available for "regular" expansion.
-  uint expansion_regions() { return _expansion_regions; }
-
-  // Factory method for HeapRegion instances. It will return NULL if
-  // the allocation fails.
-  HeapRegion* new_heap_region(uint hrs_index, HeapWord* bottom);
+  uint num_used_regions() const { return num_regions() - num_free_regions(); }
 
   void verify_not_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
   void verify_dirty_region(HeapRegion* hr) PRODUCT_RETURN;
   void verify_dirty_young_list(HeapRegion* head) PRODUCT_RETURN;
   void verify_dirty_young_regions() PRODUCT_RETURN;
 
+#ifndef PRODUCT
+  // Make sure that the given bitmap has no marked objects in the
+  // range [from,limit). If it does, print an error message and return
+  // false. Otherwise, just return true. bitmap_name should be "prev"
+  // or "next".
+  bool verify_no_bits_over_tams(const char* bitmap_name, CMBitMapRO* bitmap,
+                                HeapWord* from, HeapWord* limit);
+
+  // Verify that the prev / next bitmap range [tams,end) for the given
+  // region has no marks. Return true if all is well, false if errors
+  // are detected.
+  bool verify_bitmaps(const char* caller, HeapRegion* hr);
+#endif // PRODUCT
+
+  // If G1VerifyBitmaps is set, verify that the marking bitmaps for
+  // the given region do not have any spurious marks. If errors are
+  // detected, print appropriate error messages and crash.
+  void check_bitmaps(const char* caller, HeapRegion* hr) PRODUCT_RETURN;
+
+  // If G1VerifyBitmaps is set, verify that the marking bitmaps do not
+  // have any spurious marks. If errors are detected, print
+  // appropriate error messages and crash.
+  void check_bitmaps(const char* caller) PRODUCT_RETURN;
+
   // verify_region_sets() performs verification over the region
   // lists. It will be compiled in the product code to be used when
   // necessary (i.e., during heap verification).
@@ -1230,7 +1233,7 @@
 
 #ifdef ASSERT
   bool is_on_master_free_list(HeapRegion* hr) {
-    return hr->containing_set() == &_free_list;
+    return _hrs.is_free(hr);
   }
 #endif // ASSERT
 
@@ -1242,7 +1245,7 @@
   }
 
   void append_secondary_free_list() {
-    _free_list.add_ordered(&_secondary_free_list);
+    _hrs.insert_list_into_free_list(&_secondary_free_list);
   }
 
   void append_secondary_free_list_if_not_empty_with_lock() {
@@ -1288,33 +1291,84 @@
 
   // Returns "TRUE" iff "p" points into the committed areas of the heap.
   virtual bool is_in(const void* p) const;
+#ifdef ASSERT
+  // Returns whether p is in one of the available areas of the heap. Slow but
+  // extensive version.
+  bool is_in_exact(const void* p) const;
+#endif
 
   // Return "TRUE" iff the given object address is within the collection
-  // set.
+  // set. Slow implementation.
   inline bool obj_in_cs(oop obj);
 
+  inline bool is_in_cset(oop obj);
+
+  inline bool is_in_cset_or_humongous(const oop obj);
+
+  enum in_cset_state_t {
+   InNeither,           // neither in collection set nor humongous
+   InCSet,              // region is in collection set only
+   IsHumongous          // region is a humongous start region
+  };
+ private:
+  // Instances of this class are used for quick tests on whether a reference points
+  // into the collection set or is a humongous object (points into a humongous
+  // object).
+  // Each of the array's elements denotes whether the corresponding region is in
+  // the collection set or a humongous region.
+  // We use this to quickly reclaim humongous objects: by making a humongous region
+  // succeed this test, we sort-of add it to the collection set. During the reference
+  // iteration closures, when we see a humongous region, we simply mark it as
+  // referenced, i.e. live.
+  class G1FastCSetBiasedMappedArray : public G1BiasedMappedArray<char> {
+   protected:
+    char default_value() const { return G1CollectedHeap::InNeither; }
+   public:
+    void set_humongous(uintptr_t index) {
+      assert(get_by_index(index) != InCSet, "Should not overwrite InCSet values");
+      set_by_index(index, G1CollectedHeap::IsHumongous);
+    }
+
+    void clear_humongous(uintptr_t index) {
+      set_by_index(index, G1CollectedHeap::InNeither);
+    }
+
+    void set_in_cset(uintptr_t index) {
+      assert(get_by_index(index) != G1CollectedHeap::IsHumongous, "Should not overwrite IsHumongous value");
+      set_by_index(index, G1CollectedHeap::InCSet);
+    }
+
+    bool is_in_cset_or_humongous(HeapWord* addr) const { return get_by_address(addr) != G1CollectedHeap::InNeither; }
+    bool is_in_cset(HeapWord* addr) const { return get_by_address(addr) == G1CollectedHeap::InCSet; }
+    G1CollectedHeap::in_cset_state_t at(HeapWord* addr) const { return (G1CollectedHeap::in_cset_state_t)get_by_address(addr); }
+    void clear() { G1BiasedMappedArray<char>::clear(); }
+  };
+
+  // This array is used for a quick test on whether a reference points into
+  // the collection set or not. Each of the array's elements denotes whether the
+  // corresponding region is in the collection set or not.
+  G1FastCSetBiasedMappedArray _in_cset_fast_test;
+
+ public:
+
+  inline in_cset_state_t in_cset_state(const oop obj);
+
   // Return "TRUE" iff the given object address is in the reserved
   // region of g1.
   bool is_in_g1_reserved(const void* p) const {
-    return _g1_reserved.contains(p);
+    return _hrs.reserved().contains(p);
   }
 
   // Returns a MemRegion that corresponds to the space that has been
   // reserved for the heap
-  MemRegion g1_reserved() {
-    return _g1_reserved;
-  }
-
-  // Returns a MemRegion that corresponds to the space that has been
-  // committed in the heap
-  MemRegion g1_committed() {
-    return _g1_committed;
+  MemRegion g1_reserved() const {
+    return _hrs.reserved();
   }
 
   virtual bool is_in_closed_subset(const void* p) const;
 
-  G1SATBCardTableModRefBS* g1_barrier_set() {
-    return (G1SATBCardTableModRefBS*) barrier_set();
+  G1SATBCardTableLoggingModRefBS* g1_barrier_set() {
+    return (G1SATBCardTableLoggingModRefBS*) barrier_set();
   }
 
   // This resets the card table to all zeros.  It is used after
@@ -1327,9 +1381,6 @@
   // "cl.do_oop" on each.
   virtual void oop_iterate(ExtendedOopClosure* cl);
 
-  // Same as above, restricted to a memory region.
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
-
   // Iterate over all objects, calling "cl.do_object" on each.
   virtual void object_iterate(ObjectClosure* cl);
 
@@ -1347,6 +1398,12 @@
   // Return the region with the given index. It assumes the index is valid.
   inline HeapRegion* region_at(uint index) const;
 
+  // Calculate the region index of the given address. Given address must be
+  // within the heap.
+  inline uint addr_to_region(HeapWord* addr) const;
+
+  inline HeapWord* bottom_addr_for_region(uint index) const;
+
   // Divide the heap region sequence into "chunks" of some size (the number
   // of regions divided by the number of parallel threads times some
   // overpartition factor, currently 4).  Assumes that this will be called
@@ -1360,10 +1417,10 @@
   // setting the claim value of the second and subsequent regions of the
   // chunk.)  For now requires that "doHeapRegion" always returns "false",
   // i.e., that a closure never attempt to abort a traversal.
-  void heap_region_par_iterate_chunked(HeapRegionClosure* blk,
-                                       uint worker,
-                                       uint no_of_par_workers,
-                                       jint claim_value);
+  void heap_region_par_iterate_chunked(HeapRegionClosure* cl,
+                                       uint worker_id,
+                                       uint num_workers,
+                                       jint claim_value) const;
 
   // It resets all the region claim values to the default.
   void reset_heap_region_claim_values();
@@ -1388,35 +1445,27 @@
   // starting region for iterating over the current collection set.
   HeapRegion* start_cset_region_for_worker(uint worker_i);
 
-  // This is a convenience method that is used by the
-  // HeapRegionIterator classes to calculate the starting region for
-  // each worker so that they do not all start from the same region.
-  HeapRegion* start_region_for_worker(uint worker_i, uint no_of_par_workers);
-
   // Iterate over the regions (if any) in the current collection set.
   void collection_set_iterate(HeapRegionClosure* blk);
 
   // As above but starting from region r
   void collection_set_iterate_from(HeapRegion* r, HeapRegionClosure *blk);
 
-  // Returns the first (lowest address) compactible space in the heap.
-  virtual CompactibleSpace* first_compactible_space();
+  HeapRegion* next_compaction_region(const HeapRegion* from) const;
 
   // A CollectedHeap will contain some number of spaces.  This finds the
   // space containing a given address, or else returns NULL.
   virtual Space* space_containing(const void* addr) const;
 
-  // A G1CollectedHeap will contain some number of heap regions.  This
-  // finds the region containing a given address, or else returns NULL.
-  template <class T>
-  inline HeapRegion* heap_region_containing(const T addr) const;
-
-  // Like the above, but requires "addr" to be in the heap (to avoid a
-  // null-check), and unlike the above, may return an continuing humongous
-  // region.
+  // Returns the HeapRegion that contains addr. addr must not be NULL.
   template <class T>
   inline HeapRegion* heap_region_containing_raw(const T addr) const;
 
+  // Returns the HeapRegion that contains addr. addr must not be NULL.
+  // If addr is within a humongous continues region, it returns its humongous start region.
+  template <class T>
+  inline HeapRegion* heap_region_containing(const T addr) const;
+
   // A CollectedHeap is divided into a dense sequence of "blocks"; that is,
   // each address in the (reserved) heap is a member of exactly
   // one block.  The defining characteristic of a block is that it is
@@ -1558,7 +1607,6 @@
   // the region to which the object belongs. An object is dead
   // iff a) it was not allocated since the last mark and b) it
   // is not marked.
-
   bool is_obj_dead(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_prev_marking(obj) &&
@@ -1568,7 +1616,6 @@
   // This function returns true when an object has been
   // around since the previous marking and hasn't yet
   // been marked during this marking.
-
   bool is_obj_ill(const oop obj, const HeapRegion* hr) const {
     return
       !hr->obj_allocated_since_next_marking(obj) &&
@@ -1623,10 +1670,6 @@
   // Free up superfluous code root memory.
   void purge_code_root_memory();
 
-  // During an initial mark pause, mark all the code roots that
-  // point into regions *not* in the collection set.
-  void mark_strong_code_roots(uint worker_id);
-
   // Rebuild the stong code root lists for each region
   // after a full GC
   void rebuild_strong_code_roots();
@@ -1635,6 +1678,9 @@
   // in symbol table, possibly in parallel.
   void unlink_string_and_symbol_table(BoolObjectClosure* is_alive, bool unlink_strings = true, bool unlink_symbols = true);
 
+  // Parallel phase of unloading/cleaning after G1 concurrent mark.
+  void parallel_cleaning(BoolObjectClosure* is_alive, bool process_strings, bool process_symbols, bool class_unloading_occurred);
+
   // Redirty logged cards in the refinement queue.
   void redirty_logged_cards();
   // Verification
@@ -1712,268 +1758,22 @@
 
 public:
   G1ParGCAllocBuffer(size_t gclab_word_size);
+  virtual ~G1ParGCAllocBuffer() {
+    guarantee(_retired, "Allocation buffer has not been retired");
+  }
 
-  void set_buf(HeapWord* buf) {
+  virtual void set_buf(HeapWord* buf) {
     ParGCAllocBuffer::set_buf(buf);
     _retired = false;
   }
 
-  void retire(bool end_of_gc, bool retain) {
-    if (_retired)
+  virtual void retire(bool end_of_gc, bool retain) {
+    if (_retired) {
       return;
+    }
     ParGCAllocBuffer::retire(end_of_gc, retain);
     _retired = true;
   }
 };
 
-class G1ParScanThreadState : public StackObj {
-protected:
-  G1CollectedHeap* _g1h;
-  RefToScanQueue*  _refs;
-  DirtyCardQueue   _dcq;
-  G1SATBCardTableModRefBS* _ct_bs;
-  G1RemSet* _g1_rem;
-
-  G1ParGCAllocBuffer  _surviving_alloc_buffer;
-  G1ParGCAllocBuffer  _tenured_alloc_buffer;
-  G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
-  ageTable            _age_table;
-
-  G1ParScanClosure    _scanner;
-
-  size_t           _alloc_buffer_waste;
-  size_t           _undo_waste;
-
-  OopsInHeapRegionClosure*      _evac_failure_cl;
-
-  int  _hash_seed;
-  uint _queue_num;
-
-  size_t _term_attempts;
-
-  double _start;
-  double _start_strong_roots;
-  double _strong_roots_time;
-  double _start_term;
-  double _term_time;
-
-  // Map from young-age-index (0 == not young, 1 is youngest) to
-  // surviving words. base is what we get back from the malloc call
-  size_t* _surviving_young_words_base;
-  // this points into the array, as we use the first few entries for padding
-  size_t* _surviving_young_words;
-
-#define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
-
-  void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
-
-  void   add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
-
-  DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
-  G1SATBCardTableModRefBS* ctbs()                { return _ct_bs; }
-
-  template <class T> inline void immediate_rs_update(HeapRegion* from, T* p, int tid);
-
-  template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) {
-    // If the new value of the field points to the same region or
-    // is the to-space, we don't need to include it in the Rset updates.
-    if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
-      size_t card_index = ctbs()->index_for(p);
-      // If the card hasn't been added to the buffer, do it.
-      if (ctbs()->mark_card_deferred(card_index)) {
-        dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
-      }
-    }
-  }
-
-public:
-  G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
-
-  ~G1ParScanThreadState() {
-    FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC);
-  }
-
-  RefToScanQueue*   refs()            { return _refs;             }
-  ageTable*         age_table()       { return &_age_table;       }
-
-  G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
-    return _alloc_buffers[purpose];
-  }
-
-  size_t alloc_buffer_waste() const              { return _alloc_buffer_waste; }
-  size_t undo_waste() const                      { return _undo_waste; }
-
-#ifdef ASSERT
-  bool verify_ref(narrowOop* ref) const;
-  bool verify_ref(oop* ref) const;
-  bool verify_task(StarTask ref) const;
-#endif // ASSERT
-
-  template <class T> void push_on_queue(T* ref) {
-    assert(verify_ref(ref), "sanity");
-    refs()->push(ref);
-  }
-
-  template <class T> inline void update_rs(HeapRegion* from, T* p, int tid);
-
-  HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
-    HeapWord* obj = NULL;
-    size_t gclab_word_size = _g1h->desired_plab_sz(purpose);
-    if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
-      G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
-      add_to_alloc_buffer_waste(alloc_buf->words_remaining());
-      alloc_buf->retire(false /* end_of_gc */, false /* retain */);
-
-      HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size);
-      if (buf == NULL) return NULL; // Let caller handle allocation failure.
-      // Otherwise.
-      alloc_buf->set_word_size(gclab_word_size);
-      alloc_buf->set_buf(buf);
-
-      obj = alloc_buf->allocate(word_sz);
-      assert(obj != NULL, "buffer was definitely big enough...");
-    } else {
-      obj = _g1h->par_allocate_during_gc(purpose, word_sz);
-    }
-    return obj;
-  }
-
-  HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz) {
-    HeapWord* obj = alloc_buffer(purpose)->allocate(word_sz);
-    if (obj != NULL) return obj;
-    return allocate_slow(purpose, word_sz);
-  }
-
-  void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) {
-    if (alloc_buffer(purpose)->contains(obj)) {
-      assert(alloc_buffer(purpose)->contains(obj + word_sz - 1),
-             "should contain whole object");
-      alloc_buffer(purpose)->undo_allocation(obj, word_sz);
-    } else {
-      CollectedHeap::fill_with_object(obj, word_sz);
-      add_to_undo_waste(word_sz);
-    }
-  }
-
-  void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
-    _evac_failure_cl = evac_failure_cl;
-  }
-  OopsInHeapRegionClosure* evac_failure_closure() {
-    return _evac_failure_cl;
-  }
-
-  int* hash_seed() { return &_hash_seed; }
-  uint queue_num() { return _queue_num; }
-
-  size_t term_attempts() const  { return _term_attempts; }
-  void note_term_attempt() { _term_attempts++; }
-
-  void start_strong_roots() {
-    _start_strong_roots = os::elapsedTime();
-  }
-  void end_strong_roots() {
-    _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
-  }
-  double strong_roots_time() const { return _strong_roots_time; }
-
-  void start_term_time() {
-    note_term_attempt();
-    _start_term = os::elapsedTime();
-  }
-  void end_term_time() {
-    _term_time += (os::elapsedTime() - _start_term);
-  }
-  double term_time() const { return _term_time; }
-
-  double elapsed_time() const {
-    return os::elapsedTime() - _start;
-  }
-
-  static void
-    print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
-  void
-    print_termination_stats(int i, outputStream* const st = gclog_or_tty) const;
-
-  size_t* surviving_young_words() {
-    // We add on to hide entry 0 which accumulates surviving words for
-    // age -1 regions (i.e. non-young ones)
-    return _surviving_young_words;
-  }
-
-  void retire_alloc_buffers() {
-    for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
-      size_t waste = _alloc_buffers[ap]->words_remaining();
-      add_to_alloc_buffer_waste(waste);
-      _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap),
-                                                 true /* end_of_gc */,
-                                                 false /* retain */);
-    }
-  }
-private:
-  #define G1_PARTIAL_ARRAY_MASK 0x2
-
-  inline bool has_partial_array_mask(oop* ref) const {
-    return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
-  }
-
-  // We never encode partial array oops as narrowOop*, so return false immediately.
-  // This allows the compiler to create optimized code when popping references from
-  // the work queue.
-  inline bool has_partial_array_mask(narrowOop* ref) const {
-    assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*");
-    return false;
-  }
-
-  // Only implement set_partial_array_mask() for regular oops, not for narrowOops.
-  // We always encode partial arrays as regular oop, to allow the
-  // specialization for has_partial_array_mask() for narrowOops above.
-  // This means that unintentional use of this method with narrowOops are caught
-  // by the compiler.
-  inline oop* set_partial_array_mask(oop obj) const {
-    assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!");
-    return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK);
-  }
-
-  inline oop clear_partial_array_mask(oop* ref) const {
-    return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
-  }
-
-  inline void do_oop_partial_array(oop* p);
-
-  // This method is applied to the fields of the objects that have just been copied.
-  template <class T> void do_oop_evac(T* p, HeapRegion* from) {
-    assert(!oopDesc::is_null(oopDesc::load_decode_heap_oop(p)),
-           "Reference should not be NULL here as such are never pushed to the task queue.");
-    oop obj = oopDesc::load_decode_heap_oop_not_null(p);
-
-    // Although we never intentionally push references outside of the collection
-    // set, due to (benign) races in the claim mechanism during RSet scanning more
-    // than one thread might claim the same card. So the same card may be
-    // processed multiple times. So redo this check.
-    if (_g1h->in_cset_fast_test(obj)) {
-      oop forwardee;
-      if (obj->is_forwarded()) {
-        forwardee = obj->forwardee();
-      } else {
-        forwardee = copy_to_survivor_space(obj);
-      }
-      assert(forwardee != NULL, "forwardee should not be NULL");
-      oopDesc::encode_store_heap_oop(p, forwardee);
-    }
-
-    assert(obj != NULL, "Must be");
-    update_rs(from, p, queue_num());
-  }
-public:
-
-  oop copy_to_survivor_space(oop const obj);
-
-  template <class T> inline void deal_with_reference(T* ref_to_scan);
-
-  inline void deal_with_reference(StarTask ref);
-
-public:
-  void trim_queue();
-};
-
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1COLLECTEDHEAP_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp
index d731e9b..f0efb2e 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.inline.hpp
@@ -29,10 +29,10 @@
 #include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/g1AllocRegion.inline.hpp"
 #include "gc_implementation/g1/g1CollectorPolicy.hpp"
-#include "gc_implementation/g1/g1RemSet.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/taskqueue.hpp"
 
 // Inline functions for G1CollectedHeap
@@ -40,23 +40,46 @@
 // Return the region with the given index. It assumes the index is valid.
 inline HeapRegion* G1CollectedHeap::region_at(uint index) const { return _hrs.at(index); }
 
+inline uint G1CollectedHeap::addr_to_region(HeapWord* addr) const {
+  assert(is_in_reserved(addr),
+         err_msg("Cannot calculate region index for address "PTR_FORMAT" that is outside of the heap ["PTR_FORMAT", "PTR_FORMAT")",
+                 p2i(addr), p2i(_reserved.start()), p2i(_reserved.end())));
+  return (uint)(pointer_delta(addr, _reserved.start(), sizeof(uint8_t)) >> HeapRegion::LogOfHRGrainBytes);
+}
+
+inline HeapWord* G1CollectedHeap::bottom_addr_for_region(uint index) const {
+  return _hrs.reserved().start() + index * HeapRegion::GrainWords;
+}
+
 template <class T>
-inline HeapRegion*
-G1CollectedHeap::heap_region_containing(const T addr) const {
-  HeapRegion* hr = _hrs.addr_to_region((HeapWord*) addr);
-  // hr can be null if addr in perm_gen
-  if (hr != NULL && hr->continuesHumongous()) {
-    hr = hr->humongous_start_region();
+inline HeapRegion* G1CollectedHeap::heap_region_containing_raw(const T addr) const {
+  assert(addr != NULL, "invariant");
+  assert(is_in_g1_reserved((const void*) addr),
+      err_msg("Address "PTR_FORMAT" is outside of the heap ranging from ["PTR_FORMAT" to "PTR_FORMAT")",
+          p2i((void*)addr), p2i(g1_reserved().start()), p2i(g1_reserved().end())));
+  return _hrs.addr_to_region((HeapWord*) addr);
+}
+
+template <class T>
+inline HeapRegion* G1CollectedHeap::heap_region_containing(const T addr) const {
+  HeapRegion* hr = heap_region_containing_raw(addr);
+  if (hr->continuesHumongous()) {
+    return hr->humongous_start_region();
   }
   return hr;
 }
 
-template <class T>
-inline HeapRegion*
-G1CollectedHeap::heap_region_containing_raw(const T addr) const {
-  assert(_g1_reserved.contains((const void*) addr), "invariant");
-  HeapRegion* res = _hrs.addr_to_region_unsafe((HeapWord*) addr);
-  return res;
+inline void G1CollectedHeap::reset_gc_time_stamp() {
+  _gc_time_stamp = 0;
+  OrderAccess::fence();
+  // Clear the cached CSet starting regions and time stamps.
+  // Their validity is dependent on the GC timestamp.
+  clear_cset_start_regions();
+}
+
+inline void G1CollectedHeap::increment_gc_time_stamp() {
+  ++_gc_time_stamp;
+  OrderAccess::fence();
 }
 
 inline void G1CollectedHeap::old_set_remove(HeapRegion* hr) {
@@ -68,10 +91,9 @@
   return r != NULL && r->in_collection_set();
 }
 
-inline HeapWord*
-G1CollectedHeap::attempt_allocation(size_t word_size,
-                                    unsigned int* gc_count_before_ret,
-                                    int* gclocker_retry_count_ret) {
+inline HeapWord* G1CollectedHeap::attempt_allocation(size_t word_size,
+                                                     unsigned int* gc_count_before_ret,
+                                                     int* gclocker_retry_count_ret) {
   assert_heap_not_locked_and_not_at_safepoint();
   assert(!isHumongous(word_size), "attempt_allocation() should not "
          "be called for humongous allocation requests");
@@ -134,8 +156,7 @@
   // have to keep calling heap_region_containing_raw() in the
   // asserts below.
   DEBUG_ONLY(HeapRegion* containing_hr = heap_region_containing_raw(start);)
-  assert(containing_hr != NULL && start != NULL && word_size > 0,
-         "pre-condition");
+  assert(word_size > 0, "pre-condition");
   assert(containing_hr->is_in(start), "it should contain start");
   assert(containing_hr->is_young(), "it should be young");
   assert(!containing_hr->isHumongous(), "it should not be humongous");
@@ -159,17 +180,11 @@
   return _cm->nextMarkBitMap()->isMarked((HeapWord *)obj);
 }
 
-
 // This is a fast test on whether a reference points into the
 // collection set or not. Assume that the reference
 // points into the heap.
-inline bool G1CollectedHeap::in_cset_fast_test(oop obj) {
-  assert(_in_cset_fast_test != NULL, "sanity");
-  assert(_g1_committed.contains((HeapWord*) obj), err_msg("Given reference outside of heap, is "PTR_FORMAT, p2i((HeapWord*)obj)));
-  // no need to subtract the bottom of the heap from obj,
-  // _in_cset_fast_test is biased
-  uintx index = cast_from_oop<uintx>(obj) >> HeapRegion::LogOfHRGrainBytes;
-  bool ret = _in_cset_fast_test[index];
+inline bool G1CollectedHeap::is_in_cset(oop obj) {
+  bool ret = _in_cset_fast_test.is_in_cset((HeapWord*)obj);
   // let's make sure the result is consistent with what the slower
   // test returns
   assert( ret || !obj_in_cs(obj), "sanity");
@@ -177,6 +192,18 @@
   return ret;
 }
 
+bool G1CollectedHeap::is_in_cset_or_humongous(const oop obj) {
+  return _in_cset_fast_test.is_in_cset_or_humongous((HeapWord*)obj);
+}
+
+G1CollectedHeap::in_cset_state_t G1CollectedHeap::in_cset_state(const oop obj) {
+  return _in_cset_fast_test.at((HeapWord*)obj);
+}
+
+void G1CollectedHeap::register_humongous_region_with_in_cset_fast_test(uint index) {
+  _in_cset_fast_test.set_humongous(index);
+}
+
 #ifndef PRODUCT
 // Support for G1EvacuationFailureALot
 
@@ -226,8 +253,7 @@
   }
 }
 
-inline bool
-G1CollectedHeap::evacuation_should_fail() {
+inline bool G1CollectedHeap::evacuation_should_fail() {
   if (!G1EvacuationFailureALot || !_evacuation_failure_alot_for_current_gc) {
     return false;
   }
@@ -251,8 +277,10 @@
 #endif  // #ifndef PRODUCT
 
 inline bool G1CollectedHeap::is_in_young(const oop obj) {
-  HeapRegion* hr = heap_region_containing(obj);
-  return hr != NULL && hr->is_young();
+  if (obj == NULL) {
+    return false;
+  }
+  return heap_region_containing(obj)->is_young();
 }
 
 // We don't need barriers for initializing stores to objects
@@ -265,105 +293,34 @@
 }
 
 inline bool G1CollectedHeap::is_obj_dead(const oop obj) const {
-  const HeapRegion* hr = heap_region_containing(obj);
-  if (hr == NULL) {
-    if (obj == NULL) return false;
-    else return true;
+  if (obj == NULL) {
+    return false;
   }
-  else return is_obj_dead(obj, hr);
+  return is_obj_dead(obj, heap_region_containing(obj));
 }
 
 inline bool G1CollectedHeap::is_obj_ill(const oop obj) const {
-  const HeapRegion* hr = heap_region_containing(obj);
-  if (hr == NULL) {
-    if (obj == NULL) return false;
-    else return true;
+  if (obj == NULL) {
+    return false;
   }
-  else return is_obj_ill(obj, hr);
+  return is_obj_ill(obj, heap_region_containing(obj));
 }
 
-template <class T> inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) {
-  if (!from->is_survivor()) {
-    _g1_rem->par_write_ref(from, p, tid);
-  }
-}
-
-template <class T> void G1ParScanThreadState::update_rs(HeapRegion* from, T* p, int tid) {
-  if (G1DeferredRSUpdate) {
-    deferred_rs_update(from, p, tid);
-  } else {
-    immediate_rs_update(from, p, tid);
-  }
-}
-
-
-inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
-  assert(has_partial_array_mask(p), "invariant");
-  oop from_obj = clear_partial_array_mask(p);
-
-  assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap.");
-  assert(from_obj->is_objArray(), "must be obj array");
-  objArrayOop from_obj_array = objArrayOop(from_obj);
-  // The from-space object contains the real length.
-  int length                 = from_obj_array->length();
-
-  assert(from_obj->is_forwarded(), "must be forwarded");
-  oop to_obj                 = from_obj->forwardee();
-  assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
-  objArrayOop to_obj_array   = objArrayOop(to_obj);
-  // We keep track of the next start index in the length field of the
-  // to-space object.
-  int next_index             = to_obj_array->length();
-  assert(0 <= next_index && next_index < length,
-         err_msg("invariant, next index: %d, length: %d", next_index, length));
-
-  int start                  = next_index;
-  int end                    = length;
-  int remainder              = end - start;
-  // We'll try not to push a range that's smaller than ParGCArrayScanChunk.
-  if (remainder > 2 * ParGCArrayScanChunk) {
-    end = start + ParGCArrayScanChunk;
-    to_obj_array->set_length(end);
-    // Push the remainder before we process the range in case another
-    // worker has run out of things to do and can steal it.
-    oop* from_obj_p = set_partial_array_mask(from_obj);
-    push_on_queue(from_obj_p);
-  } else {
-    assert(length == end, "sanity");
-    // We'll process the final range for this object. Restore the length
-    // so that the heap remains parsable in case of evacuation failure.
-    to_obj_array->set_length(end);
-  }
-  _scanner.set_region(_g1h->heap_region_containing_raw(to_obj));
-  // Process indexes [start,end). It will also process the header
-  // along with the first chunk (i.e., the chunk with start == 0).
-  // Note that at this point the length field of to_obj_array is not
-  // correct given that we are using it to keep track of the next
-  // start index. oop_iterate_range() (thankfully!) ignores the length
-  // field and only relies on the start / end parameters.  It does
-  // however return the size of the object which will be incorrect. So
-  // we have to ignore it even if we wanted to use it.
-  to_obj_array->oop_iterate_range(&_scanner, start, end);
-}
-
-template <class T> inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) {
-  if (!has_partial_array_mask(ref_to_scan)) {
-    // Note: we can use "raw" versions of "region_containing" because
-    // "obj_to_scan" is definitely in the heap, and is not in a
-    // humongous region.
-    HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
-    do_oop_evac(ref_to_scan, r);
-  } else {
-    do_oop_partial_array((oop*)ref_to_scan);
-  }
-}
-
-inline void G1ParScanThreadState::deal_with_reference(StarTask ref) {
-  assert(verify_task(ref), "sanity");
-  if (ref.is_narrow()) {
-    deal_with_reference((narrowOop*)ref);
-  } else {
-    deal_with_reference((oop*)ref);
+inline void G1CollectedHeap::set_humongous_is_live(oop obj) {
+  uint region = addr_to_region((HeapWord*)obj);
+  // We not only set the "live" flag in the humongous_is_live table, but also
+  // reset the entry in the _in_cset_fast_test table so that subsequent references
+  // to the same humongous object do not go into the slow path again.
+  // This is racy, as multiple threads may at the same time enter here, but this
+  // is benign.
+  // During collection we only ever set the "live" flag, and only ever clear the
+  // entry in the in_cset_fast_table.
+  // We only ever evaluate the contents of these tables (in the VM thread) after
+  // having synchronized the worker threads with the VM thread, or in the same
+  // thread (i.e. within the VM thread).
+  if (!_humongous_is_live.is_live(region)) {
+    _humongous_is_live.set_live(region);
+    _in_cset_fast_test.clear_humongous(region);
   }
 }
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
index 02c91e9..bd3bbe9 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp
@@ -455,7 +455,7 @@
   } else {
     _young_list_fixed_length = _young_gen_sizer->min_desired_young_length();
   }
-  _free_regions_at_end_of_collection = _g1->free_regions();
+  _free_regions_at_end_of_collection = _g1->num_free_regions();
   update_young_list_target_length();
 
   // We may immediately start allocating regions and placing them on the
@@ -828,7 +828,7 @@
 
   record_survivor_regions(0, NULL, NULL);
 
-  _free_regions_at_end_of_collection = _g1->free_regions();
+  _free_regions_at_end_of_collection = _g1->num_free_regions();
   // Reset survivors SurvRateGroup.
   _survivor_surv_rate_group->reset();
   update_young_list_target_length();
@@ -1046,7 +1046,7 @@
 
   bool new_in_marking_window = _in_marking_window;
   bool new_in_marking_window_im = false;
-  if (during_initial_mark_pause()) {
+  if (last_pause_included_initial_mark) {
     new_in_marking_window = true;
     new_in_marking_window_im = true;
   }
@@ -1180,7 +1180,7 @@
 
   _in_marking_window = new_in_marking_window;
   _in_marking_window_im = new_in_marking_window_im;
-  _free_regions_at_end_of_collection = _g1->free_regions();
+  _free_regions_at_end_of_collection = _g1->num_free_regions();
   update_young_list_target_length();
 
   // Note that _mmu_tracker->max_gc_time() returns the time in seconds.
@@ -1202,7 +1202,7 @@
   _survivor_used_bytes_before_gc = young_list->survivor_used_bytes();
   _heap_capacity_bytes_before_gc = _g1->capacity();
   _heap_used_bytes_before_gc = _g1->used();
-  _cur_collection_pause_used_regions_at_start = _g1->used_regions();
+  _cur_collection_pause_used_regions_at_start = _g1->num_used_regions();
 
   _eden_capacity_bytes_before_gc =
          (_young_list_target_length * HeapRegion::GrainBytes) - _survivor_used_bytes_before_gc;
@@ -1617,7 +1617,7 @@
 G1CollectorPolicy::record_concurrent_mark_cleanup_end(int no_of_gc_threads) {
   _collectionSetChooser->clear();
 
-  uint region_num = _g1->n_regions();
+  uint region_num = _g1->num_regions();
   if (G1CollectedHeap::use_parallel_gc_threads()) {
     const uint OverpartitionFactor = 4;
     uint WorkUnit;
@@ -1638,7 +1638,7 @@
         MAX2(region_num / (uint) (ParallelGCThreads * OverpartitionFactor),
              MinWorkUnit);
     }
-    _collectionSetChooser->prepare_for_par_region_addition(_g1->n_regions(),
+    _collectionSetChooser->prepare_for_par_region_addition(_g1->num_regions(),
                                                            WorkUnit);
     ParKnownGarbageTask parKnownGarbageTask(_collectionSetChooser,
                                             (int) WorkUnit);
@@ -1935,7 +1935,7 @@
   // of them are available.
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  const size_t region_num = g1h->n_regions();
+  const size_t region_num = g1h->num_regions();
   const size_t perc = (size_t) G1OldCSetRegionThresholdPercent;
   size_t result = region_num * perc / 100;
   // emulate ceiling
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp
index eb64b87..4b25d90 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1EvacFailure.hpp
@@ -71,6 +71,9 @@
   bool _during_initial_mark;
   bool _during_conc_mark;
   uint _worker_id;
+  HeapWord* _end_of_last_gap;
+  HeapWord* _last_gap_threshold;
+  HeapWord* _last_obj_threshold;
 
 public:
   RemoveSelfForwardPtrObjClosure(G1CollectedHeap* g1, ConcurrentMark* cm,
@@ -83,7 +86,10 @@
     _update_rset_cl(update_rset_cl),
     _during_initial_mark(during_initial_mark),
     _during_conc_mark(during_conc_mark),
-    _worker_id(worker_id) { }
+    _worker_id(worker_id),
+    _end_of_last_gap(hr->bottom()),
+    _last_gap_threshold(hr->bottom()),
+    _last_obj_threshold(hr->bottom()) { }
 
   size_t marked_bytes() { return _marked_bytes; }
 
@@ -107,7 +113,12 @@
     HeapWord* obj_addr = (HeapWord*) obj;
     assert(_hr->is_in(obj_addr), "sanity");
     size_t obj_size = obj->size();
-    _hr->update_bot_for_object(obj_addr, obj_size);
+    HeapWord* obj_end = obj_addr + obj_size;
+
+    if (_end_of_last_gap != obj_addr) {
+      // there was a gap before obj_addr
+      _last_gap_threshold = _hr->cross_threshold(_end_of_last_gap, obj_addr);
+    }
 
     if (obj->is_forwarded() && obj->forwardee() == obj) {
       // The object failed to move.
@@ -115,7 +126,9 @@
       // We consider all objects that we find self-forwarded to be
       // live. What we'll do is that we'll update the prev marking
       // info so that they are all under PTAMS and explicitly marked.
-      _cm->markPrev(obj);
+      if (!_cm->isPrevMarked(obj)) {
+        _cm->markPrev(obj);
+      }
       if (_during_initial_mark) {
         // For the next marking info we'll only mark the
         // self-forwarded objects explicitly if we are during
@@ -145,13 +158,18 @@
       // remembered set entries missing given that we skipped cards on
       // the collection set. So, we'll recreate such entries now.
       obj->oop_iterate(_update_rset_cl);
-      assert(_cm->isPrevMarked(obj), "Should be marked!");
     } else {
+
       // The object has been either evacuated or is dead. Fill it with a
       // dummy object.
-      MemRegion mr((HeapWord*) obj, obj_size);
+      MemRegion mr(obj_addr, obj_size);
       CollectedHeap::fill_with_object(mr);
+
+      // must nuke all dead objects which we skipped when iterating over the region
+      _cm->clearRangePrevBitmap(MemRegion(_end_of_last_gap, obj_end));
     }
+    _end_of_last_gap = obj_end;
+    _last_obj_threshold = _hr->cross_threshold(obj_addr, obj_end);
   }
 };
 
@@ -182,15 +200,9 @@
                                             during_conc_mark,
                                             _worker_id);
 
-        MemRegion mr(hr->bottom(), hr->end());
-        // We'll recreate the prev marking info so we'll first clear
-        // the prev bitmap range for this region. We never mark any
-        // CSet objects explicitly so the next bitmap range should be
-        // cleared anyway.
-        _cm->clearRangePrevBitmap(mr);
-
         hr->note_self_forwarding_removal_start(during_initial_mark,
                                                during_conc_mark);
+        _g1h->check_bitmaps("Self-Forwarding Ptr Removal", hr);
 
         // In the common case (i.e. when there is no evacuation
         // failure) we make sure that the following is done when
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
index e5729bc..b18e6da 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.cpp
@@ -166,13 +166,14 @@
   _last_update_rs_processed_buffers(_max_gc_threads, "%d"),
   _last_scan_rs_times_ms(_max_gc_threads, "%.1lf"),
   _last_strong_code_root_scan_times_ms(_max_gc_threads, "%.1lf"),
-  _last_strong_code_root_mark_times_ms(_max_gc_threads, "%.1lf"),
   _last_obj_copy_times_ms(_max_gc_threads, "%.1lf"),
   _last_termination_times_ms(_max_gc_threads, "%.1lf"),
   _last_termination_attempts(_max_gc_threads, SIZE_FORMAT),
   _last_gc_worker_end_times_ms(_max_gc_threads, "%.1lf", false),
   _last_gc_worker_times_ms(_max_gc_threads, "%.1lf"),
   _last_gc_worker_other_times_ms(_max_gc_threads, "%.1lf"),
+  _last_redirty_logged_cards_time_ms(_max_gc_threads, "%.1lf"),
+  _last_redirty_logged_cards_processed_cards(_max_gc_threads, SIZE_FORMAT),
   _cur_string_dedup_queue_fixup_worker_times_ms(_max_gc_threads, "%.1lf"),
   _cur_string_dedup_table_fixup_worker_times_ms(_max_gc_threads, "%.1lf")
 {
@@ -191,13 +192,16 @@
   _last_update_rs_processed_buffers.reset();
   _last_scan_rs_times_ms.reset();
   _last_strong_code_root_scan_times_ms.reset();
-  _last_strong_code_root_mark_times_ms.reset();
   _last_obj_copy_times_ms.reset();
   _last_termination_times_ms.reset();
   _last_termination_attempts.reset();
   _last_gc_worker_end_times_ms.reset();
   _last_gc_worker_times_ms.reset();
   _last_gc_worker_other_times_ms.reset();
+
+  _last_redirty_logged_cards_time_ms.reset();
+  _last_redirty_logged_cards_processed_cards.reset();
+
 }
 
 void G1GCPhaseTimes::note_gc_end() {
@@ -208,7 +212,6 @@
   _last_update_rs_processed_buffers.verify();
   _last_scan_rs_times_ms.verify();
   _last_strong_code_root_scan_times_ms.verify();
-  _last_strong_code_root_mark_times_ms.verify();
   _last_obj_copy_times_ms.verify();
   _last_termination_times_ms.verify();
   _last_termination_attempts.verify();
@@ -223,7 +226,6 @@
                                _last_update_rs_times_ms.get(i) +
                                _last_scan_rs_times_ms.get(i) +
                                _last_strong_code_root_scan_times_ms.get(i) +
-                               _last_strong_code_root_mark_times_ms.get(i) +
                                _last_obj_copy_times_ms.get(i) +
                                _last_termination_times_ms.get(i);
 
@@ -233,6 +235,11 @@
 
   _last_gc_worker_times_ms.verify();
   _last_gc_worker_other_times_ms.verify();
+
+  if (G1DeferredRSUpdate) {
+    _last_redirty_logged_cards_time_ms.verify();
+    _last_redirty_logged_cards_processed_cards.verify();
+  }
 }
 
 void G1GCPhaseTimes::note_string_dedup_fixup_start() {
@@ -249,6 +256,10 @@
   LineBuffer(level).append_and_print_cr("[%s: %.1lf ms]", str, value);
 }
 
+void G1GCPhaseTimes::print_stats(int level, const char* str, size_t value) {
+  LineBuffer(level).append_and_print_cr("[%s: "SIZE_FORMAT"]", str, value);
+}
+
 void G1GCPhaseTimes::print_stats(int level, const char* str, double value, uint workers) {
   LineBuffer(level).append_and_print_cr("[%s: %.1lf ms, GC Workers: " UINT32_FORMAT "]", str, value, workers);
 }
@@ -292,9 +303,6 @@
     if (_last_satb_filtering_times_ms.sum() > 0.0) {
       _last_satb_filtering_times_ms.print(2, "SATB Filtering (ms)");
     }
-    if (_last_strong_code_root_mark_times_ms.sum() > 0.0) {
-     _last_strong_code_root_mark_times_ms.print(2, "Code Root Marking (ms)");
-    }
     _last_update_rs_times_ms.print(2, "Update RS (ms)");
       _last_update_rs_processed_buffers.print(3, "Processed Buffers");
     _last_scan_rs_times_ms.print(2, "Scan RS (ms)");
@@ -312,9 +320,6 @@
     if (_last_satb_filtering_times_ms.sum() > 0.0) {
       _last_satb_filtering_times_ms.print(1, "SATB Filtering (ms)");
     }
-    if (_last_strong_code_root_mark_times_ms.sum() > 0.0) {
-      _last_strong_code_root_mark_times_ms.print(1, "Code Root Marking (ms)");
-    }
     _last_update_rs_times_ms.print(1, "Update RS (ms)");
       _last_update_rs_processed_buffers.print(2, "Processed Buffers");
     _last_scan_rs_times_ms.print(1, "Scan RS (ms)");
@@ -352,6 +357,18 @@
   print_stats(2, "Ref Enq", _cur_ref_enq_time_ms);
   if (G1DeferredRSUpdate) {
     print_stats(2, "Redirty Cards", _recorded_redirty_logged_cards_time_ms);
+    if (G1Log::finest()) {
+      _last_redirty_logged_cards_time_ms.print(3, "Parallel Redirty");
+      _last_redirty_logged_cards_processed_cards.print(3, "Redirtied Cards");
+    }
+  }
+  if (G1ReclaimDeadHumongousObjectsAtYoungGC) {
+    print_stats(2, "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms);
+    if (G1Log::finest()) {
+      print_stats(3, "Humongous Total", _cur_fast_reclaim_humongous_total);
+      print_stats(3, "Humongous Candidate", _cur_fast_reclaim_humongous_candidates);
+      print_stats(3, "Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed);
+    }
   }
   print_stats(2, "Free CSet",
     (_recorded_young_free_cset_time_ms +
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
index e47c389..4237c97 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1GCPhaseTimes.hpp
@@ -120,7 +120,6 @@
   WorkerDataArray<int>    _last_update_rs_processed_buffers;
   WorkerDataArray<double> _last_scan_rs_times_ms;
   WorkerDataArray<double> _last_strong_code_root_scan_times_ms;
-  WorkerDataArray<double> _last_strong_code_root_mark_times_ms;
   WorkerDataArray<double> _last_obj_copy_times_ms;
   WorkerDataArray<double> _last_termination_times_ms;
   WorkerDataArray<size_t> _last_termination_attempts;
@@ -151,16 +150,24 @@
   double _recorded_young_cset_choice_time_ms;
   double _recorded_non_young_cset_choice_time_ms;
 
+  WorkerDataArray<double> _last_redirty_logged_cards_time_ms;
+  WorkerDataArray<size_t> _last_redirty_logged_cards_processed_cards;
   double _recorded_redirty_logged_cards_time_ms;
 
   double _recorded_young_free_cset_time_ms;
   double _recorded_non_young_free_cset_time_ms;
 
+  double _cur_fast_reclaim_humongous_time_ms;
+  size_t _cur_fast_reclaim_humongous_total;
+  size_t _cur_fast_reclaim_humongous_candidates;
+  size_t _cur_fast_reclaim_humongous_reclaimed;
+
   double _cur_verify_before_time_ms;
   double _cur_verify_after_time_ms;
 
   // Helper methods for detailed logging
   void print_stats(int level, const char* str, double value);
+  void print_stats(int level, const char* str, size_t value);
   void print_stats(int level, const char* str, double value, uint workers);
 
  public:
@@ -197,10 +204,6 @@
     _last_strong_code_root_scan_times_ms.set(worker_i, ms);
   }
 
-  void record_strong_code_root_mark_time(uint worker_i, double ms) {
-    _last_strong_code_root_mark_times_ms.set(worker_i, ms);
-  }
-
   void record_obj_copy_time(uint worker_i, double ms) {
     _last_obj_copy_times_ms.set(worker_i, ms);
   }
@@ -285,6 +288,16 @@
     _recorded_non_young_free_cset_time_ms = time_ms;
   }
 
+  void record_fast_reclaim_humongous_stats(size_t total, size_t candidates) {
+    _cur_fast_reclaim_humongous_total = total;
+    _cur_fast_reclaim_humongous_candidates = candidates;
+  }
+
+  void record_fast_reclaim_humongous_time_ms(double value, size_t reclaimed) {
+    _cur_fast_reclaim_humongous_time_ms = value;
+    _cur_fast_reclaim_humongous_reclaimed = reclaimed;
+  }
+
   void record_young_cset_choice_time_ms(double time_ms) {
     _recorded_young_cset_choice_time_ms = time_ms;
   }
@@ -293,6 +306,14 @@
     _recorded_non_young_cset_choice_time_ms = time_ms;
   }
 
+  void record_redirty_logged_cards_time_ms(uint worker_i, double time_ms) {
+    _last_redirty_logged_cards_time_ms.set(worker_i, time_ms);
+  }
+
+  void record_redirty_logged_cards_processed_cards(uint worker_i, size_t processed_buffers) {
+    _last_redirty_logged_cards_processed_cards.set(worker_i, processed_buffers);
+  }
+
   void record_redirty_logged_cards_time_ms(double time_ms) {
     _recorded_redirty_logged_cards_time_ms = time_ms;
   }
@@ -343,6 +364,10 @@
     return _recorded_non_young_free_cset_time_ms;
   }
 
+  double fast_reclaim_humongous_time_ms() {
+    return _cur_fast_reclaim_humongous_time_ms;
+  }
+
   double average_last_update_rs_time() {
     return _last_update_rs_times_ms.average();
   }
@@ -359,10 +384,6 @@
     return _last_strong_code_root_scan_times_ms.average();
   }
 
-  double average_last_strong_code_root_mark_time(){
-    return _last_strong_code_root_mark_times_ms.average();
-  }
-
   double average_last_obj_copy_time() {
     return _last_obj_copy_times_ms.average();
   }
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp
index dfae91e..07da908 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.cpp
@@ -33,7 +33,7 @@
 G1HotCardCache::G1HotCardCache(G1CollectedHeap *g1h):
   _g1h(g1h), _hot_cache(NULL), _use_cache(false), _card_counts(g1h) {}
 
-void G1HotCardCache::initialize() {
+void G1HotCardCache::initialize(G1RegionToSpaceMapper* card_counts_storage) {
   if (default_use_cache()) {
     _use_cache = true;
 
@@ -49,7 +49,7 @@
     _hot_cache_par_chunk_size = MAX2(1, _hot_cache_size / (int)n_workers);
     _hot_cache_par_claimed_idx = 0;
 
-    _card_counts.initialize();
+    _card_counts.initialize(card_counts_storage);
   }
 }
 
@@ -135,11 +135,8 @@
   // above, are discarded prior to re-enabling the cache near the end of the GC.
 }
 
-void G1HotCardCache::resize_card_counts(size_t heap_capacity) {
-  _card_counts.resize(heap_capacity);
-}
-
 void G1HotCardCache::reset_card_counts(HeapRegion* hr) {
+  assert(!hr->isHumongous(), "Should have been cleared");
   _card_counts.clear_region(hr);
 }
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp
index 5dc929c..becd683 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1HotCardCache.hpp
@@ -78,7 +78,7 @@
   G1HotCardCache(G1CollectedHeap* g1h);
   ~G1HotCardCache();
 
-  void initialize();
+  void initialize(G1RegionToSpaceMapper* card_counts_storage);
 
   bool use_cache() { return _use_cache; }
 
@@ -115,9 +115,6 @@
 
   bool hot_cache_is_empty() { return _n_hot == 0; }
 
-  // Resizes the card counts table to match the given capacity
-  void resize_card_counts(size_t heap_capacity);
-
   // Zeros the values in the card counts table for entire committed heap
   void reset_card_counts();
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
index 91d1434..2636515 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1MarkSweep.cpp
@@ -123,20 +123,20 @@
 void G1MarkSweep::mark_sweep_phase1(bool& marked_for_unloading,
                                     bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer());
+  GCTraceTime tm("phase 1", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
   GenMarkSweep::trace(" 1");
 
   SharedHeap* sh = SharedHeap::heap();
 
-  // Need cleared claim bits for the strong roots processing
+  // Need cleared claim bits for the roots processing
   ClassLoaderDataGraph::clear_claimed_marks();
 
-  sh->process_strong_roots(true,  // activate StrongRootsScope
-                           false, // not scavenging.
-                           SharedHeap::SO_SystemClasses,
+  MarkingCodeBlobClosure follow_code_closure(&GenMarkSweep::follow_root_closure, !CodeBlobToOopClosure::FixRelocations);
+  sh->process_strong_roots(true,   // activate StrongRootsScope
+                           SharedHeap::SO_None,
                            &GenMarkSweep::follow_root_closure,
-                           &GenMarkSweep::follow_code_root_closure,
-                           &GenMarkSweep::follow_klass_closure);
+                           &GenMarkSweep::follow_cld_closure,
+                           &follow_code_closure);
 
   // Process reference objects found during marking
   ReferenceProcessor* rp = GenMarkSweep::ref_processor();
@@ -148,7 +148,8 @@
                                       &GenMarkSweep::keep_alive,
                                       &GenMarkSweep::follow_stack_closure,
                                       NULL,
-                                      gc_timer());
+                                      gc_timer(),
+                                      gc_tracer()->gc_id());
   gc_tracer()->report_gc_reference_stats(stats);
 
 
@@ -199,6 +200,23 @@
   CompactPoint _cp;
   HeapRegionSetCount _humongous_regions_removed;
 
+  bool is_cp_initialized() const {
+    return _cp.space != NULL;
+  }
+
+  void prepare_for_compaction(HeapRegion* hr, HeapWord* end) {
+    // If this is the first live region that we came across which we can compact,
+    // initialize the CompactPoint.
+    if (!is_cp_initialized()) {
+      _cp.space = hr;
+      _cp.threshold = hr->initialize_threshold();
+    }
+    hr->prepare_for_compaction(&_cp);
+    // Also clear the part of the card table that will be unused after
+    // compaction.
+    _mrbs->clear(MemRegion(hr->compaction_top(), end));
+  }
+
   void free_humongous_region(HeapRegion* hr) {
     HeapWord* end = hr->end();
     FreeRegionList dummy_free_list("Dummy Free List for G1MarkSweep");
@@ -210,18 +228,15 @@
     _humongous_regions_removed.increment(1u, hr->capacity());
 
     _g1h->free_humongous_region(hr, &dummy_free_list, false /* par */);
-    hr->prepare_for_compaction(&_cp);
-    // Also clear the part of the card table that will be unused after
-    // compaction.
-    _mrbs->clear(MemRegion(hr->compaction_top(), end));
+    prepare_for_compaction(hr, end);
     dummy_free_list.remove_all();
   }
 
 public:
-  G1PrepareCompactClosure(CompactibleSpace* cs)
+  G1PrepareCompactClosure()
   : _g1h(G1CollectedHeap::heap()),
     _mrbs(_g1h->g1_barrier_set()),
-    _cp(NULL, cs, cs->initialize_threshold()),
+    _cp(NULL),
     _humongous_regions_removed() { }
 
   void update_sets() {
@@ -244,10 +259,7 @@
         assert(hr->continuesHumongous(), "Invalid humongous.");
       }
     } else {
-      hr->prepare_for_compaction(&_cp);
-      // Also clear the part of the card table that will be unused after
-      // compaction.
-      _mrbs->clear(MemRegion(hr->compaction_top(), hr->end()));
+      prepare_for_compaction(hr, hr->end());
     }
     return false;
   }
@@ -262,17 +274,10 @@
 
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer());
+  GCTraceTime tm("phase 2", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
   GenMarkSweep::trace("2");
 
-  // find the first region
-  HeapRegion* r = g1h->region_at(0);
-  CompactibleSpace* sp = r;
-  if (r->isHumongous() && oop(r->bottom())->is_gc_marked()) {
-    sp = r->next_compaction_space();
-  }
-
-  G1PrepareCompactClosure blk(sp);
+  G1PrepareCompactClosure blk;
   g1h->heap_region_iterate(&blk);
   blk.update_sets();
 }
@@ -299,27 +304,27 @@
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
   // Adjust the pointers to reflect the new locations
-  GCTraceTime tm("phase 3", G1Log::fine() && Verbose, true, gc_timer());
+  GCTraceTime tm("phase 3", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
   GenMarkSweep::trace("3");
 
   SharedHeap* sh = SharedHeap::heap();
 
-  // Need cleared claim bits for the strong roots processing
+  // Need cleared claim bits for the roots processing
   ClassLoaderDataGraph::clear_claimed_marks();
 
-  sh->process_strong_roots(true,  // activate StrongRootsScope
-                           false, // not scavenging.
-                           SharedHeap::SO_AllClasses,
-                           &GenMarkSweep::adjust_pointer_closure,
-                           NULL,  // do not touch code cache here
-                           &GenMarkSweep::adjust_klass_closure);
+  CodeBlobToOopClosure adjust_code_closure(&GenMarkSweep::adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations);
+  sh->process_all_roots(true,  // activate StrongRootsScope
+                        SharedHeap::SO_AllCodeCache,
+                        &GenMarkSweep::adjust_pointer_closure,
+                        &GenMarkSweep::adjust_cld_closure,
+                        &adjust_code_closure);
 
   assert(GenMarkSweep::ref_processor() == g1h->ref_processor_stw(), "Sanity");
   g1h->ref_processor_stw()->weak_oops_do(&GenMarkSweep::adjust_pointer_closure);
 
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
-  g1h->g1_process_weak_roots(&GenMarkSweep::adjust_pointer_closure);
+  sh->process_weak_roots(&GenMarkSweep::adjust_pointer_closure);
 
   if (G1StringDedup::is_enabled()) {
     G1StringDedup::oops_do(&GenMarkSweep::adjust_pointer_closure);
@@ -362,7 +367,7 @@
   // to use a higher index (saved from phase2) when verifying perm_gen.
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
 
-  GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer());
+  GCTraceTime tm("phase 4", G1Log::fine() && Verbose, true, gc_timer(), gc_tracer()->gc_id());
   GenMarkSweep::trace("4");
 
   G1SpaceCompactClosure blk;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp
index a30b004..2bdbca5 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.cpp
@@ -25,7 +25,28 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1OopClosures.inline.hpp"
+#include "gc_implementation/g1/g1ParScanThreadState.hpp"
 
 G1ParCopyHelper::G1ParCopyHelper(G1CollectedHeap* g1,  G1ParScanThreadState* par_scan_state) :
   G1ParClosureSuper(g1, par_scan_state), _scanned_klass(NULL),
   _cm(_g1->concurrent_mark()) {}
+
+G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1) :
+  _g1(g1), _par_scan_state(NULL), _worker_id(UINT_MAX) { }
+
+G1ParClosureSuper::G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state) :
+  _g1(g1), _par_scan_state(NULL),
+  _worker_id(UINT_MAX) {
+  set_par_scan_thread_state(par_scan_state);
+}
+
+void G1ParClosureSuper::set_par_scan_thread_state(G1ParScanThreadState* par_scan_state) {
+  assert(_par_scan_state == NULL, "_par_scan_state must only be set once");
+  assert(par_scan_state != NULL, "Must set par_scan_state to non-NULL.");
+
+  _par_scan_state = par_scan_state;
+  _worker_id = par_scan_state->queue_num();
+
+  assert(_worker_id < MAX2((uint)ParallelGCThreads, 1u),
+         err_msg("The given worker id %u must be less than the number of threads %u", _worker_id, MAX2((uint)ParallelGCThreads, 1u)));
+}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp
index fd22e81..79f8b52 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.hpp
@@ -25,6 +25,8 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1OOPCLOSURES_HPP
 
+#include "memory/iterator.hpp"
+
 class HeapRegion;
 class G1CollectedHeap;
 class G1RemSet;
@@ -51,8 +53,13 @@
   G1ParScanThreadState* _par_scan_state;
   uint _worker_id;
 public:
+  // Initializes the instance, leaving _par_scan_state uninitialized. Must be done
+  // later using the set_par_scan_thread_state() method.
+  G1ParClosureSuper(G1CollectedHeap* g1);
   G1ParClosureSuper(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state);
   bool apply_to_weak_ref_discovered_field() { return true; }
+
+  void set_par_scan_thread_state(G1ParScanThreadState* par_scan_state);
 };
 
 class G1ParPushHeapRSClosure : public G1ParClosureSuper {
@@ -68,9 +75,8 @@
 
 class G1ParScanClosure : public G1ParClosureSuper {
 public:
-  G1ParScanClosure(G1CollectedHeap* g1, G1ParScanThreadState* par_scan_state, ReferenceProcessor* rp) :
-    G1ParClosureSuper(g1, par_scan_state)
-  {
+  G1ParScanClosure(G1CollectedHeap* g1, ReferenceProcessor* rp) :
+    G1ParClosureSuper(g1) {
     assert(_ref_processor == NULL, "sanity");
     _ref_processor = rp;
   }
@@ -102,7 +108,7 @@
   template <class T> void do_klass_barrier(T* p, oop new_obj);
 };
 
-template <G1Barrier barrier, bool do_mark_object>
+template <G1Barrier barrier, G1Mark do_mark_object>
 class G1ParCopyClosure : public G1ParCopyHelper {
 private:
   template <class T> void do_oop_work(T* p);
@@ -117,19 +123,19 @@
   template <class T> void do_oop_nv(T* p) { do_oop_work(p); }
   virtual void do_oop(oop* p)       { do_oop_nv(p); }
   virtual void do_oop(narrowOop* p) { do_oop_nv(p); }
+
+  G1CollectedHeap*      g1()  { return _g1; };
+  G1ParScanThreadState* pss() { return _par_scan_state; }
+  ReferenceProcessor*   rp()  { return _ref_processor; };
 };
 
-typedef G1ParCopyClosure<G1BarrierNone, false> G1ParScanExtRootClosure;
-typedef G1ParCopyClosure<G1BarrierKlass, false> G1ParScanMetadataClosure;
-
-
-typedef G1ParCopyClosure<G1BarrierNone, true> G1ParScanAndMarkExtRootClosure;
-typedef G1ParCopyClosure<G1BarrierKlass, true> G1ParScanAndMarkMetadataClosure;
-
+typedef G1ParCopyClosure<G1BarrierNone,  G1MarkNone>             G1ParScanExtRootClosure;
+typedef G1ParCopyClosure<G1BarrierNone,  G1MarkFromRoot>         G1ParScanAndMarkExtRootClosure;
+typedef G1ParCopyClosure<G1BarrierNone,  G1MarkPromotedFromRoot> G1ParScanAndMarkWeakExtRootClosure;
 // We use a separate closure to handle references during evacuation
 // failure processing.
 
-typedef G1ParCopyClosure<G1BarrierEvac, false> G1ParScanHeapEvacFailureClosure;
+typedef G1ParCopyClosure<G1BarrierEvac, G1MarkNone> G1ParScanHeapEvacFailureClosure;
 
 class FilterIntoCSClosure: public ExtendedOopClosure {
   G1CollectedHeap* _g1;
@@ -160,10 +166,11 @@
 };
 
 // Closure for iterating over object fields during concurrent marking
-class G1CMOopClosure : public ExtendedOopClosure {
+class G1CMOopClosure : public MetadataAwareOopClosure {
+protected:
+  ConcurrentMark*    _cm;
 private:
   G1CollectedHeap*   _g1h;
-  ConcurrentMark*    _cm;
   CMTask*            _task;
 public:
   G1CMOopClosure(G1CollectedHeap* g1h, ConcurrentMark* cm, CMTask* task);
@@ -173,7 +180,7 @@
 };
 
 // Closure to scan the root regions during concurrent marking
-class G1RootRegionScanClosure : public ExtendedOopClosure {
+class G1RootRegionScanClosure : public MetadataAwareOopClosure {
 private:
   G1CollectedHeap* _g1h;
   ConcurrentMark*  _cm;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp
index 25a0d05..bcf30b6 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1OopClosures.inline.hpp
@@ -28,9 +28,12 @@
 #include "gc_implementation/g1/concurrentMark.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.hpp"
 #include "gc_implementation/g1/g1OopClosures.hpp"
+#include "gc_implementation/g1/g1ParScanThreadState.inline.hpp"
 #include "gc_implementation/g1/g1RemSet.hpp"
 #include "gc_implementation/g1/g1RemSet.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
+#include "memory/iterator.inline.hpp"
+#include "runtime/prefetch.inline.hpp"
 
 /*
  * This really ought to be an inline function, but apparently the C++
@@ -41,7 +44,7 @@
 inline void FilterIntoCSClosure::do_oop_nv(T* p) {
   T heap_oop = oopDesc::load_heap_oop(p);
   if (!oopDesc::is_null(heap_oop) &&
-      _g1->obj_in_cs(oopDesc::decode_heap_oop_not_null(heap_oop))) {
+      _g1->is_in_cset_or_humongous(oopDesc::decode_heap_oop_not_null(heap_oop))) {
     _oc->do_oop(p);
   }
 }
@@ -64,7 +67,8 @@
 
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    if (_g1->in_cset_fast_test(obj)) {
+    G1CollectedHeap::in_cset_state_t state = _g1->in_cset_state(obj);
+    if (state == G1CollectedHeap::InCSet) {
       // We're not going to even bother checking whether the object is
       // already forwarded or not, as this usually causes an immediate
       // stall. We'll try to prefetch the object (for write, given that
@@ -83,6 +87,9 @@
 
       _par_scan_state->push_on_queue(p);
     } else {
+      if (state == G1CollectedHeap::IsHumongous) {
+        _g1->set_humongous_is_live(obj);
+      }
       _par_scan_state->update_rs(_from, p, _worker_id);
     }
   }
@@ -94,22 +101,20 @@
 
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
-    if (_g1->in_cset_fast_test(obj)) {
+    if (_g1->is_in_cset_or_humongous(obj)) {
       Prefetch::write(obj->mark_addr(), 0);
       Prefetch::read(obj->mark_addr(), (HeapWordSize*2));
 
       // Place on the references queue
       _par_scan_state->push_on_queue(p);
+    } else {
+      assert(!_g1->obj_in_cs(obj), "checking");
     }
   }
 }
 
 template <class T>
 inline void G1CMOopClosure::do_oop_nv(T* p) {
-  assert(_g1h->is_in_g1_reserved((HeapWord*) p), "invariant");
-  assert(!_g1h->is_on_master_free_list(
-                    _g1h->heap_region_containing((HeapWord*) p)), "invariant");
-
   oop obj = oopDesc::load_decode_heap_oop(p);
   if (_cm->verbose_high()) {
     gclog_or_tty->print_cr("[%u] we're looking at location "
@@ -125,9 +130,7 @@
   if (!oopDesc::is_null(heap_oop)) {
     oop obj = oopDesc::decode_heap_oop_not_null(heap_oop);
     HeapRegion* hr = _g1h->heap_region_containing((HeapWord*) obj);
-    if (hr != NULL) {
-      _cm->grayRoot(obj, obj->size(), _worker_id, hr);
-    }
+    _cm->grayRoot(obj, obj->size(), _worker_id, hr);
   }
 }
 
@@ -154,57 +157,61 @@
 template <class T>
 inline void G1UpdateRSOrPushRefOopClosure::do_oop_nv(T* p) {
   oop obj = oopDesc::load_decode_heap_oop(p);
+  if (obj == NULL) {
+    return;
+  }
 #ifdef ASSERT
   // can't do because of races
   // assert(obj == NULL || obj->is_oop(), "expected an oop");
 
   // Do the safe subset of is_oop
-  if (obj != NULL) {
 #ifdef CHECK_UNHANDLED_OOPS
-    oopDesc* o = obj.obj();
+  oopDesc* o = obj.obj();
 #else
-    oopDesc* o = obj;
+  oopDesc* o = obj;
 #endif // CHECK_UNHANDLED_OOPS
-    assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
-    assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
-  }
+  assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
+  assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
 #endif // ASSERT
 
   assert(_from != NULL, "from region must be non-NULL");
   assert(_from->is_in_reserved(p), "p is not in from");
 
   HeapRegion* to = _g1->heap_region_containing(obj);
-  if (to != NULL && _from != to) {
-    // The _record_refs_into_cset flag is true during the RSet
-    // updating part of an evacuation pause. It is false at all
-    // other times:
-    //  * rebuilding the rembered sets after a full GC
-    //  * during concurrent refinement.
-    //  * updating the remembered sets of regions in the collection
-    //    set in the event of an evacuation failure (when deferred
-    //    updates are enabled).
+  if (_from == to) {
+    // Normally this closure should only be called with cross-region references.
+    // But since Java threads are manipulating the references concurrently and we
+    // reload the values things may have changed.
+    return;
+  }
+  // The _record_refs_into_cset flag is true during the RSet
+  // updating part of an evacuation pause. It is false at all
+  // other times:
+  //  * rebuilding the remembered sets after a full GC
+  //  * during concurrent refinement.
+  //  * updating the remembered sets of regions in the collection
+  //    set in the event of an evacuation failure (when deferred
+  //    updates are enabled).
 
-    if (_record_refs_into_cset && to->in_collection_set()) {
-      // We are recording references that point into the collection
-      // set and this particular reference does exactly that...
-      // If the referenced object has already been forwarded
-      // to itself, we are handling an evacuation failure and
-      // we have already visited/tried to copy this object
-      // there is no need to retry.
-      if (!self_forwarded(obj)) {
-        assert(_push_ref_cl != NULL, "should not be null");
-        // Push the reference in the refs queue of the G1ParScanThreadState
-        // instance for this worker thread.
-        _push_ref_cl->do_oop(p);
-      }
+  if (_record_refs_into_cset && to->in_collection_set()) {
+    // We are recording references that point into the collection
+    // set and this particular reference does exactly that...
+    // If the referenced object has already been forwarded
+    // to itself, we are handling an evacuation failure and
+    // we have already visited/tried to copy this object
+    // there is no need to retry.
+    if (!self_forwarded(obj)) {
+      assert(_push_ref_cl != NULL, "should not be null");
+      // Push the reference in the refs queue of the G1ParScanThreadState
+      // instance for this worker thread.
+      _push_ref_cl->do_oop(p);
+     }
 
-      // Deferred updates to the CSet are either discarded (in the normal case),
-      // or processed (if an evacuation failure occurs) at the end
-      // of the collection.
-      // See G1RemSet::cleanup_after_oops_into_collection_set_do().
-      return;
-    }
-
+    // Deferred updates to the CSet are either discarded (in the normal case),
+    // or processed (if an evacuation failure occurs) at the end
+    // of the collection.
+    // See G1RemSet::cleanup_after_oops_into_collection_set_do().
+  } else {
     // We either don't care about pushing references that point into the
     // collection set (i.e. we're not during an evacuation pause) _or_
     // the reference doesn't point into the collection set. Either way
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp
new file mode 100644
index 0000000..1b294ed
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/g1PageBasedVirtualSpace.hpp"
+#include "oops/markOop.hpp"
+#include "oops/oop.inline.hpp"
+#include "services/memTracker.hpp"
+#ifdef TARGET_OS_FAMILY_linux
+# include "os_linux.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_solaris
+# include "os_solaris.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_windows
+# include "os_windows.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_aix
+# include "os_aix.inline.hpp"
+#endif
+#ifdef TARGET_OS_FAMILY_bsd
+# include "os_bsd.inline.hpp"
+#endif
+#include "utilities/bitMap.inline.hpp"
+
+G1PageBasedVirtualSpace::G1PageBasedVirtualSpace() : _low_boundary(NULL),
+  _high_boundary(NULL), _committed(), _page_size(0), _special(false), _executable(false) {
+}
+
+bool G1PageBasedVirtualSpace::initialize_with_granularity(ReservedSpace rs, size_t page_size) {
+  if (!rs.is_reserved()) {
+    return false;  // Allocation failed.
+  }
+  assert(_low_boundary == NULL, "VirtualSpace already initialized");
+  assert(page_size > 0, "Granularity must be non-zero.");
+
+  _low_boundary  = rs.base();
+  _high_boundary = _low_boundary + rs.size();
+
+  _special = rs.special();
+  _executable = rs.executable();
+
+  _page_size = page_size;
+
+  assert(_committed.size() == 0, "virtual space initialized more than once");
+  uintx size_in_bits = rs.size() / page_size;
+  _committed.resize(size_in_bits, /* in_resource_area */ false);
+
+  return true;
+}
+
+
+G1PageBasedVirtualSpace::~G1PageBasedVirtualSpace() {
+  release();
+}
+
+void G1PageBasedVirtualSpace::release() {
+  // This does not release memory it never reserved.
+  // Caller must release via rs.release();
+  _low_boundary           = NULL;
+  _high_boundary          = NULL;
+  _special                = false;
+  _executable             = false;
+  _page_size              = 0;
+  _committed.resize(0, false);
+}
+
+size_t G1PageBasedVirtualSpace::committed_size() const {
+  return _committed.count_one_bits() * _page_size;
+}
+
+size_t G1PageBasedVirtualSpace::reserved_size() const {
+  return pointer_delta(_high_boundary, _low_boundary, sizeof(char));
+}
+
+size_t G1PageBasedVirtualSpace::uncommitted_size()  const {
+  return reserved_size() - committed_size();
+}
+
+uintptr_t G1PageBasedVirtualSpace::addr_to_page_index(char* addr) const {
+  return (addr - _low_boundary) / _page_size;
+}
+
+bool G1PageBasedVirtualSpace::is_area_committed(uintptr_t start, size_t size_in_pages) const {
+  uintptr_t end = start + size_in_pages;
+  return _committed.get_next_zero_offset(start, end) >= end;
+}
+
+bool G1PageBasedVirtualSpace::is_area_uncommitted(uintptr_t start, size_t size_in_pages) const {
+  uintptr_t end = start + size_in_pages;
+  return _committed.get_next_one_offset(start, end) >= end;
+}
+
+char* G1PageBasedVirtualSpace::page_start(uintptr_t index) {
+  return _low_boundary + index * _page_size;
+}
+
+size_t G1PageBasedVirtualSpace::byte_size_for_pages(size_t num) {
+  return num * _page_size;
+}
+
+MemRegion G1PageBasedVirtualSpace::commit(uintptr_t start, size_t size_in_pages) {
+  // We need to make sure to commit all pages covered by the given area.
+  guarantee(is_area_uncommitted(start, size_in_pages), "Specified area is not uncommitted");
+
+  if (!_special) {
+    os::commit_memory_or_exit(page_start(start), byte_size_for_pages(size_in_pages), _executable,
+                              err_msg("Failed to commit pages from "SIZE_FORMAT" of length "SIZE_FORMAT, start, size_in_pages));
+  }
+  _committed.set_range(start, start + size_in_pages);
+
+  MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
+  return result;
+}
+
+MemRegion G1PageBasedVirtualSpace::uncommit(uintptr_t start, size_t size_in_pages) {
+  guarantee(is_area_committed(start, size_in_pages), "checking");
+
+  if (!_special) {
+    os::uncommit_memory(page_start(start), byte_size_for_pages(size_in_pages));
+  }
+
+  _committed.clear_range(start, start + size_in_pages);
+
+  MemRegion result((HeapWord*)page_start(start), byte_size_for_pages(size_in_pages) / HeapWordSize);
+  return result;
+}
+
+bool G1PageBasedVirtualSpace::contains(const void* p) const {
+  return _low_boundary <= (const char*) p && (const char*) p < _high_boundary;
+}
+
+#ifndef PRODUCT
+void G1PageBasedVirtualSpace::print_on(outputStream* out) {
+  out->print   ("Virtual space:");
+  if (special()) out->print(" (pinned in memory)");
+  out->cr();
+  out->print_cr(" - committed: " SIZE_FORMAT, committed_size());
+  out->print_cr(" - reserved:  " SIZE_FORMAT, reserved_size());
+  out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]",  p2i(_low_boundary), p2i(_high_boundary));
+}
+
+void G1PageBasedVirtualSpace::print() {
+  print_on(tty);
+}
+#endif
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp
new file mode 100644
index 0000000..972a69b
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1PageBasedVirtualSpace.hpp
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1PAGEBASEDVIRTUALSPACE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1PAGEBASEDVIRTUALSPACE_HPP
+
+#include "memory/allocation.hpp"
+#include "memory/memRegion.hpp"
+#include "runtime/virtualspace.hpp"
+#include "utilities/bitMap.hpp"
+
+// Virtual space management helper for a virtual space with an OS page allocation
+// granularity.
+// (De-)Allocation requests are always OS page aligned by passing a page index
+// and multiples of pages.
+// The implementation gives an error when trying to commit or uncommit pages that
+// have already been committed or uncommitted.
+class G1PageBasedVirtualSpace VALUE_OBJ_CLASS_SPEC {
+  friend class VMStructs;
+ private:
+  // Reserved area addresses.
+  char* _low_boundary;
+  char* _high_boundary;
+
+  // The commit/uncommit granularity in bytes.
+  size_t _page_size;
+
+  // Bitmap used for verification of commit/uncommit operations.
+  BitMap _committed;
+
+  // Indicates that the entire space has been committed and pinned in memory,
+  // os::commit_memory() or os::uncommit_memory() have no function.
+  bool _special;
+
+  // Indicates whether the committed space should be executable.
+  bool _executable;
+
+  // Returns the index of the page which contains the given address.
+  uintptr_t  addr_to_page_index(char* addr) const;
+  // Returns the address of the given page index.
+  char*  page_start(uintptr_t index);
+  // Returns the byte size of the given number of pages.
+  size_t byte_size_for_pages(size_t num);
+
+  // Returns true if the entire area is backed by committed memory.
+  bool is_area_committed(uintptr_t start, size_t size_in_pages) const;
+  // Returns true if the entire area is not backed by committed memory.
+  bool is_area_uncommitted(uintptr_t start, size_t size_in_pages) const;
+
+ public:
+
+  // Commit the given area of pages starting at start being size_in_pages large.
+  MemRegion commit(uintptr_t start, size_t size_in_pages);
+
+  // Uncommit the given area of pages starting at start being size_in_pages large.
+  MemRegion uncommit(uintptr_t start, size_t size_in_pages);
+
+  bool special() const { return _special; }
+
+  // Initialization
+  G1PageBasedVirtualSpace();
+  bool initialize_with_granularity(ReservedSpace rs, size_t page_size);
+
+  // Destruction
+  ~G1PageBasedVirtualSpace();
+
+  // Amount of reserved memory.
+  size_t reserved_size() const;
+  // Memory used in this virtual space.
+  size_t committed_size() const;
+  // Memory left to use/expand in this virtual space.
+  size_t uncommitted_size() const;
+
+  bool contains(const void* p) const;
+
+  MemRegion reserved() {
+    MemRegion x((HeapWord*)_low_boundary, reserved_size() / HeapWordSize);
+    return x;
+  }
+
+  void release();
+
+  void check_for_contiguity() PRODUCT_RETURN;
+
+  // Debugging
+  void print_on(outputStream* out) PRODUCT_RETURN;
+  void print();
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1PAGEBASEDVIRTUALSPACE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp
new file mode 100644
index 0000000..bf5824f
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/g1OopClosures.inline.hpp"
+#include "gc_implementation/g1/g1ParScanThreadState.inline.hpp"
+#include "oops/oop.inline.hpp"
+#include "oops/oop.pcgc.inline.hpp"
+#include "runtime/prefetch.inline.hpp"
+
+G1ParScanThreadState::G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp)
+  : _g1h(g1h),
+    _refs(g1h->task_queue(queue_num)),
+    _dcq(&g1h->dirty_card_queue_set()),
+    _ct_bs(g1h->g1_barrier_set()),
+    _g1_rem(g1h->g1_rem_set()),
+    _hash_seed(17), _queue_num(queue_num),
+    _term_attempts(0),
+    _surviving_alloc_buffer(g1h->desired_plab_sz(GCAllocForSurvived)),
+    _tenured_alloc_buffer(g1h->desired_plab_sz(GCAllocForTenured)),
+    _age_table(false), _scanner(g1h, rp),
+    _strong_roots_time(0), _term_time(0),
+    _alloc_buffer_waste(0), _undo_waste(0) {
+  _scanner.set_par_scan_thread_state(this);
+  // we allocate G1YoungSurvRateNumRegions plus one entries, since
+  // we "sacrifice" entry 0 to keep track of surviving bytes for
+  // non-young regions (where the age is -1)
+  // We also add a few elements at the beginning and at the end in
+  // an attempt to eliminate cache contention
+  uint real_length = 1 + _g1h->g1_policy()->young_cset_region_length();
+  uint array_length = PADDING_ELEM_NUM +
+                      real_length +
+                      PADDING_ELEM_NUM;
+  _surviving_young_words_base = NEW_C_HEAP_ARRAY(size_t, array_length, mtGC);
+  if (_surviving_young_words_base == NULL)
+    vm_exit_out_of_memory(array_length * sizeof(size_t), OOM_MALLOC_ERROR,
+                          "Not enough space for young surv histo.");
+  _surviving_young_words = _surviving_young_words_base + PADDING_ELEM_NUM;
+  memset(_surviving_young_words, 0, (size_t) real_length * sizeof(size_t));
+
+  _alloc_buffers[GCAllocForSurvived] = &_surviving_alloc_buffer;
+  _alloc_buffers[GCAllocForTenured]  = &_tenured_alloc_buffer;
+
+  _start = os::elapsedTime();
+}
+
+G1ParScanThreadState::~G1ParScanThreadState() {
+  retire_alloc_buffers();
+  FREE_C_HEAP_ARRAY(size_t, _surviving_young_words_base, mtGC);
+}
+
+void
+G1ParScanThreadState::print_termination_stats_hdr(outputStream* const st)
+{
+  st->print_raw_cr("GC Termination Stats");
+  st->print_raw_cr("     elapsed  --strong roots-- -------termination-------"
+                   " ------waste (KiB)------");
+  st->print_raw_cr("thr     ms        ms      %        ms      %    attempts"
+                   "  total   alloc    undo");
+  st->print_raw_cr("--- --------- --------- ------ --------- ------ --------"
+                   " ------- ------- -------");
+}
+
+void
+G1ParScanThreadState::print_termination_stats(int i,
+                                              outputStream* const st) const
+{
+  const double elapsed_ms = elapsed_time() * 1000.0;
+  const double s_roots_ms = strong_roots_time() * 1000.0;
+  const double term_ms    = term_time() * 1000.0;
+  st->print_cr("%3d %9.2f %9.2f %6.2f "
+               "%9.2f %6.2f " SIZE_FORMAT_W(8) " "
+               SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7) " " SIZE_FORMAT_W(7),
+               i, elapsed_ms, s_roots_ms, s_roots_ms * 100 / elapsed_ms,
+               term_ms, term_ms * 100 / elapsed_ms, term_attempts(),
+               (alloc_buffer_waste() + undo_waste()) * HeapWordSize / K,
+               alloc_buffer_waste() * HeapWordSize / K,
+               undo_waste() * HeapWordSize / K);
+}
+
+#ifdef ASSERT
+bool G1ParScanThreadState::verify_ref(narrowOop* ref) const {
+  assert(ref != NULL, "invariant");
+  assert(UseCompressedOops, "sanity");
+  assert(!has_partial_array_mask(ref), err_msg("ref=" PTR_FORMAT, p2i(ref)));
+  oop p = oopDesc::load_decode_heap_oop(ref);
+  assert(_g1h->is_in_g1_reserved(p),
+         err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));
+  return true;
+}
+
+bool G1ParScanThreadState::verify_ref(oop* ref) const {
+  assert(ref != NULL, "invariant");
+  if (has_partial_array_mask(ref)) {
+    // Must be in the collection set--it's already been copied.
+    oop p = clear_partial_array_mask(ref);
+    assert(_g1h->obj_in_cs(p),
+           err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));
+  } else {
+    oop p = oopDesc::load_decode_heap_oop(ref);
+    assert(_g1h->is_in_g1_reserved(p),
+           err_msg("ref=" PTR_FORMAT " p=" PTR_FORMAT, p2i(ref), p2i(p)));
+  }
+  return true;
+}
+
+bool G1ParScanThreadState::verify_task(StarTask ref) const {
+  if (ref.is_narrow()) {
+    return verify_ref((narrowOop*) ref);
+  } else {
+    return verify_ref((oop*) ref);
+  }
+}
+#endif // ASSERT
+
+void G1ParScanThreadState::trim_queue() {
+  assert(_evac_failure_cl != NULL, "not set");
+
+  StarTask ref;
+  do {
+    // Drain the overflow stack first, so other threads can steal.
+    while (_refs->pop_overflow(ref)) {
+      dispatch_reference(ref);
+    }
+
+    while (_refs->pop_local(ref)) {
+      dispatch_reference(ref);
+    }
+  } while (!_refs->is_empty());
+}
+
+oop G1ParScanThreadState::copy_to_survivor_space(oop const old) {
+  size_t word_sz = old->size();
+  HeapRegion* from_region = _g1h->heap_region_containing_raw(old);
+  // +1 to make the -1 indexes valid...
+  int       young_index = from_region->young_index_in_cset()+1;
+  assert( (from_region->is_young() && young_index >  0) ||
+         (!from_region->is_young() && young_index == 0), "invariant" );
+  G1CollectorPolicy* g1p = _g1h->g1_policy();
+  markOop m = old->mark();
+  int age = m->has_displaced_mark_helper() ? m->displaced_mark_helper()->age()
+                                           : m->age();
+  GCAllocPurpose alloc_purpose = g1p->evacuation_destination(from_region, age,
+                                                             word_sz);
+  HeapWord* obj_ptr = allocate(alloc_purpose, word_sz);
+#ifndef PRODUCT
+  // Should this evacuation fail?
+  if (_g1h->evacuation_should_fail()) {
+    if (obj_ptr != NULL) {
+      undo_allocation(alloc_purpose, obj_ptr, word_sz);
+      obj_ptr = NULL;
+    }
+  }
+#endif // !PRODUCT
+
+  if (obj_ptr == NULL) {
+    // This will either forward-to-self, or detect that someone else has
+    // installed a forwarding pointer.
+    return _g1h->handle_evacuation_failure_par(this, old);
+  }
+
+  oop obj = oop(obj_ptr);
+
+  // We're going to allocate linearly, so might as well prefetch ahead.
+  Prefetch::write(obj_ptr, PrefetchCopyIntervalInBytes);
+
+  oop forward_ptr = old->forward_to_atomic(obj);
+  if (forward_ptr == NULL) {
+    Copy::aligned_disjoint_words((HeapWord*) old, obj_ptr, word_sz);
+
+    // alloc_purpose is just a hint to allocate() above, recheck the type of region
+    // we actually allocated from and update alloc_purpose accordingly
+    HeapRegion* to_region = _g1h->heap_region_containing_raw(obj_ptr);
+    alloc_purpose = to_region->is_young() ? GCAllocForSurvived : GCAllocForTenured;
+
+    if (g1p->track_object_age(alloc_purpose)) {
+      // We could simply do obj->incr_age(). However, this causes a
+      // performance issue. obj->incr_age() will first check whether
+      // the object has a displaced mark by checking its mark word;
+      // getting the mark word from the new location of the object
+      // stalls. So, given that we already have the mark word and we
+      // are about to install it anyway, it's better to increase the
+      // age on the mark word, when the object does not have a
+      // displaced mark word. We're not expecting many objects to have
+      // a displaced marked word, so that case is not optimized
+      // further (it could be...) and we simply call obj->incr_age().
+
+      if (m->has_displaced_mark_helper()) {
+        // in this case, we have to install the mark word first,
+        // otherwise obj looks to be forwarded (the old mark word,
+        // which contains the forward pointer, was copied)
+        obj->set_mark(m);
+        obj->incr_age();
+      } else {
+        m = m->incr_age();
+        obj->set_mark(m);
+      }
+      age_table()->add(obj, word_sz);
+    } else {
+      obj->set_mark(m);
+    }
+
+    if (G1StringDedup::is_enabled()) {
+      G1StringDedup::enqueue_from_evacuation(from_region->is_young(),
+                                             to_region->is_young(),
+                                             queue_num(),
+                                             obj);
+    }
+
+    size_t* surv_young_words = surviving_young_words();
+    surv_young_words[young_index] += word_sz;
+
+    if (obj->is_objArray() && arrayOop(obj)->length() >= ParGCArrayScanChunk) {
+      // We keep track of the next start index in the length field of
+      // the to-space object. The actual length can be found in the
+      // length field of the from-space object.
+      arrayOop(obj)->set_length(0);
+      oop* old_p = set_partial_array_mask(old);
+      push_on_queue(old_p);
+    } else {
+      // No point in using the slower heap_region_containing() method,
+      // given that we know obj is in the heap.
+      _scanner.set_region(_g1h->heap_region_containing_raw(obj));
+      obj->oop_iterate_backwards(&_scanner);
+    }
+  } else {
+    undo_allocation(alloc_purpose, obj_ptr, word_sz);
+    obj = forward_ptr;
+  }
+  return obj;
+}
+
+HeapWord* G1ParScanThreadState::allocate_slow(GCAllocPurpose purpose, size_t word_sz) {
+  HeapWord* obj = NULL;
+  size_t gclab_word_size = _g1h->desired_plab_sz(purpose);
+  if (word_sz * 100 < gclab_word_size * ParallelGCBufferWastePct) {
+    G1ParGCAllocBuffer* alloc_buf = alloc_buffer(purpose);
+    add_to_alloc_buffer_waste(alloc_buf->words_remaining());
+    alloc_buf->retire(false /* end_of_gc */, false /* retain */);
+
+    HeapWord* buf = _g1h->par_allocate_during_gc(purpose, gclab_word_size);
+    if (buf == NULL) {
+      return NULL; // Let caller handle allocation failure.
+    }
+    // Otherwise.
+    alloc_buf->set_word_size(gclab_word_size);
+    alloc_buf->set_buf(buf);
+
+    obj = alloc_buf->allocate(word_sz);
+    assert(obj != NULL, "buffer was definitely big enough...");
+  } else {
+    obj = _g1h->par_allocate_during_gc(purpose, word_sz);
+  }
+  return obj;
+}
+
+void G1ParScanThreadState::undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz) {
+  if (alloc_buffer(purpose)->contains(obj)) {
+    assert(alloc_buffer(purpose)->contains(obj + word_sz - 1),
+           "should contain whole object");
+    alloc_buffer(purpose)->undo_allocation(obj, word_sz);
+  } else {
+    CollectedHeap::fill_with_object(obj, word_sz);
+    add_to_undo_waste(word_sz);
+  }
+}
+
+HeapWord* G1ParScanThreadState::allocate(GCAllocPurpose purpose, size_t word_sz) {
+  HeapWord* obj = NULL;
+  if (purpose == GCAllocForSurvived) {
+    obj = alloc_buffer(GCAllocForSurvived)->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
+  } else {
+    obj = alloc_buffer(GCAllocForTenured)->allocate(word_sz);
+  }
+  if (obj != NULL) {
+    return obj;
+  }
+  return allocate_slow(purpose, word_sz);
+}
+
+void G1ParScanThreadState::retire_alloc_buffers() {
+  for (int ap = 0; ap < GCAllocPurposeCount; ++ap) {
+    size_t waste = _alloc_buffers[ap]->words_remaining();
+    add_to_alloc_buffer_waste(waste);
+    _alloc_buffers[ap]->flush_stats_and_retire(_g1h->stats_for_purpose((GCAllocPurpose)ap),
+                                               true /* end_of_gc */,
+                                               false /* retain */);
+  }
+}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp
new file mode 100644
index 0000000..e590a9e
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.hpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP
+
+#include "gc_implementation/g1/dirtyCardQueue.hpp"
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.hpp"
+#include "gc_implementation/g1/g1CollectorPolicy.hpp"
+#include "gc_implementation/g1/g1OopClosures.hpp"
+#include "gc_implementation/g1/g1RemSet.hpp"
+#include "gc_implementation/shared/ageTable.hpp"
+#include "memory/allocation.hpp"
+#include "oops/oop.hpp"
+
+class HeapRegion;
+class outputStream;
+
+class G1ParScanThreadState : public StackObj {
+ private:
+  G1CollectedHeap* _g1h;
+  RefToScanQueue*  _refs;
+  DirtyCardQueue   _dcq;
+  G1SATBCardTableModRefBS* _ct_bs;
+  G1RemSet* _g1_rem;
+
+  G1ParGCAllocBuffer  _surviving_alloc_buffer;
+  G1ParGCAllocBuffer  _tenured_alloc_buffer;
+  G1ParGCAllocBuffer* _alloc_buffers[GCAllocPurposeCount];
+  ageTable            _age_table;
+
+  G1ParScanClosure    _scanner;
+
+  size_t           _alloc_buffer_waste;
+  size_t           _undo_waste;
+
+  OopsInHeapRegionClosure*      _evac_failure_cl;
+
+  int  _hash_seed;
+  uint _queue_num;
+
+  size_t _term_attempts;
+
+  double _start;
+  double _start_strong_roots;
+  double _strong_roots_time;
+  double _start_term;
+  double _term_time;
+
+  // Map from young-age-index (0 == not young, 1 is youngest) to
+  // surviving words. base is what we get back from the malloc call
+  size_t* _surviving_young_words_base;
+  // this points into the array, as we use the first few entries for padding
+  size_t* _surviving_young_words;
+
+#define PADDING_ELEM_NUM (DEFAULT_CACHE_LINE_SIZE / sizeof(size_t))
+
+  void   add_to_alloc_buffer_waste(size_t waste) { _alloc_buffer_waste += waste; }
+
+  void   add_to_undo_waste(size_t waste)         { _undo_waste += waste; }
+
+  DirtyCardQueue& dirty_card_queue()             { return _dcq;  }
+  G1SATBCardTableModRefBS* ctbs()                { return _ct_bs; }
+
+  template <class T> inline void immediate_rs_update(HeapRegion* from, T* p, int tid);
+
+  template <class T> void deferred_rs_update(HeapRegion* from, T* p, int tid) {
+    // If the new value of the field points to the same region or
+    // is the to-space, we don't need to include it in the Rset updates.
+    if (!from->is_in_reserved(oopDesc::load_decode_heap_oop(p)) && !from->is_survivor()) {
+      size_t card_index = ctbs()->index_for(p);
+      // If the card hasn't been added to the buffer, do it.
+      if (ctbs()->mark_card_deferred(card_index)) {
+        dirty_card_queue().enqueue((jbyte*)ctbs()->byte_for_index(card_index));
+      }
+    }
+  }
+
+ public:
+  G1ParScanThreadState(G1CollectedHeap* g1h, uint queue_num, ReferenceProcessor* rp);
+  ~G1ParScanThreadState();
+
+  ageTable*         age_table()       { return &_age_table;       }
+
+  G1ParGCAllocBuffer* alloc_buffer(GCAllocPurpose purpose) {
+    return _alloc_buffers[purpose];
+  }
+
+  size_t alloc_buffer_waste() const              { return _alloc_buffer_waste; }
+  size_t undo_waste() const                      { return _undo_waste; }
+
+#ifdef ASSERT
+  bool queue_is_empty() const { return _refs->is_empty(); }
+
+  bool verify_ref(narrowOop* ref) const;
+  bool verify_ref(oop* ref) const;
+  bool verify_task(StarTask ref) const;
+#endif // ASSERT
+
+  template <class T> void push_on_queue(T* ref) {
+    assert(verify_ref(ref), "sanity");
+    _refs->push(ref);
+  }
+
+  template <class T> inline void update_rs(HeapRegion* from, T* p, int tid);
+
+ private:
+
+  inline HeapWord* allocate(GCAllocPurpose purpose, size_t word_sz);
+  inline HeapWord* allocate_slow(GCAllocPurpose purpose, size_t word_sz);
+  inline void undo_allocation(GCAllocPurpose purpose, HeapWord* obj, size_t word_sz);
+
+ public:
+
+  void set_evac_failure_closure(OopsInHeapRegionClosure* evac_failure_cl) {
+    _evac_failure_cl = evac_failure_cl;
+  }
+
+  OopsInHeapRegionClosure* evac_failure_closure() { return _evac_failure_cl; }
+
+  int* hash_seed() { return &_hash_seed; }
+  uint queue_num() { return _queue_num; }
+
+  size_t term_attempts() const  { return _term_attempts; }
+  void note_term_attempt() { _term_attempts++; }
+
+  void start_strong_roots() {
+    _start_strong_roots = os::elapsedTime();
+  }
+  void end_strong_roots() {
+    _strong_roots_time += (os::elapsedTime() - _start_strong_roots);
+  }
+  double strong_roots_time() const { return _strong_roots_time; }
+
+  void start_term_time() {
+    note_term_attempt();
+    _start_term = os::elapsedTime();
+  }
+  void end_term_time() {
+    _term_time += (os::elapsedTime() - _start_term);
+  }
+  double term_time() const { return _term_time; }
+
+  double elapsed_time() const {
+    return os::elapsedTime() - _start;
+  }
+
+  static void print_termination_stats_hdr(outputStream* const st = gclog_or_tty);
+  void print_termination_stats(int i, outputStream* const st = gclog_or_tty) const;
+
+  size_t* surviving_young_words() {
+    // We add on to hide entry 0 which accumulates surviving words for
+    // age -1 regions (i.e. non-young ones)
+    return _surviving_young_words;
+  }
+
+ private:
+  void retire_alloc_buffers();
+
+  #define G1_PARTIAL_ARRAY_MASK 0x2
+
+  inline bool has_partial_array_mask(oop* ref) const {
+    return ((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) == G1_PARTIAL_ARRAY_MASK;
+  }
+
+  // We never encode partial array oops as narrowOop*, so return false immediately.
+  // This allows the compiler to create optimized code when popping references from
+  // the work queue.
+  inline bool has_partial_array_mask(narrowOop* ref) const {
+    assert(((uintptr_t)ref & G1_PARTIAL_ARRAY_MASK) != G1_PARTIAL_ARRAY_MASK, "Partial array oop reference encoded as narrowOop*");
+    return false;
+  }
+
+  // Only implement set_partial_array_mask() for regular oops, not for narrowOops.
+  // We always encode partial arrays as regular oop, to allow the
+  // specialization for has_partial_array_mask() for narrowOops above.
+  // This means that unintentional use of this method with narrowOops are caught
+  // by the compiler.
+  inline oop* set_partial_array_mask(oop obj) const {
+    assert(((uintptr_t)(void *)obj & G1_PARTIAL_ARRAY_MASK) == 0, "Information loss!");
+    return (oop*) ((uintptr_t)(void *)obj | G1_PARTIAL_ARRAY_MASK);
+  }
+
+  inline oop clear_partial_array_mask(oop* ref) const {
+    return cast_to_oop((intptr_t)ref & ~G1_PARTIAL_ARRAY_MASK);
+  }
+
+  inline void do_oop_partial_array(oop* p);
+
+  // This method is applied to the fields of the objects that have just been copied.
+  template <class T> inline void do_oop_evac(T* p, HeapRegion* from);
+
+  template <class T> inline void deal_with_reference(T* ref_to_scan);
+
+  inline void dispatch_reference(StarTask ref);
+ public:
+
+  oop copy_to_survivor_space(oop const obj);
+
+  void trim_queue();
+
+  inline void steal_and_trim_queue(RefToScanQueueSet *task_queues);
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp
new file mode 100644
index 0000000..75517fb
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1ParScanThreadState.inline.hpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_INLINE_HPP
+
+#include "gc_implementation/g1/g1ParScanThreadState.hpp"
+#include "gc_implementation/g1/g1RemSet.inline.hpp"
+#include "oops/oop.inline.hpp"
+
+template <class T> inline void G1ParScanThreadState::immediate_rs_update(HeapRegion* from, T* p, int tid) {
+  if (!from->is_survivor()) {
+    _g1_rem->par_write_ref(from, p, tid);
+  }
+}
+
+template <class T> void G1ParScanThreadState::update_rs(HeapRegion* from, T* p, int tid) {
+  if (G1DeferredRSUpdate) {
+    deferred_rs_update(from, p, tid);
+  } else {
+    immediate_rs_update(from, p, tid);
+  }
+}
+
+template <class T> void G1ParScanThreadState::do_oop_evac(T* p, HeapRegion* from) {
+  assert(!oopDesc::is_null(oopDesc::load_decode_heap_oop(p)),
+         "Reference should not be NULL here as such are never pushed to the task queue.");
+  oop obj = oopDesc::load_decode_heap_oop_not_null(p);
+
+  // Although we never intentionally push references outside of the collection
+  // set, due to (benign) races in the claim mechanism during RSet scanning more
+  // than one thread might claim the same card. So the same card may be
+  // processed multiple times. So redo this check.
+  G1CollectedHeap::in_cset_state_t in_cset_state = _g1h->in_cset_state(obj);
+  if (in_cset_state == G1CollectedHeap::InCSet) {
+    oop forwardee;
+    if (obj->is_forwarded()) {
+      forwardee = obj->forwardee();
+    } else {
+      forwardee = copy_to_survivor_space(obj);
+    }
+    oopDesc::encode_store_heap_oop(p, forwardee);
+  } else if (in_cset_state == G1CollectedHeap::IsHumongous) {
+    _g1h->set_humongous_is_live(obj);
+  } else {
+    assert(in_cset_state == G1CollectedHeap::InNeither,
+           err_msg("In_cset_state must be InNeither here, but is %d", in_cset_state));
+  }
+
+  assert(obj != NULL, "Must be");
+  update_rs(from, p, queue_num());
+}
+
+inline void G1ParScanThreadState::do_oop_partial_array(oop* p) {
+  assert(has_partial_array_mask(p), "invariant");
+  oop from_obj = clear_partial_array_mask(p);
+
+  assert(Universe::heap()->is_in_reserved(from_obj), "must be in heap.");
+  assert(from_obj->is_objArray(), "must be obj array");
+  objArrayOop from_obj_array = objArrayOop(from_obj);
+  // The from-space object contains the real length.
+  int length                 = from_obj_array->length();
+
+  assert(from_obj->is_forwarded(), "must be forwarded");
+  oop to_obj                 = from_obj->forwardee();
+  assert(from_obj != to_obj, "should not be chunking self-forwarded objects");
+  objArrayOop to_obj_array   = objArrayOop(to_obj);
+  // We keep track of the next start index in the length field of the
+  // to-space object.
+  int next_index             = to_obj_array->length();
+  assert(0 <= next_index && next_index < length,
+         err_msg("invariant, next index: %d, length: %d", next_index, length));
+
+  int start                  = next_index;
+  int end                    = length;
+  int remainder              = end - start;
+  // We'll try not to push a range that's smaller than ParGCArrayScanChunk.
+  if (remainder > 2 * ParGCArrayScanChunk) {
+    end = start + ParGCArrayScanChunk;
+    to_obj_array->set_length(end);
+    // Push the remainder before we process the range in case another
+    // worker has run out of things to do and can steal it.
+    oop* from_obj_p = set_partial_array_mask(from_obj);
+    push_on_queue(from_obj_p);
+  } else {
+    assert(length == end, "sanity");
+    // We'll process the final range for this object. Restore the length
+    // so that the heap remains parsable in case of evacuation failure.
+    to_obj_array->set_length(end);
+  }
+  _scanner.set_region(_g1h->heap_region_containing_raw(to_obj));
+  // Process indexes [start,end). It will also process the header
+  // along with the first chunk (i.e., the chunk with start == 0).
+  // Note that at this point the length field of to_obj_array is not
+  // correct given that we are using it to keep track of the next
+  // start index. oop_iterate_range() (thankfully!) ignores the length
+  // field and only relies on the start / end parameters.  It does
+  // however return the size of the object which will be incorrect. So
+  // we have to ignore it even if we wanted to use it.
+  to_obj_array->oop_iterate_range(&_scanner, start, end);
+}
+
+template <class T> inline void G1ParScanThreadState::deal_with_reference(T* ref_to_scan) {
+  if (!has_partial_array_mask(ref_to_scan)) {
+    // Note: we can use "raw" versions of "region_containing" because
+    // "obj_to_scan" is definitely in the heap, and is not in a
+    // humongous region.
+    HeapRegion* r = _g1h->heap_region_containing_raw(ref_to_scan);
+    do_oop_evac(ref_to_scan, r);
+  } else {
+    do_oop_partial_array((oop*)ref_to_scan);
+  }
+}
+
+inline void G1ParScanThreadState::dispatch_reference(StarTask ref) {
+  assert(verify_task(ref), "sanity");
+  if (ref.is_narrow()) {
+    deal_with_reference((narrowOop*)ref);
+  } else {
+    deal_with_reference((oop*)ref);
+  }
+}
+
+void G1ParScanThreadState::steal_and_trim_queue(RefToScanQueueSet *task_queues) {
+  StarTask stolen_task;
+  while (task_queues->steal(queue_num(), hash_seed(), stolen_task)) {
+    assert(verify_task(stolen_task), "sanity");
+    dispatch_reference(stolen_task);
+
+    // We've just processed a reference and we might have made
+    // available new entries on the queues. So we have to make sure
+    // we drain the queues as necessary.
+    trim_queue();
+  }
+}
+
+#endif /* SHARE_VM_GC_IMPLEMENTATION_G1_G1PARSCANTHREADSTATE_INLINE_HPP */
+
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp
new file mode 100644
index 0000000..da0976c
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 2001, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/g1/g1BiasedArray.hpp"
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
+#include "memory/allocation.inline.hpp"
+#include "runtime/virtualspace.hpp"
+#include "services/memTracker.hpp"
+#include "utilities/bitMap.inline.hpp"
+
+G1RegionToSpaceMapper::G1RegionToSpaceMapper(ReservedSpace rs,
+                                             size_t commit_granularity,
+                                             size_t region_granularity,
+                                             MemoryType type) :
+  _storage(),
+  _commit_granularity(commit_granularity),
+  _region_granularity(region_granularity),
+  _listener(NULL),
+  _commit_map() {
+  guarantee(is_power_of_2(commit_granularity), "must be");
+  guarantee(is_power_of_2(region_granularity), "must be");
+  _storage.initialize_with_granularity(rs, commit_granularity);
+
+  MemTracker::record_virtual_memory_type((address)rs.base(), type);
+}
+
+// G1RegionToSpaceMapper implementation where the region granularity is larger than
+// or the same as the commit granularity.
+// Basically, the space corresponding to one region region spans several OS pages.
+class G1RegionsLargerThanCommitSizeMapper : public G1RegionToSpaceMapper {
+ private:
+  size_t _pages_per_region;
+
+ public:
+  G1RegionsLargerThanCommitSizeMapper(ReservedSpace rs,
+                                      size_t os_commit_granularity,
+                                      size_t alloc_granularity,
+                                      size_t commit_factor,
+                                      MemoryType type) :
+     G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
+    _pages_per_region(alloc_granularity / (os_commit_granularity * commit_factor)) {
+
+    guarantee(alloc_granularity >= os_commit_granularity, "allocation granularity smaller than commit granularity");
+    _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
+  }
+
+  virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
+    _storage.commit(start_idx * _pages_per_region, num_regions * _pages_per_region);
+    _commit_map.set_range(start_idx, start_idx + num_regions);
+    fire_on_commit(start_idx, num_regions);
+  }
+
+  virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
+    _storage.uncommit(start_idx * _pages_per_region, num_regions * _pages_per_region);
+    _commit_map.clear_range(start_idx, start_idx + num_regions);
+  }
+};
+
+// G1RegionToSpaceMapper implementation where the region granularity is smaller
+// than the commit granularity.
+// Basically, the contents of one OS page span several regions.
+class G1RegionsSmallerThanCommitSizeMapper : public G1RegionToSpaceMapper {
+ private:
+  class CommitRefcountArray : public G1BiasedMappedArray<uint> {
+   protected:
+     virtual uint default_value() const { return 0; }
+  };
+
+  size_t _regions_per_page;
+
+  CommitRefcountArray _refcounts;
+
+  uintptr_t region_idx_to_page_idx(uint region) const {
+    return region / _regions_per_page;
+  }
+
+ public:
+  G1RegionsSmallerThanCommitSizeMapper(ReservedSpace rs,
+                                       size_t os_commit_granularity,
+                                       size_t alloc_granularity,
+                                       size_t commit_factor,
+                                       MemoryType type) :
+     G1RegionToSpaceMapper(rs, os_commit_granularity, alloc_granularity, type),
+    _regions_per_page((os_commit_granularity * commit_factor) / alloc_granularity), _refcounts() {
+
+    guarantee((os_commit_granularity * commit_factor) >= alloc_granularity, "allocation granularity smaller than commit granularity");
+    _refcounts.initialize((HeapWord*)rs.base(), (HeapWord*)(rs.base() + rs.size()), os_commit_granularity);
+    _commit_map.resize(rs.size() * commit_factor / alloc_granularity, /* in_resource_area */ false);
+  }
+
+  virtual void commit_regions(uintptr_t start_idx, size_t num_regions) {
+    for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
+      assert(!_commit_map.at(i), err_msg("Trying to commit storage at region "INTPTR_FORMAT" that is already committed", i));
+      uintptr_t idx = region_idx_to_page_idx(i);
+      uint old_refcount = _refcounts.get_by_index(idx);
+      if (old_refcount == 0) {
+        _storage.commit(idx, 1);
+      }
+      _refcounts.set_by_index(idx, old_refcount + 1);
+      _commit_map.set_bit(i);
+      fire_on_commit(i, 1);
+    }
+  }
+
+  virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions) {
+    for (uintptr_t i = start_idx; i < start_idx + num_regions; i++) {
+      assert(_commit_map.at(i), err_msg("Trying to uncommit storage at region "INTPTR_FORMAT" that is not committed", i));
+      uintptr_t idx = region_idx_to_page_idx(i);
+      uint old_refcount = _refcounts.get_by_index(idx);
+      assert(old_refcount > 0, "must be");
+      if (old_refcount == 1) {
+        _storage.uncommit(idx, 1);
+      }
+      _refcounts.set_by_index(idx, old_refcount - 1);
+      _commit_map.clear_bit(i);
+    }
+  }
+};
+
+void G1RegionToSpaceMapper::fire_on_commit(uint start_idx, size_t num_regions) {
+  if (_listener != NULL) {
+    _listener->on_commit(start_idx, num_regions);
+  }
+}
+
+G1RegionToSpaceMapper* G1RegionToSpaceMapper::create_mapper(ReservedSpace rs,
+                                                            size_t os_commit_granularity,
+                                                            size_t region_granularity,
+                                                            size_t commit_factor,
+                                                            MemoryType type) {
+
+  if (region_granularity >= (os_commit_granularity * commit_factor)) {
+    return new G1RegionsLargerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
+  } else {
+    return new G1RegionsSmallerThanCommitSizeMapper(rs, os_commit_granularity, region_granularity, commit_factor, type);
+  }
+}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp
new file mode 100644
index 0000000..5f614b7
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RegionToSpaceMapper.hpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1REGIONTOSPACEMAPPER_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_G1_G1REGIONTOSPACEMAPPER_HPP
+
+#include "gc_implementation/g1/g1PageBasedVirtualSpace.hpp"
+#include "memory/allocation.hpp"
+#include "utilities/debug.hpp"
+
+class G1MappingChangedListener VALUE_OBJ_CLASS_SPEC {
+ public:
+  // Fired after commit of the memory, i.e. the memory this listener is registered
+  // for can be accessed.
+  virtual void on_commit(uint start_idx, size_t num_regions) = 0;
+};
+
+// Maps region based commit/uncommit requests to the underlying page sized virtual
+// space.
+class G1RegionToSpaceMapper : public CHeapObj<mtGC> {
+ private:
+  G1MappingChangedListener* _listener;
+ protected:
+  // Backing storage.
+  G1PageBasedVirtualSpace _storage;
+  size_t _commit_granularity;
+  size_t _region_granularity;
+  // Mapping management
+  BitMap _commit_map;
+
+  G1RegionToSpaceMapper(ReservedSpace rs, size_t commit_granularity, size_t region_granularity, MemoryType type);
+
+  void fire_on_commit(uint start_idx, size_t num_regions);
+ public:
+  MemRegion reserved() { return _storage.reserved(); }
+
+  void set_mapping_changed_listener(G1MappingChangedListener* listener) { _listener = listener; }
+
+  virtual ~G1RegionToSpaceMapper() {
+    _commit_map.resize(0, /* in_resource_area */ false);
+  }
+
+  bool is_committed(uintptr_t idx) const {
+    return _commit_map.at(idx);
+  }
+
+  virtual void commit_regions(uintptr_t start_idx, size_t num_regions = 1) = 0;
+  virtual void uncommit_regions(uintptr_t start_idx, size_t num_regions = 1) = 0;
+
+  // Creates an appropriate G1RegionToSpaceMapper for the given parameters.
+  // The byte_translation_factor defines how many bytes in a region correspond to
+  // a single byte in the data structure this mapper is for.
+  // Eg. in the card table, this value corresponds to the size a single card
+  // table entry corresponds to.
+  static G1RegionToSpaceMapper* create_mapper(ReservedSpace rs,
+                                              size_t os_commit_granularity,
+                                              size_t region_granularity,
+                                              size_t byte_translation_factor,
+                                              MemoryType type);
+};
+
+#endif /* SHARE_VM_GC_IMPLEMENTATION_G1_G1REGIONTOSPACEMAPPER_HPP */
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
index 5877f0a..e79936e 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.cpp
@@ -23,7 +23,6 @@
  */
 
 #include "precompiled.hpp"
-#include "gc_implementation/g1/bufferingOopClosure.hpp"
 #include "gc_implementation/g1/concurrentG1Refine.hpp"
 #include "gc_implementation/g1/concurrentG1RefineThread.hpp"
 #include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
@@ -212,7 +211,6 @@
 #endif
 
       HeapRegion* card_region = _g1h->heap_region_containing(card_start);
-      assert(card_region != NULL, "Yielding cards not in the heap?");
       _cards++;
 
       if (!card_region->is_on_dirty_cards_region_list()) {
@@ -407,7 +405,6 @@
     HeapWord* start = _ct_bs->addr_for(card_ptr);
     // And find the region containing it.
     HeapRegion* r = _g1->heap_region_containing(start);
-    assert(r != NULL, "unexpected null");
 
     // Scan oops in the card looking for references into the collection set
     // Don't use addr_for(card_ptr + 1) which can ask for
@@ -557,6 +554,12 @@
 
 bool G1RemSet::refine_card(jbyte* card_ptr, uint worker_i,
                            bool check_for_refs_into_cset) {
+  assert(_g1->is_in_exact(_ct_bs->addr_for(card_ptr)),
+         err_msg("Card at "PTR_FORMAT" index "SIZE_FORMAT" representing heap at "PTR_FORMAT" (%u) must be in committed heap",
+                 p2i(card_ptr),
+                 _ct_bs->index_for(_ct_bs->addr_for(card_ptr)),
+                 _ct_bs->addr_for(card_ptr),
+                 _g1->addr_to_region(_ct_bs->addr_for(card_ptr))));
 
   // If the card is no longer dirty, nothing to do.
   if (*card_ptr != CardTableModRefBS::dirty_card_val()) {
@@ -569,11 +572,6 @@
   HeapWord* start = _ct_bs->addr_for(card_ptr);
   // And find the region containing it.
   HeapRegion* r = _g1->heap_region_containing(start);
-  if (r == NULL) {
-    // Again no need to return that this card contains refs that
-    // point into the collection set.
-    return false;  // Not in the G1 heap (might be in perm, for example.)
-  }
 
   // Why do we have to check here whether a card is on a young region,
   // given that we dirty young regions and, as a result, the
@@ -626,10 +624,6 @@
 
     start = _ct_bs->addr_for(card_ptr);
     r = _g1->heap_region_containing(start);
-    if (r == NULL) {
-      // Not in the G1 heap
-      return false;
-    }
 
     // Checking whether the region we got back from the cache
     // is young here is inappropriate. The region could have been
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp
index 440e37e..81e8559 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp
index 79f4df9..949614b 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1RemSet.inline.hpp
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1REMSET_INLINE_HPP
 
 #include "gc_implementation/g1/g1RemSet.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "oops/oop.inline.hpp"
 
@@ -45,26 +46,28 @@
 template <class T>
 inline void G1RemSet::par_write_ref(HeapRegion* from, T* p, int tid) {
   oop obj = oopDesc::load_decode_heap_oop(p);
+  if (obj == NULL) {
+    return;
+  }
+
 #ifdef ASSERT
   // can't do because of races
   // assert(obj == NULL || obj->is_oop(), "expected an oop");
 
   // Do the safe subset of is_oop
-  if (obj != NULL) {
 #ifdef CHECK_UNHANDLED_OOPS
-    oopDesc* o = obj.obj();
+  oopDesc* o = obj.obj();
 #else
-    oopDesc* o = obj;
+  oopDesc* o = obj;
 #endif // CHECK_UNHANDLED_OOPS
-    assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
-    assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
-  }
+  assert((intptr_t)o % MinObjAlignmentInBytes == 0, "not oop aligned");
+  assert(Universe::heap()->is_in_reserved(obj), "must be in heap");
 #endif // ASSERT
 
   assert(from == NULL || from->is_in_reserved(p), "p is not in from");
 
   HeapRegion* to = _g1->heap_region_containing(obj);
-  if (to != NULL && from != to) {
+  if (from != to) {
     assert(to->rem_set() != NULL, "Need per-region 'into' remsets.");
     to->rem_set()->add_reference(p, tid);
   }
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp
index 7382be2..26c8829 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.cpp
@@ -23,10 +23,12 @@
  */
 
 #include "precompiled.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/satbQueue.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/thread.inline.hpp"
 
 G1SATBCardTableModRefBS::G1SATBCardTableModRefBS(MemRegion whole_heap,
@@ -36,7 +38,6 @@
   _kind = G1SATBCT;
 }
 
-
 void G1SATBCardTableModRefBS::enqueue(oop pre_val) {
   // Nulls should have been already filtered.
   assert(pre_val->is_oop(true), "Error");
@@ -64,6 +65,17 @@
   }
 }
 
+void G1SATBCardTableModRefBS::write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
+  if (!dest_uninitialized) {
+    write_ref_array_pre_work(dst, count);
+  }
+}
+void G1SATBCardTableModRefBS::write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
+  if (!dest_uninitialized) {
+    write_ref_array_pre_work(dst, count);
+  }
+}
+
 bool G1SATBCardTableModRefBS::mark_card_deferred(size_t card_index) {
   jbyte val = _byte_map[card_index];
   // It's already processed
@@ -112,13 +124,52 @@
 }
 #endif
 
+void G1SATBCardTableLoggingModRefBSChangedListener::on_commit(uint start_idx, size_t num_regions) {
+  MemRegion mr(G1CollectedHeap::heap()->bottom_addr_for_region(start_idx), num_regions * HeapRegion::GrainWords);
+  _card_table->clear(mr);
+}
+
 G1SATBCardTableLoggingModRefBS::
 G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
                                int max_covered_regions) :
   G1SATBCardTableModRefBS(whole_heap, max_covered_regions),
-  _dcqs(JavaThread::dirty_card_queue_set())
+  _dcqs(JavaThread::dirty_card_queue_set()),
+  _listener()
 {
   _kind = G1SATBCTLogging;
+  _listener.set_card_table(this);
+}
+
+void G1SATBCardTableLoggingModRefBS::initialize(G1RegionToSpaceMapper* mapper) {
+  mapper->set_mapping_changed_listener(&_listener);
+
+  _byte_map_size = mapper->reserved().byte_size();
+
+  _guard_index = cards_required(_whole_heap.word_size()) - 1;
+  _last_valid_index = _guard_index - 1;
+
+  HeapWord* low_bound  = _whole_heap.start();
+  HeapWord* high_bound = _whole_heap.end();
+
+  _cur_covered_regions = 1;
+  _covered[0] = _whole_heap;
+
+  _byte_map = (jbyte*) mapper->reserved().start();
+  byte_map_base = _byte_map - (uintptr_t(low_bound) >> card_shift);
+  assert(byte_for(low_bound) == &_byte_map[0], "Checking start of map");
+  assert(byte_for(high_bound-1) <= &_byte_map[_last_valid_index], "Checking end of map");
+
+  if (TraceCardTableModRefBS) {
+    gclog_or_tty->print_cr("G1SATBCardTableModRefBS::G1SATBCardTableModRefBS: ");
+    gclog_or_tty->print_cr("  "
+                  "  &_byte_map[0]: " INTPTR_FORMAT
+                  "  &_byte_map[_last_valid_index]: " INTPTR_FORMAT,
+                  p2i(&_byte_map[0]),
+                  p2i(&_byte_map[_last_valid_index]));
+    gclog_or_tty->print_cr("  "
+                  "  byte_map_base: " INTPTR_FORMAT,
+                  p2i(byte_map_base));
+  }
 }
 
 void
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp
index 99d49cc..f02c28c 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1SATBCARDTABLEMODREFBS_HPP
 
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
 #include "memory/cardTableModRefBS.hpp"
 #include "memory/memRegion.hpp"
 #include "oops/oop.inline.hpp"
@@ -33,6 +34,7 @@
 #if INCLUDE_ALL_GCS
 
 class DirtyCardQueueSet;
+class G1SATBCardTableLoggingModRefBS;
 
 // This barrier is specialized to use a logging barrier to support
 // snapshot-at-the-beginning marking.
@@ -86,16 +88,8 @@
   }
 
   template <class T> void write_ref_array_pre_work(T* dst, int count);
-  virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
-    if (!dest_uninitialized) {
-      write_ref_array_pre_work(dst, count);
-    }
-  }
-  virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
-    if (!dest_uninitialized) {
-      write_ref_array_pre_work(dst, count);
-    }
-  }
+  virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized);
+  virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized);
 
 /*
    Claimed and deferred bits are used together in G1 during the evacuation
@@ -134,18 +128,40 @@
     jbyte val = _byte_map[card_index];
     return (val & (clean_card_mask_val() | deferred_card_val())) == deferred_card_val();
   }
+};
 
+class G1SATBCardTableLoggingModRefBSChangedListener : public G1MappingChangedListener {
+ private:
+  G1SATBCardTableLoggingModRefBS* _card_table;
+ public:
+  G1SATBCardTableLoggingModRefBSChangedListener() : _card_table(NULL) { }
+
+  void set_card_table(G1SATBCardTableLoggingModRefBS* card_table) { _card_table = card_table; }
+
+  virtual void on_commit(uint start_idx, size_t num_regions);
 };
 
 // Adds card-table logging to the post-barrier.
 // Usual invariant: all dirty cards are logged in the DirtyCardQueueSet.
 class G1SATBCardTableLoggingModRefBS: public G1SATBCardTableModRefBS {
+  friend class G1SATBCardTableLoggingModRefBSChangedListener;
  private:
+  G1SATBCardTableLoggingModRefBSChangedListener _listener;
   DirtyCardQueueSet& _dcqs;
  public:
+  static size_t compute_size(size_t mem_region_size_in_words) {
+    size_t number_of_slots = (mem_region_size_in_words / card_size_in_words);
+    return ReservedSpace::allocation_align_size_up(number_of_slots);
+  }
+
   G1SATBCardTableLoggingModRefBS(MemRegion whole_heap,
                                  int max_covered_regions);
 
+  virtual void initialize() { }
+  virtual void initialize(G1RegionToSpaceMapper* mapper);
+
+  virtual void resize_covered_region(MemRegion new_region) { ShouldNotReachHere(); }
+
   bool is_a(BarrierSet::Name bsn) {
     return bsn == BarrierSet::G1SATBCTLogging ||
       G1SATBCardTableModRefBS::is_a(bsn);
@@ -162,8 +178,6 @@
 
   void write_region_work(MemRegion mr)    { invalidate(mr); }
   void write_ref_array_work(MemRegion mr) { invalidate(mr); }
-
-
 };
 
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
index 4a6dc27..e59efa7 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1StringDedupThread.cpp
@@ -77,38 +77,37 @@
       break;
     }
 
-    // Include this thread in safepoints
-    stsJoin();
+    {
+      // Include thread in safepoints
+      SuspendibleThreadSetJoiner sts;
 
-    stat.mark_exec();
+      stat.mark_exec();
 
-    // Process the queue
-    for (;;) {
-      oop java_string = G1StringDedupQueue::pop();
-      if (java_string == NULL) {
-        break;
+      // Process the queue
+      for (;;) {
+        oop java_string = G1StringDedupQueue::pop();
+        if (java_string == NULL) {
+          break;
+        }
+
+        G1StringDedupTable::deduplicate(java_string, stat);
+
+        // Safepoint this thread if needed
+        if (sts.should_yield()) {
+          stat.mark_block();
+          sts.yield();
+          stat.mark_unblock();
+        }
       }
 
-      G1StringDedupTable::deduplicate(java_string, stat);
+      G1StringDedupTable::trim_entry_cache();
 
-      // Safepoint this thread if needed
-      if (stsShouldYield()) {
-        stat.mark_block();
-        stsYield(NULL);
-        stat.mark_unblock();
-      }
+      stat.mark_done();
+
+      // Print statistics
+      total_stat.add(stat);
+      print(gclog_or_tty, stat, total_stat);
     }
-
-    G1StringDedupTable::trim_entry_cache();
-
-    stat.mark_done();
-
-    // Print statistics
-    total_stat.add(stat);
-    print(gclog_or_tty, stat, total_stat);
-
-    // Exclude this thread from safepoints
-    stsLeave();
   }
 
   terminate();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
index 6aa670e..a14d7f0 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_globals.hpp
@@ -289,6 +289,13 @@
           "The amount of code root chunks that should be kept at most "     \
           "as percentage of already allocated.")                            \
                                                                             \
+  experimental(bool, G1ReclaimDeadHumongousObjectsAtYoungGC, true,          \
+          "Try to reclaim dead large objects at every young GC.")           \
+                                                                            \
+  experimental(bool, G1TraceReclaimDeadHumongousObjectsAtYoungGC, false,    \
+          "Print some information about large object liveness "             \
+          "at every young GC.")                                             \
+                                                                            \
   experimental(uintx, G1OldCSetRegionThresholdPercent, 10,                  \
           "An upper bound for the number of old CSet regions expressed "    \
           "as a percentage of the heap size.")                              \
@@ -325,11 +332,14 @@
           "evacuation pauses")                                              \
                                                                             \
   diagnostic(bool, G1VerifyRSetsDuringFullGC, false,                        \
-             "If true, perform verification of each heap region's "         \
-             "remembered set when verifying the heap during a full GC.")    \
+          "If true, perform verification of each heap region's "            \
+          "remembered set when verifying the heap during a full GC.")       \
                                                                             \
   diagnostic(bool, G1VerifyHeapRegionCodeRoots, false,                      \
-             "Verify the code root lists attached to each heap region.")
+          "Verify the code root lists attached to each heap region.")       \
+                                                                            \
+  develop(bool, G1VerifyBitmaps, false,                                     \
+          "Verifies the consistency of the marking bitmaps")
 
 G1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG, DECLARE_MANAGEABLE_FLAG, DECLARE_PRODUCT_RW_FLAG)
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp
index 538ca44..309392c 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/g1_specialized_oop_closures.hpp
@@ -30,14 +30,21 @@
 // non-virtually, using a mechanism defined in this file.  Extend these
 // macros in the obvious way to add specializations for new closures.
 
-// Forward declarations.
 enum G1Barrier {
   G1BarrierNone,
   G1BarrierEvac,
   G1BarrierKlass
 };
 
-template<G1Barrier barrier, bool do_mark_object>
+enum G1Mark {
+  G1MarkNone,
+  G1MarkFromRoot,
+  G1MarkPromotedFromRoot
+};
+
+// Forward declarations.
+
+template<G1Barrier barrier, G1Mark do_mark_object>
 class G1ParCopyClosure;
 
 class G1ParScanClosure;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
index d06b27b..ee678b1 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp
@@ -30,9 +30,12 @@
 #include "gc_implementation/g1/heapRegion.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
+#include "gc_implementation/shared/liveRange.hpp"
 #include "memory/genOopClosures.inline.hpp"
 #include "memory/iterator.hpp"
+#include "memory/space.inline.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
@@ -46,7 +49,7 @@
                                  HeapRegion* hr, ExtendedOopClosure* cl,
                                  CardTableModRefBS::PrecisionStyle precision,
                                  FilterKind fk) :
-  ContiguousSpaceDCTOC(hr, cl, precision, NULL),
+  DirtyCardToOopClosure(hr, cl, precision, NULL),
   _hr(hr), _fk(fk), _g1(g1) { }
 
 FilterOutOfRegionClosure::FilterOutOfRegionClosure(HeapRegion* r,
@@ -58,7 +61,7 @@
                                HeapRegion* hr,
                                HeapWord* cur, HeapWord* top) {
   oop cur_oop = oop(cur);
-  int oop_size = cur_oop->size();
+  size_t oop_size = hr->block_size(cur);
   HeapWord* next_obj = cur + oop_size;
   while (next_obj < top) {
     // Keep filtering the remembered set.
@@ -69,25 +72,24 @@
     }
     cur = next_obj;
     cur_oop = oop(cur);
-    oop_size = cur_oop->size();
+    oop_size = hr->block_size(cur);
     next_obj = cur + oop_size;
   }
   return cur;
 }
 
-void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr,
-                                              HeapWord* bottom,
-                                              HeapWord* top,
-                                              ExtendedOopClosure* cl) {
+void HeapRegionDCTOC::walk_mem_region(MemRegion mr,
+                                      HeapWord* bottom,
+                                      HeapWord* top) {
   G1CollectedHeap* g1h = _g1;
-  int oop_size;
+  size_t oop_size;
   ExtendedOopClosure* cl2 = NULL;
 
-  FilterIntoCSClosure intoCSFilt(this, g1h, cl);
-  FilterOutOfRegionClosure outOfRegionFilt(_hr, cl);
+  FilterIntoCSClosure intoCSFilt(this, g1h, _cl);
+  FilterOutOfRegionClosure outOfRegionFilt(_hr, _cl);
 
   switch (_fk) {
-  case NoFilterKind:          cl2 = cl; break;
+  case NoFilterKind:          cl2 = _cl; break;
   case IntoCSFilterKind:      cl2 = &intoCSFilt; break;
   case OutOfRegionFilterKind: cl2 = &outOfRegionFilt; break;
   default:                    ShouldNotReachHere();
@@ -100,7 +102,7 @@
   if (!g1h->is_obj_dead(oop(bottom), _hr)) {
     oop_size = oop(bottom)->oop_iterate(cl2, mr);
   } else {
-    oop_size = oop(bottom)->size();
+    oop_size = _hr->block_size(bottom);
   }
 
   bottom += oop_size;
@@ -109,17 +111,17 @@
     // We replicate the loop below for several kinds of possible filters.
     switch (_fk) {
     case NoFilterKind:
-      bottom = walk_mem_region_loop(cl, g1h, _hr, bottom, top);
+      bottom = walk_mem_region_loop(_cl, g1h, _hr, bottom, top);
       break;
 
     case IntoCSFilterKind: {
-      FilterIntoCSClosure filt(this, g1h, cl);
+      FilterIntoCSClosure filt(this, g1h, _cl);
       bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top);
       break;
     }
 
     case OutOfRegionFilterKind: {
-      FilterOutOfRegionClosure filt(_hr, cl);
+      FilterOutOfRegionClosure filt(_hr, _cl);
       bottom = walk_mem_region_loop(&filt, g1h, _hr, bottom, top);
       break;
     }
@@ -342,11 +344,6 @@
   return low;
 }
 
-#ifdef _MSC_VER // the use of 'this' below gets a warning, make it go away
-#pragma warning( disable:4355 ) // 'this' : used in base member initializer list
-#endif // _MSC_VER
-
-
 HeapRegion::HeapRegion(uint hrs_index,
                        G1BlockOffsetSharedArray* sharedOffsetArray,
                        MemRegion mr) :
@@ -358,7 +355,7 @@
     _claimed(InitialClaimValue), _evacuation_failed(false),
     _prev_marked_bytes(0), _next_marked_bytes(0), _gc_efficiency(0.0),
     _young_type(NotYoung), _next_young_region(NULL),
-    _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL), _pending_removal(false),
+    _next_dirty_cards_region(NULL), _next(NULL), _prev(NULL),
 #ifdef ASSERT
     _containing_set(NULL),
 #endif // ASSERT
@@ -367,55 +364,24 @@
     _predicted_bytes_to_copy(0)
 {
   _rem_set = new HeapRegionRemSet(sharedOffsetArray, this);
+  assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant.");
+
+  initialize(mr);
+}
+
+void HeapRegion::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
+  assert(_rem_set->is_empty(), "Remembered set must be empty");
+
+  G1OffsetTableContigSpace::initialize(mr, clear_space, mangle_space);
+
   _orig_end = mr.end();
-  // Note that initialize() will set the start of the unmarked area of the
-  // region.
   hr_clear(false /*par*/, false /*clear_space*/);
   set_top(bottom());
-  set_saved_mark();
-
-  assert(HeapRegionRemSet::num_par_rem_sets() > 0, "Invariant.");
+  record_top_and_timestamp();
 }
 
 CompactibleSpace* HeapRegion::next_compaction_space() const {
-  // We're not using an iterator given that it will wrap around when
-  // it reaches the last region and this is not what we want here.
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-  uint index = hrs_index() + 1;
-  while (index < g1h->n_regions()) {
-    HeapRegion* hr = g1h->region_at(index);
-    if (!hr->isHumongous()) {
-      return hr;
-    }
-    index += 1;
-  }
-  return NULL;
-}
-
-void HeapRegion::save_marks() {
-  set_saved_mark();
-}
-
-void HeapRegion::oops_in_mr_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  HeapWord* p = mr.start();
-  HeapWord* e = mr.end();
-  oop obj;
-  while (p < e) {
-    obj = oop(p);
-    p += obj->oop_iterate(cl);
-  }
-  assert(p == e, "bad memregion: doesn't end on obj boundary");
-}
-
-#define HeapRegion_OOP_SINCE_SAVE_MARKS_DEFN(OopClosureType, nv_suffix) \
-void HeapRegion::oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl) { \
-  ContiguousSpace::oop_since_save_marks_iterate##nv_suffix(cl);              \
-}
-SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(HeapRegion_OOP_SINCE_SAVE_MARKS_DEFN)
-
-
-void HeapRegion::oop_before_save_marks_iterate(ExtendedOopClosure* cl) {
-  oops_in_mr_iterate(MemRegion(bottom(), saved_mark_word()), cl);
+  return G1CollectedHeap::heap()->next_compaction_region(this);
 }
 
 void HeapRegion::note_self_forwarding_removal_start(bool during_initial_mark,
@@ -423,7 +389,6 @@
   // We always recreate the prev marking info and we'll explicitly
   // mark all objects we find to be self-forwarded on the prev
   // bitmap. So all objects need to be below PTAMS.
-  _prev_top_at_mark_start = top();
   _prev_marked_bytes = 0;
 
   if (during_initial_mark) {
@@ -447,6 +412,7 @@
   assert(0 <= marked_bytes && marked_bytes <= used(),
          err_msg("marked: "SIZE_FORMAT" used: "SIZE_FORMAT,
                  marked_bytes, used()));
+  _prev_top_at_mark_start = top();
   _prev_marked_bytes = marked_bytes;
 }
 
@@ -477,7 +443,7 @@
     if (cl->abort()) return cur;
     // The check above must occur before the operation below, since an
     // abort might invalidate the "size" operation.
-    cur += obj->size();
+    cur += block_size(cur);
   }
   return NULL;
 }
@@ -549,7 +515,7 @@
       return cur;
     }
     // Otherwise...
-    next = (cur + obj->size());
+    next = cur + block_size(cur);
   }
 
   // If we finish the above loop...We have a parseable object that
@@ -557,10 +523,9 @@
   // inside or spans the entire region.
 
   assert(obj == oop(cur), "sanity");
-  assert(cur <= start &&
-         obj->klass_or_null() != NULL &&
-         (cur + obj->size()) > start,
-         "Loop postcondition");
+  assert(cur <= start, "Loop postcondition");
+  assert(obj->klass_or_null() != NULL, "Loop postcondition");
+  assert((cur + block_size(cur)) > start, "Loop postcondition");
 
   if (!g1h->is_obj_dead(obj)) {
     obj->oop_iterate(cl, mr);
@@ -574,7 +539,7 @@
     };
 
     // Otherwise:
-    next = (cur + obj->size());
+    next = cur + block_size(cur);
 
     if (!g1h->is_obj_dead(obj)) {
       if (next < end || !obj->is_objArray()) {
@@ -929,10 +894,11 @@
   size_t object_num = 0;
   while (p < top()) {
     oop obj = oop(p);
-    size_t obj_size = obj->size();
+    size_t obj_size = block_size(p);
     object_num += 1;
 
-    if (is_humongous != g1->isHumongous(obj_size)) {
+    if (is_humongous != g1->isHumongous(obj_size) &&
+        !g1->is_obj_dead(obj, this)) { // Dead objects may have bigger block_size since they span several objects.
       gclog_or_tty->print_cr("obj "PTR_FORMAT" is of %shumongous size ("
                              SIZE_FORMAT" words) in a %shumongous region",
                              p, g1->isHumongous(obj_size) ? "" : "non-",
@@ -942,8 +908,10 @@
     }
 
     // If it returns false, verify_for_object() will output the
-    // appropriate messasge.
-    if (do_bot_verify && !_offsets.verify_for_object(p, obj_size)) {
+    // appropriate message.
+    if (do_bot_verify &&
+        !g1->is_obj_dead(obj, this) &&
+        !_offsets.verify_for_object(p, obj_size)) {
       *failures = true;
       return;
     }
@@ -951,7 +919,10 @@
     if (!g1->is_obj_dead_cond(obj, this, vo)) {
       if (obj->is_oop()) {
         Klass* klass = obj->klass();
-        if (!klass->is_metaspace_object()) {
+        bool is_metaspace_object = Metaspace::contains(klass) ||
+                                   (vo == VerifyOption_G1UsePrevMarking &&
+                                   ClassLoaderDataGraph::unload_list_contains(klass));
+        if (!is_metaspace_object) {
           gclog_or_tty->print_cr("klass "PTR_FORMAT" of object "PTR_FORMAT" "
                                  "not metadata", klass, (void *)obj);
           *failures = true;
@@ -1065,9 +1036,10 @@
 // away eventually.
 
 void G1OffsetTableContigSpace::clear(bool mangle_space) {
-  ContiguousSpace::clear(mangle_space);
-  _offsets.zero_bottom_entry();
-  _offsets.initialize_threshold();
+  set_top(bottom());
+  set_saved_mark_word(bottom());
+  CompactibleSpace::clear(mangle_space);
+  reset_bot();
 }
 
 void G1OffsetTableContigSpace::set_bottom(HeapWord* new_bottom) {
@@ -1103,10 +1075,10 @@
   if (_gc_time_stamp < g1h->get_gc_time_stamp())
     return top();
   else
-    return ContiguousSpace::saved_mark_word();
+    return Space::saved_mark_word();
 }
 
-void G1OffsetTableContigSpace::set_saved_mark() {
+void G1OffsetTableContigSpace::record_top_and_timestamp() {
   G1CollectedHeap* g1h = G1CollectedHeap::heap();
   unsigned curr_gc_time_stamp = g1h->get_gc_time_stamp();
 
@@ -1118,7 +1090,7 @@
     // of region. If it does so after _gc_time_stamp = ..., then it
     // will pick up the right saved_mark_word() as the high water mark
     // of the region. Either way, the behaviour will be correct.
-    ContiguousSpace::set_saved_mark();
+    Space::set_saved_mark_word(top());
     OrderAccess::storestore();
     _gc_time_stamp = curr_gc_time_stamp;
     // No need to do another barrier to flush the writes above. If
@@ -1129,6 +1101,26 @@
   }
 }
 
+void G1OffsetTableContigSpace::safe_object_iterate(ObjectClosure* blk) {
+  object_iterate(blk);
+}
+
+void G1OffsetTableContigSpace::object_iterate(ObjectClosure* blk) {
+  HeapWord* p = bottom();
+  while (p < top()) {
+    if (block_is_obj(p)) {
+      blk->do_object(oop(p));
+    }
+    p += block_size(p);
+  }
+}
+
+#define block_is_always_obj(q) true
+void G1OffsetTableContigSpace::prepare_for_compaction(CompactPoint* cp) {
+  SCAN_AND_FORWARD(cp, top, block_is_always_obj, block_size);
+}
+#undef block_is_always_obj
+
 G1OffsetTableContigSpace::
 G1OffsetTableContigSpace(G1BlockOffsetSharedArray* sharedOffsetArray,
                          MemRegion mr) :
@@ -1137,8 +1129,11 @@
   _gc_time_stamp(0)
 {
   _offsets.set_space(this);
-  // false ==> we'll do the clearing if there's clearing to be done.
-  ContiguousSpace::initialize(mr, false, SpaceDecorator::Mangle);
-  _offsets.zero_bottom_entry();
-  _offsets.initialize_threshold();
 }
+
+void G1OffsetTableContigSpace::initialize(MemRegion mr, bool clear_space, bool mangle_space) {
+  CompactibleSpace::initialize(mr, clear_space, mangle_space);
+  _top = bottom();
+  reset_bot();
+}
+
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp
index 25ffe1c..7f6485b 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp
@@ -25,7 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_HPP
 
-#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc_implementation/g1/g1BlockOffsetTable.hpp"
 #include "gc_implementation/g1/g1_specialized_oop_closures.hpp"
 #include "gc_implementation/g1/survRateGroup.hpp"
 #include "gc_implementation/shared/ageTable.hpp"
@@ -46,8 +46,6 @@
 // The solution is to remove this method from the definition
 // of a Space.
 
-class CompactibleSpace;
-class ContiguousSpace;
 class HeapRegionRemSet;
 class HeapRegionRemSetIterator;
 class HeapRegion;
@@ -64,14 +62,14 @@
                 p2i((_hr_)->bottom()), p2i((_hr_)->top()), p2i((_hr_)->end())
 
 // sentinel value for hrs_index
-#define G1_NULL_HRS_INDEX ((uint) -1)
+#define G1_NO_HRS_INDEX ((uint) -1)
 
 // A dirty card to oop closure for heap regions. It
 // knows how to get the G1 heap and how to use the bitmap
 // in the concurrent marker used by G1 to filter remembered
 // sets.
 
-class HeapRegionDCTOC : public ContiguousSpaceDCTOC {
+class HeapRegionDCTOC : public DirtyCardToOopClosure {
 public:
   // Specification of possible DirtyCardToOopClosure filtering.
   enum FilterKind {
@@ -85,39 +83,13 @@
   FilterKind _fk;
   G1CollectedHeap* _g1;
 
-  void walk_mem_region_with_cl(MemRegion mr,
-                               HeapWord* bottom, HeapWord* top,
-                               ExtendedOopClosure* cl);
-
-  // We don't specialize this for FilteringClosure; filtering is handled by
-  // the "FilterKind" mechanism.  But we provide this to avoid a compiler
-  // warning.
-  void walk_mem_region_with_cl(MemRegion mr,
-                               HeapWord* bottom, HeapWord* top,
-                               FilteringClosure* cl) {
-    HeapRegionDCTOC::walk_mem_region_with_cl(mr, bottom, top,
-                                             (ExtendedOopClosure*)cl);
-  }
-
-  // Get the actual top of the area on which the closure will
-  // operate, given where the top is assumed to be (the end of the
-  // memory region passed to do_MemRegion) and where the object
-  // at the top is assumed to start. For example, an object may
-  // start at the top but actually extend past the assumed top,
-  // in which case the top becomes the end of the object.
-  HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj) {
-    return ContiguousSpaceDCTOC::get_actual_top(top, top_obj);
-  }
-
   // Walk the given memory region from bottom to (actual) top
   // looking for objects and applying the oop closure (_cl) to
   // them. The base implementation of this treats the area as
   // blocks, where a block may or may not be an object. Sub-
   // classes should override this to provide more accurate
   // or possibly more efficient walking.
-  void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top) {
-    Filtering_DCTOC::walk_mem_region(mr, bottom, top);
-  }
+  void walk_mem_region(MemRegion mr, HeapWord* bottom, HeapWord* top);
 
 public:
   HeapRegionDCTOC(G1CollectedHeap* g1,
@@ -151,9 +123,9 @@
 // the regions anyway) and at the end of a Full GC. The current scheme
 // that uses sequential unsigned ints will fail only if we have 4b
 // evacuation pauses between two cleanups, which is _highly_ unlikely.
-
-class G1OffsetTableContigSpace: public ContiguousSpace {
+class G1OffsetTableContigSpace: public CompactibleSpace {
   friend class VMStructs;
+  HeapWord* _top;
  protected:
   G1BlockOffsetArrayContigSpace _offsets;
   Mutex _par_alloc_lock;
@@ -170,11 +142,35 @@
   G1OffsetTableContigSpace(G1BlockOffsetSharedArray* sharedOffsetArray,
                            MemRegion mr);
 
+  void set_top(HeapWord* value) { _top = value; }
+  HeapWord* top() const { return _top; }
+
+ protected:
+  // Reset the G1OffsetTableContigSpace.
+  virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space);
+
+  HeapWord** top_addr() { return &_top; }
+  // Allocation helpers (return NULL if full).
+  inline HeapWord* allocate_impl(size_t word_size, HeapWord* end_value);
+  inline HeapWord* par_allocate_impl(size_t word_size, HeapWord* end_value);
+
+ public:
+  void reset_after_compaction() { set_top(compaction_top()); }
+
+  size_t used() const { return byte_size(bottom(), top()); }
+  size_t free() const { return byte_size(top(), end()); }
+  bool is_free_block(const HeapWord* p) const { return p >= top(); }
+
+  MemRegion used_region() const { return MemRegion(bottom(), top()); }
+
+  void object_iterate(ObjectClosure* blk);
+  void safe_object_iterate(ObjectClosure* blk);
+
   void set_bottom(HeapWord* value);
   void set_end(HeapWord* value);
 
   virtual HeapWord* saved_mark_word() const;
-  virtual void set_saved_mark();
+  void record_top_and_timestamp();
   void reset_gc_time_stamp() { _gc_time_stamp = 0; }
   unsigned get_gc_time_stamp() { return _gc_time_stamp; }
 
@@ -194,6 +190,8 @@
   HeapWord* block_start(const void* p);
   HeapWord* block_start_const(const void* p) const;
 
+  void prepare_for_compaction(CompactPoint* cp);
+
   // Add offset table update.
   virtual HeapWord* allocate(size_t word_size);
   HeapWord* par_allocate(size_t word_size);
@@ -205,8 +203,7 @@
   virtual void print() const;
 
   void reset_bot() {
-    _offsets.zero_bottom_entry();
-    _offsets.initialize_threshold();
+    _offsets.reset_bot();
   }
 
   void update_bot_for_object(HeapWord* start, size_t word_size) {
@@ -228,10 +225,6 @@
     ContinuesHumongous
   };
 
-  // Requires that the region "mr" be dense with objects, and begin and end
-  // with an object.
-  void oops_in_mr_iterate(MemRegion mr, ExtendedOopClosure* cl);
-
   // The remembered set for this region.
   // (Might want to make this "inline" later, to avoid some alloc failure
   // issues.)
@@ -256,11 +249,9 @@
   bool _evacuation_failed;
 
   // A heap region may be a member one of a number of special subsets, each
-  // represented as linked lists through the field below.  Currently, these
-  // sets include:
+  // represented as linked lists through the field below.  Currently, there
+  // is only one set:
   //   The collection set.
-  //   The set of allocation regions used in a collection pause.
-  //   Spaces that may contain gray objects.
   HeapRegion* _next_in_special_set;
 
   // next region in the young "generation" region set
@@ -275,7 +266,6 @@
 #ifdef ASSERT
   HeapRegionSetBase* _containing_set;
 #endif // ASSERT
-  bool _pending_removal;
 
   // For parallel heapRegion traversal.
   jint _claimed;
@@ -344,6 +334,12 @@
              G1BlockOffsetSharedArray* sharedOffsetArray,
              MemRegion mr);
 
+  // Initializing the HeapRegion not only resets the data structure, but also
+  // resets the BOT for that heap region.
+  // The default values for clear_space means that we will do the clearing if
+  // there's clearing to be done ourselves. We also always mangle the space.
+  virtual void initialize(MemRegion mr, bool clear_space = false, bool mangle_space = SpaceDecorator::Mangle);
+
   static int    LogOfHRGrainBytes;
   static int    LogOfHRGrainWords;
 
@@ -379,14 +375,15 @@
     ParMarkRootClaimValue      = 9
   };
 
-  inline HeapWord* par_allocate_no_bot_updates(size_t word_size) {
-    assert(is_young(), "we can only skip BOT updates on young regions");
-    return ContiguousSpace::par_allocate(word_size);
-  }
-  inline HeapWord* allocate_no_bot_updates(size_t word_size) {
-    assert(is_young(), "we can only skip BOT updates on young regions");
-    return ContiguousSpace::allocate(word_size);
-  }
+  // All allocated blocks are occupied by objects in a HeapRegion
+  bool block_is_obj(const HeapWord* p) const;
+
+  // Returns the object size for all valid block starts
+  // and the amount of unallocated words if called on top()
+  size_t block_size(const HeapWord* p) const;
+
+  inline HeapWord* par_allocate_no_bot_updates(size_t word_size);
+  inline HeapWord* allocate_no_bot_updates(size_t word_size);
 
   // If this region is a member of a HeapRegionSeq, the index in that
   // sequence, otherwise -1.
@@ -563,26 +560,6 @@
   // to provide a dummy version of it.
 #endif // ASSERT
 
-  // If we want to remove regions from a list in bulk we can simply tag
-  // them with the pending_removal tag and call the
-  // remove_all_pending() method on the list.
-
-  bool pending_removal() { return _pending_removal; }
-
-  void set_pending_removal(bool pending_removal) {
-    if (pending_removal) {
-      assert(!_pending_removal && containing_set() != NULL,
-             "can only set pending removal to true if it's false and "
-             "the region belongs to a region set");
-    } else {
-      assert( _pending_removal && containing_set() == NULL,
-              "can only set pending removal to false if it's true and "
-              "the region does not belong to a region set");
-    }
-
-    _pending_removal = pending_removal;
-  }
-
   HeapRegion* get_next_young_region() { return _next_young_region; }
   void set_next_young_region(HeapRegion* hr) {
     _next_young_region = hr;
@@ -595,9 +572,6 @@
 
   HeapWord* orig_end() { return _orig_end; }
 
-  // Allows logical separation between objects allocated before and after.
-  void save_marks();
-
   // Reset HR stuff to default values.
   void hr_clear(bool par, bool clear_space, bool locked = false);
   void par_clear();
@@ -606,10 +580,6 @@
   HeapWord* prev_top_at_mark_start() const { return _prev_top_at_mark_start; }
   HeapWord* next_top_at_mark_start() const { return _next_top_at_mark_start; }
 
-  // Apply "cl->do_oop" to (the addresses of) all reference fields in objects
-  // allocated in the current region before the last call to "save_mark".
-  void oop_before_save_marks_iterate(ExtendedOopClosure* cl);
-
   // Note the start or end of marking. This tells the heap region
   // that the collector is about to start or has finished (concurrently)
   // marking the heap.
@@ -795,10 +765,6 @@
     _predicted_bytes_to_copy = bytes;
   }
 
-#define HeapRegion_OOP_SINCE_SAVE_MARKS_DECL(OopClosureType, nv_suffix)  \
-  virtual void oop_since_save_marks_iterate##nv_suffix(OopClosureType* cl);
-  SPECIALIZED_SINCE_SAVE_MARKS_CLOSURES(HeapRegion_OOP_SINCE_SAVE_MARKS_DECL)
-
   virtual CompactibleSpace* next_compaction_space() const;
 
   virtual void reset_after_compaction();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp
index d88bc07..62ae230 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.inline.hpp
@@ -25,8 +25,49 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_INLINE_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGION_INLINE_HPP
 
+#include "gc_implementation/g1/g1BlockOffsetTable.inline.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.hpp"
+#include "gc_implementation/g1/heapRegion.hpp"
+#include "memory/space.hpp"
+#include "runtime/atomic.inline.hpp"
+
+// This version requires locking.
+inline HeapWord* G1OffsetTableContigSpace::allocate_impl(size_t size,
+                                                HeapWord* const end_value) {
+  HeapWord* obj = top();
+  if (pointer_delta(end_value, obj) >= size) {
+    HeapWord* new_top = obj + size;
+    set_top(new_top);
+    assert(is_aligned(obj) && is_aligned(new_top), "checking alignment");
+    return obj;
+  } else {
+    return NULL;
+  }
+}
+
+// This version is lock-free.
+inline HeapWord* G1OffsetTableContigSpace::par_allocate_impl(size_t size,
+                                                    HeapWord* const end_value) {
+  do {
+    HeapWord* obj = top();
+    if (pointer_delta(end_value, obj) >= size) {
+      HeapWord* new_top = obj + size;
+      HeapWord* result = (HeapWord*)Atomic::cmpxchg_ptr(new_top, top_addr(), obj);
+      // result can be one of two:
+      //  the old top value: the exchange succeeded
+      //  otherwise: the new value of the top is returned.
+      if (result == obj) {
+        assert(is_aligned(obj) && is_aligned(new_top), "checking alignment");
+        return obj;
+      }
+    } else {
+      return NULL;
+    }
+  } while (true);
+}
+
 inline HeapWord* G1OffsetTableContigSpace::allocate(size_t size) {
-  HeapWord* res = ContiguousSpace::allocate(size);
+  HeapWord* res = allocate_impl(size, end());
   if (res != NULL) {
     _offsets.alloc_block(res, size);
   }
@@ -38,12 +79,7 @@
 // this is used for larger LAB allocations only.
 inline HeapWord* G1OffsetTableContigSpace::par_allocate(size_t size) {
   MutexLocker x(&_par_alloc_lock);
-  // Given that we take the lock no need to use par_allocate() here.
-  HeapWord* res = ContiguousSpace::allocate(size);
-  if (res != NULL) {
-    _offsets.alloc_block(res, size);
-  }
-  return res;
+  return allocate(size);
 }
 
 inline HeapWord* G1OffsetTableContigSpace::block_start(const void* p) {
@@ -55,6 +91,52 @@
   return _offsets.block_start_const(p);
 }
 
+inline bool
+HeapRegion::block_is_obj(const HeapWord* p) const {
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  if (ClassUnloadingWithConcurrentMark) {
+    return !g1h->is_obj_dead(oop(p), this);
+  }
+  return p < top();
+}
+
+inline size_t
+HeapRegion::block_size(const HeapWord *addr) const {
+  if (addr == top()) {
+    return pointer_delta(end(), addr);
+  }
+
+  if (block_is_obj(addr)) {
+    return oop(addr)->size();
+  }
+
+  assert(ClassUnloadingWithConcurrentMark,
+      err_msg("All blocks should be objects if G1 Class Unloading isn't used. "
+              "HR: ["PTR_FORMAT", "PTR_FORMAT", "PTR_FORMAT") "
+              "addr: " PTR_FORMAT,
+              p2i(bottom()), p2i(top()), p2i(end()), p2i(addr)));
+
+  // Old regions' dead objects may have dead classes
+  // We need to find the next live object in some other
+  // manner than getting the oop size
+  G1CollectedHeap* g1h = G1CollectedHeap::heap();
+  HeapWord* next = g1h->concurrent_mark()->prevMarkBitMap()->
+      getNextMarkedWordAddress(addr, prev_top_at_mark_start());
+
+  assert(next > addr, "must get the next live object");
+  return pointer_delta(next, addr);
+}
+
+inline HeapWord* HeapRegion::par_allocate_no_bot_updates(size_t word_size) {
+  assert(is_young(), "we can only skip BOT updates on young regions");
+  return par_allocate_impl(word_size, end());
+}
+
+inline HeapWord* HeapRegion::allocate_no_bot_updates(size_t word_size) {
+  assert(is_young(), "we can only skip BOT updates on young regions");
+  return allocate_impl(word_size, end());
+}
+
 inline void HeapRegion::note_start_of_marking() {
   _next_marked_bytes = 0;
   _next_top_at_mark_start = top();
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp
index be46ca4..f8426c5 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.cpp
@@ -169,7 +169,7 @@
 
   // Mem size in bytes.
   size_t mem_size() const {
-    return sizeof(this) + _bm.size_in_words() * HeapWordSize;
+    return sizeof(PerRegionTable) + _bm.size_in_words() * HeapWordSize;
   }
 
   // Requires "from" to be in "hr()".
@@ -288,7 +288,7 @@
   }
 
   _fine_grain_regions = NEW_C_HEAP_ARRAY3(PerRegionTablePtr, _max_fine_entries,
-                        mtGC, 0, AllocFailStrategy::RETURN_NULL);
+                        mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
 
   if (_fine_grain_regions == NULL) {
     vm_exit_out_of_memory(sizeof(void*)*_max_fine_entries, OOM_MALLOC_ERROR,
@@ -372,17 +372,17 @@
                                                        _max_regions,
                                                        &_static_mem_size);
 
-  for (uint i = 0; i < n_par_rs; i++) {
-    for (uint j = 0; j < _max_regions; j++) {
-      set(i, j, InvalidCard);
-    }
-  }
+  invalidate(0, _max_regions);
 }
 
-void FromCardCache::shrink(uint new_num_regions) {
+void FromCardCache::invalidate(uint start_idx, size_t new_num_regions) {
+  guarantee((size_t)start_idx + new_num_regions <= max_uintx,
+            err_msg("Trying to invalidate beyond maximum region, from %u size "SIZE_FORMAT,
+                    start_idx, new_num_regions));
   for (uint i = 0; i < HeapRegionRemSet::num_par_rem_sets(); i++) {
-    assert(new_num_regions <= _max_regions, "Must be within max.");
-    for (uint j = new_num_regions; j < _max_regions; j++) {
+    uint end_idx = (start_idx + (uint)new_num_regions);
+    assert(end_idx <= _max_regions, "Must be within max.");
+    for (uint j = start_idx; j < end_idx; j++) {
       set(i, j, InvalidCard);
     }
   }
@@ -406,12 +406,12 @@
   }
 }
 
-void OtherRegionsTable::init_from_card_cache(uint max_regions) {
+void OtherRegionsTable::initialize(uint max_regions) {
   FromCardCache::initialize(HeapRegionRemSet::num_par_rem_sets(), max_regions);
 }
 
-void OtherRegionsTable::shrink_from_card_cache(uint new_num_regions) {
-  FromCardCache::shrink(new_num_regions);
+void OtherRegionsTable::invalidate(uint start_idx, size_t num_regions) {
+  FromCardCache::invalidate(start_idx, num_regions);
 }
 
 void OtherRegionsTable::print_from_card_cache() {
@@ -694,6 +694,9 @@
   clear_fcc();
 }
 
+bool OtherRegionsTable::is_empty() const {
+  return occ_sparse() == 0 && occ_coarse() == 0 && _first_all_fine_prts == NULL;
+}
 
 size_t OtherRegionsTable::occupied() const {
   size_t sum = occ_fine();
@@ -735,7 +738,7 @@
   sum += (sizeof(PerRegionTable*) * _max_fine_entries);
   sum += (_coarse_map.size_in_words() * HeapWordSize);
   sum += (_sparse_table.mem_size());
-  sum += sizeof(*this) - sizeof(_sparse_table); // Avoid double counting above.
+  sum += sizeof(OtherRegionsTable) - sizeof(_sparse_table); // Avoid double counting above.
   return sum;
 }
 
@@ -770,30 +773,6 @@
   clear_fcc();
 }
 
-void OtherRegionsTable::clear_incoming_entry(HeapRegion* from_hr) {
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  size_t hrs_ind = (size_t) from_hr->hrs_index();
-  size_t ind = hrs_ind & _mod_max_fine_entries_mask;
-  if (del_single_region_table(ind, from_hr)) {
-    assert(!_coarse_map.at(hrs_ind), "Inv");
-  } else {
-    _coarse_map.par_at_put(hrs_ind, 0);
-  }
-  // Check to see if any of the fcc entries come from here.
-  uint hr_ind = hr()->hrs_index();
-  for (uint tid = 0; tid < HeapRegionRemSet::num_par_rem_sets(); tid++) {
-    int fcc_ent = FromCardCache::at(tid, hr_ind);
-    if (fcc_ent != FromCardCache::InvalidCard) {
-      HeapWord* card_addr = (HeapWord*)
-        (uintptr_t(fcc_ent) << CardTableModRefBS::card_shift);
-      if (hr()->is_in_reserved(card_addr)) {
-        // Clear the from card cache.
-        FromCardCache::set(tid, hr_ind, FromCardCache::InvalidCard);
-      }
-    }
-  }
-}
-
 bool OtherRegionsTable::del_single_region_table(size_t ind,
                                                 HeapRegion* hr) {
   assert(0 <= ind && ind < _max_fine_entries, "Preconditions.");
@@ -823,7 +802,6 @@
 
 bool OtherRegionsTable::contains_reference_locked(OopOrNarrowOopStar from) const {
   HeapRegion* hr = _g1h->heap_region_containing_raw(from);
-  if (hr == NULL) return false;
   RegionIdx_t hr_ind = (RegionIdx_t) hr->hrs_index();
   // Is this region in the coarse map?
   if (_coarse_map.at(hr_ind)) return true;
@@ -861,8 +839,8 @@
 HeapRegionRemSet::HeapRegionRemSet(G1BlockOffsetSharedArray* bosa,
                                    HeapRegion* hr)
   : _bosa(bosa),
-    _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #"UINT32_FORMAT, hr->hrs_index()), true),
-    _code_roots(), _other_regions(hr, &_m) {
+    _m(Mutex::leaf, FormatBuffer<128>("HeapRegionRemSet lock #%u", hr->hrs_index()), true),
+    _code_roots(), _other_regions(hr, &_m), _iter_state(Unclaimed), _iter_claimed(0) {
   reset_for_par_iteration();
 }
 
@@ -953,7 +931,10 @@
 
 void HeapRegionRemSet::remove_strong_code_root(nmethod* nm) {
   assert(nm != NULL, "sanity");
-  _code_roots.remove(nm);
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  _code_roots.remove_lock_free(nm);
+
   // Check that there were no duplicates
   guarantee(!_code_roots.contains(nm), "duplicate entry found");
 }
@@ -1048,20 +1029,16 @@
   return _code_roots.mem_size();
 }
 
-//-------------------- Iteration --------------------
-
 HeapRegionRemSetIterator:: HeapRegionRemSetIterator(HeapRegionRemSet* hrrs) :
   _hrrs(hrrs),
   _g1h(G1CollectedHeap::heap()),
   _coarse_map(&hrrs->_other_regions._coarse_map),
-  _fine_grain_regions(hrrs->_other_regions._fine_grain_regions),
   _bosa(hrrs->bosa()),
   _is(Sparse),
   // Set these values so that we increment to the first region.
   _coarse_cur_region_index(-1),
   _coarse_cur_region_cur_card(HeapRegion::CardsPerRegion-1),
-  _cur_region_cur_card(0),
-  _fine_array_index(-1),
+  _cur_card_in_prt(HeapRegion::CardsPerRegion),
   _fine_cur_prt(NULL),
   _n_yielded_coarse(0),
   _n_yielded_fine(0),
@@ -1093,58 +1070,59 @@
   return true;
 }
 
-void HeapRegionRemSetIterator::fine_find_next_non_null_prt() {
-  // Otherwise, find the next bucket list in the array.
-  _fine_array_index++;
-  while (_fine_array_index < (int) OtherRegionsTable::_max_fine_entries) {
-    _fine_cur_prt = _fine_grain_regions[_fine_array_index];
-    if (_fine_cur_prt != NULL) return;
-    else _fine_array_index++;
-  }
-  assert(_fine_cur_prt == NULL, "Loop post");
-}
-
 bool HeapRegionRemSetIterator::fine_has_next(size_t& card_index) {
   if (fine_has_next()) {
-    _cur_region_cur_card =
-      _fine_cur_prt->_bm.get_next_one_offset(_cur_region_cur_card + 1);
+    _cur_card_in_prt =
+      _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1);
   }
-  while (!fine_has_next()) {
-    if (_cur_region_cur_card == (size_t) HeapRegion::CardsPerRegion) {
-      _cur_region_cur_card = 0;
-      _fine_cur_prt = _fine_cur_prt->collision_list_next();
+  if (_cur_card_in_prt == HeapRegion::CardsPerRegion) {
+    // _fine_cur_prt may still be NULL in case if there are not PRTs at all for
+    // the remembered set.
+    if (_fine_cur_prt == NULL || _fine_cur_prt->next() == NULL) {
+      return false;
     }
-    if (_fine_cur_prt == NULL) {
-      fine_find_next_non_null_prt();
-      if (_fine_cur_prt == NULL) return false;
-    }
-    assert(_fine_cur_prt != NULL && _cur_region_cur_card == 0,
-           "inv.");
-    HeapWord* r_bot =
-      _fine_cur_prt->hr()->bottom();
-    _cur_region_card_offset = _bosa->index_for(r_bot);
-    _cur_region_cur_card = _fine_cur_prt->_bm.get_next_one_offset(0);
+    PerRegionTable* next_prt = _fine_cur_prt->next();
+    switch_to_prt(next_prt);
+    _cur_card_in_prt = _fine_cur_prt->_bm.get_next_one_offset(_cur_card_in_prt + 1);
   }
-  assert(fine_has_next(), "Or else we exited the loop via the return.");
-  card_index = _cur_region_card_offset + _cur_region_cur_card;
+
+  card_index = _cur_region_card_offset + _cur_card_in_prt;
+  guarantee(_cur_card_in_prt < HeapRegion::CardsPerRegion,
+            err_msg("Card index "SIZE_FORMAT" must be within the region", _cur_card_in_prt));
   return true;
 }
 
 bool HeapRegionRemSetIterator::fine_has_next() {
-  return
-    _fine_cur_prt != NULL &&
-    _cur_region_cur_card < HeapRegion::CardsPerRegion;
+  return _cur_card_in_prt != HeapRegion::CardsPerRegion;
+}
+
+void HeapRegionRemSetIterator::switch_to_prt(PerRegionTable* prt) {
+  assert(prt != NULL, "Cannot switch to NULL prt");
+  _fine_cur_prt = prt;
+
+  HeapWord* r_bot = _fine_cur_prt->hr()->bottom();
+  _cur_region_card_offset = _bosa->index_for(r_bot);
+
+  // The bitmap scan for the PRT always scans from _cur_region_cur_card + 1.
+  // To avoid special-casing this start case, and not miss the first bitmap
+  // entry, initialize _cur_region_cur_card with -1 instead of 0.
+  _cur_card_in_prt = (size_t)-1;
 }
 
 bool HeapRegionRemSetIterator::has_next(size_t& card_index) {
   switch (_is) {
-  case Sparse:
+  case Sparse: {
     if (_sparse_iter.has_next(card_index)) {
       _n_yielded_sparse++;
       return true;
     }
     // Otherwise, deliberate fall-through
     _is = Fine;
+    PerRegionTable* initial_fine_prt = _hrrs->_other_regions._first_all_fine_prts;
+    if (initial_fine_prt != NULL) {
+      switch_to_prt(_hrrs->_other_regions._first_all_fine_prts);
+    }
+  }
   case Fine:
     if (fine_has_next(card_index)) {
       _n_yielded_fine++;
@@ -1276,6 +1254,11 @@
 #ifndef PRODUCT
 void PerRegionTable::test_fl_mem_size() {
   PerRegionTable* dummy = alloc(NULL);
+
+  size_t min_prt_size = sizeof(void*) + dummy->bm()->size_in_words() * HeapWordSize;
+  assert(dummy->mem_size() > min_prt_size,
+         err_msg("PerRegionTable memory usage is suspiciously small, only has "SIZE_FORMAT" bytes. "
+                 "Should be at least "SIZE_FORMAT" bytes.", dummy->mem_size(), min_prt_size));
   free(dummy);
   guarantee(dummy->mem_size() == fl_mem_size(), "fl_mem_size() does not return the correct element size");
   // try to reset the state
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp
index 46b1745..48b53d0 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionRemSet.hpp
@@ -84,7 +84,7 @@
 
   static void initialize(uint n_par_rs, uint max_num_regions);
 
-  static void shrink(uint new_num_regions);
+  static void invalidate(uint start_idx, size_t num_regions);
 
   static void print(outputStream* out = gclog_or_tty) PRODUCT_RETURN;
 
@@ -185,6 +185,9 @@
   // objects.
   void scrub(CardTableModRefBS* ctbs, BitMap* region_bm, BitMap* card_bm);
 
+  // Returns whether this remembered set (and all sub-sets) contain no entries.
+  bool is_empty() const;
+
   size_t occupied() const;
   size_t occ_fine() const;
   size_t occ_coarse() const;
@@ -206,18 +209,15 @@
   // Specifically clear the from_card_cache.
   void clear_fcc();
 
-  // "from_hr" is being cleared; remove any entries from it.
-  void clear_incoming_entry(HeapRegion* from_hr);
-
   void do_cleanup_work(HRRSCleanupTask* hrrs_cleanup_task);
 
   // Declare the heap size (in # of regions) to the OtherRegionsTable.
   // (Uses it to initialize from_card_cache).
-  static void init_from_card_cache(uint max_regions);
+  static void initialize(uint max_regions);
 
-  // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
-  // Make sure any entries for higher regions are invalid.
-  static void shrink_from_card_cache(uint new_num_regions);
+  // Declares that regions between start_idx <= i < start_idx + num_regions are
+  // not in use. Make sure that any entries for these regions are invalid.
+  static void invalidate(uint start_idx, size_t num_regions);
 
   static void print_from_card_cache();
 };
@@ -272,6 +272,10 @@
     return _other_regions.hr();
   }
 
+  bool is_empty() const {
+    return (strong_code_roots_list_length() == 0) && _other_regions.is_empty();
+  }
+
   size_t occupied() {
     MutexLockerEx x(&_m, Mutex::_no_safepoint_check_flag);
     return occupied_locked();
@@ -342,20 +346,20 @@
     return _other_regions.mem_size()
       // This correction is necessary because the above includes the second
       // part.
-      + (sizeof(this) - sizeof(OtherRegionsTable))
+      + (sizeof(HeapRegionRemSet) - sizeof(OtherRegionsTable))
       + strong_code_roots_mem_size();
   }
 
   // Returns the memory occupancy of all static data structures associated
   // with remembered sets.
   static size_t static_mem_size() {
-    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::static_mem_size();
+    return OtherRegionsTable::static_mem_size() + G1CodeRootSet::free_chunks_static_mem_size();
   }
 
   // Returns the memory occupancy of all free_list data structures associated
   // with remembered sets.
   static size_t fl_mem_size() {
-    return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::fl_mem_size();
+    return OtherRegionsTable::fl_mem_size() + G1CodeRootSet::free_chunks_mem_size();
   }
 
   bool contains_reference(OopOrNarrowOopStar from) const {
@@ -378,7 +382,7 @@
   void strong_code_roots_do(CodeBlobClosure* blk) const;
 
   // Returns the number of elements in the strong code roots list
-  size_t strong_code_roots_list_length() {
+  size_t strong_code_roots_list_length() const {
     return _code_roots.length();
   }
 
@@ -400,13 +404,11 @@
   // Declare the heap size (in # of regions) to the HeapRegionRemSet(s).
   // (Uses it to initialize from_card_cache).
   static void init_heap(uint max_regions) {
-    G1CodeRootSet::initialize();
-    OtherRegionsTable::init_from_card_cache(max_regions);
+    OtherRegionsTable::initialize(max_regions);
   }
 
-  // Declares that only regions i s.t. 0 <= i < new_n_regs are in use.
-  static void shrink_heap(uint new_n_regs) {
-    OtherRegionsTable::shrink_from_card_cache(new_n_regs);
+  static void invalidate(uint start_idx, uint num_regions) {
+    OtherRegionsTable::invalidate(start_idx, num_regions);
   }
 
 #ifndef PRODUCT
@@ -433,26 +435,24 @@
 };
 
 class HeapRegionRemSetIterator : public StackObj {
-
-  // The region RSet over which we're iterating.
+ private:
+  // The region RSet over which we are iterating.
   HeapRegionRemSet* _hrrs;
 
   // Local caching of HRRS fields.
   const BitMap*             _coarse_map;
-  PerRegionTable**          _fine_grain_regions;
 
   G1BlockOffsetSharedArray* _bosa;
   G1CollectedHeap*          _g1h;
 
-  // The number yielded since initialization.
+  // The number of cards yielded since initialization.
   size_t _n_yielded_fine;
   size_t _n_yielded_coarse;
   size_t _n_yielded_sparse;
 
-  // Indicates what granularity of table that we're currently iterating over.
+  // Indicates what granularity of table that we are currently iterating over.
   // We start iterating over the sparse table, progress to the fine grain
   // table, and then finish with the coarse table.
-  // See HeapRegionRemSetIterator::has_next().
   enum IterState {
     Sparse,
     Fine,
@@ -460,38 +460,30 @@
   };
   IterState _is;
 
-  // In both kinds of iteration, heap offset of first card of current
-  // region.
+  // For both Coarse and Fine remembered set iteration this contains the
+  // first card number of the heap region we currently iterate over.
   size_t _cur_region_card_offset;
-  // Card offset within cur region.
-  size_t _cur_region_cur_card;
 
-  // Coarse table iteration fields:
-
-  // Current region index;
+  // Current region index for the Coarse remembered set iteration.
   int    _coarse_cur_region_index;
   size_t _coarse_cur_region_cur_card;
 
   bool coarse_has_next(size_t& card_index);
 
-  // Fine table iteration fields:
-
-  // Index of bucket-list we're working on.
-  int _fine_array_index;
-
-  // Per Region Table we're doing within current bucket list.
+  // The PRT we are currently iterating over.
   PerRegionTable* _fine_cur_prt;
+  // Card offset within the current PRT.
+  size_t _cur_card_in_prt;
 
-  /* SparsePRT::*/ SparsePRTIter _sparse_iter;
-
-  void fine_find_next_non_null_prt();
-
+  // Update internal variables when switching to the given PRT.
+  void switch_to_prt(PerRegionTable* prt);
   bool fine_has_next();
   bool fine_has_next(size_t& card_index);
 
-public:
-  // We require an iterator to be initialized before use, so the
-  // constructor does little.
+  // The Sparse remembered set iterator.
+  SparsePRTIter _sparse_iter;
+
+ public:
   HeapRegionRemSetIterator(HeapRegionRemSet* hrrs);
 
   // If there remains one or more cards to be yielded, returns true and
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp
index bb34dd0..418d01a 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp
@@ -25,237 +25,426 @@
 #include "precompiled.hpp"
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/heapRegionSeq.inline.hpp"
-#include "gc_implementation/g1/heapRegionSet.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
+#include "gc_implementation/g1/concurrentG1Refine.hpp"
 #include "memory/allocation.hpp"
 
-// Private
+void HeapRegionSeq::initialize(G1RegionToSpaceMapper* heap_storage,
+                               G1RegionToSpaceMapper* prev_bitmap,
+                               G1RegionToSpaceMapper* next_bitmap,
+                               G1RegionToSpaceMapper* bot,
+                               G1RegionToSpaceMapper* cardtable,
+                               G1RegionToSpaceMapper* card_counts) {
+  _allocated_heapregions_length = 0;
 
-uint HeapRegionSeq::find_contiguous_from(uint from, uint num) {
-  uint len = length();
-  assert(num > 1, "use this only for sequences of length 2 or greater");
-  assert(from <= len,
-         err_msg("from: %u should be valid and <= than %u", from, len));
+  _heap_mapper = heap_storage;
 
-  uint curr = from;
-  uint first = G1_NULL_HRS_INDEX;
-  uint num_so_far = 0;
-  while (curr < len && num_so_far < num) {
-    if (at(curr)->is_empty()) {
-      if (first == G1_NULL_HRS_INDEX) {
-        first = curr;
-        num_so_far = 1;
-      } else {
-        num_so_far += 1;
-      }
-    } else {
-      first = G1_NULL_HRS_INDEX;
-      num_so_far = 0;
+  _prev_bitmap_mapper = prev_bitmap;
+  _next_bitmap_mapper = next_bitmap;
+
+  _bot_mapper = bot;
+  _cardtable_mapper = cardtable;
+
+  _card_counts_mapper = card_counts;
+
+  MemRegion reserved = heap_storage->reserved();
+  _regions.initialize(reserved.start(), reserved.end(), HeapRegion::GrainBytes);
+
+  _available_map.resize(_regions.length(), false);
+  _available_map.clear();
+}
+
+bool HeapRegionSeq::is_available(uint region) const {
+  return _available_map.at(region);
+}
+
+#ifdef ASSERT
+bool HeapRegionSeq::is_free(HeapRegion* hr) const {
+  return _free_list.contains(hr);
+}
+#endif
+
+HeapRegion* HeapRegionSeq::new_heap_region(uint hrs_index) {
+  HeapWord* bottom = G1CollectedHeap::heap()->bottom_addr_for_region(hrs_index);
+  MemRegion mr(bottom, bottom + HeapRegion::GrainWords);
+  assert(reserved().contains(mr), "invariant");
+  return new HeapRegion(hrs_index, G1CollectedHeap::heap()->bot_shared(), mr);
+}
+
+void HeapRegionSeq::commit_regions(uint index, size_t num_regions) {
+  guarantee(num_regions > 0, "Must commit more than zero regions");
+  guarantee(_num_committed + num_regions <= max_length(), "Cannot commit more than the maximum amount of regions");
+
+  _num_committed += (uint)num_regions;
+
+  _heap_mapper->commit_regions(index, num_regions);
+
+  // Also commit auxiliary data
+  _prev_bitmap_mapper->commit_regions(index, num_regions);
+  _next_bitmap_mapper->commit_regions(index, num_regions);
+
+  _bot_mapper->commit_regions(index, num_regions);
+  _cardtable_mapper->commit_regions(index, num_regions);
+
+  _card_counts_mapper->commit_regions(index, num_regions);
+}
+
+void HeapRegionSeq::uncommit_regions(uint start, size_t num_regions) {
+  guarantee(num_regions >= 1, err_msg("Need to specify at least one region to uncommit, tried to uncommit zero regions at %u", start));
+  guarantee(_num_committed >= num_regions, "pre-condition");
+
+  // Print before uncommitting.
+  if (G1CollectedHeap::heap()->hr_printer()->is_active()) {
+    for (uint i = start; i < start + num_regions; i++) {
+      HeapRegion* hr = at(i);
+      G1CollectedHeap::heap()->hr_printer()->uncommit(hr->bottom(), hr->end());
     }
-    curr += 1;
   }
-  assert(num_so_far <= num, "post-condition");
-  if (num_so_far == num) {
-    // we found enough space for the humongous object
-    assert(from <= first && first < len, "post-condition");
-    assert(first < curr && (curr - first) == num, "post-condition");
-    for (uint i = first; i < first + num; ++i) {
-      assert(at(i)->is_empty(), "post-condition");
+
+  _num_committed -= (uint)num_regions;
+
+  _available_map.par_clear_range(start, start + num_regions, BitMap::unknown_range);
+  _heap_mapper->uncommit_regions(start, num_regions);
+
+  // Also uncommit auxiliary data
+  _prev_bitmap_mapper->uncommit_regions(start, num_regions);
+  _next_bitmap_mapper->uncommit_regions(start, num_regions);
+
+  _bot_mapper->uncommit_regions(start, num_regions);
+  _cardtable_mapper->uncommit_regions(start, num_regions);
+
+  _card_counts_mapper->uncommit_regions(start, num_regions);
+}
+
+void HeapRegionSeq::make_regions_available(uint start, uint num_regions) {
+  guarantee(num_regions > 0, "No point in calling this for zero regions");
+  commit_regions(start, num_regions);
+  for (uint i = start; i < start + num_regions; i++) {
+    if (_regions.get_by_index(i) == NULL) {
+      HeapRegion* new_hr = new_heap_region(i);
+      _regions.set_by_index(i, new_hr);
+      _allocated_heapregions_length = MAX2(_allocated_heapregions_length, i + 1);
     }
-    return first;
+  }
+
+  _available_map.par_set_range(start, start + num_regions, BitMap::unknown_range);
+
+  for (uint i = start; i < start + num_regions; i++) {
+    assert(is_available(i), err_msg("Just made region %u available but is apparently not.", i));
+    HeapRegion* hr = at(i);
+    if (G1CollectedHeap::heap()->hr_printer()->is_active()) {
+      G1CollectedHeap::heap()->hr_printer()->commit(hr->bottom(), hr->end());
+    }
+    HeapWord* bottom = G1CollectedHeap::heap()->bottom_addr_for_region(i);
+    MemRegion mr(bottom, bottom + HeapRegion::GrainWords);
+
+    hr->initialize(mr);
+    insert_into_free_list(at(i));
+  }
+}
+
+uint HeapRegionSeq::expand_by(uint num_regions) {
+  return expand_at(0, num_regions);
+}
+
+uint HeapRegionSeq::expand_at(uint start, uint num_regions) {
+  if (num_regions == 0) {
+    return 0;
+  }
+
+  uint cur = start;
+  uint idx_last_found = 0;
+  uint num_last_found = 0;
+
+  uint expanded = 0;
+
+  while (expanded < num_regions &&
+         (num_last_found = find_unavailable_from_idx(cur, &idx_last_found)) > 0) {
+    uint to_expand = MIN2(num_regions - expanded, num_last_found);
+    make_regions_available(idx_last_found, to_expand);
+    expanded += to_expand;
+    cur = idx_last_found + num_last_found + 1;
+  }
+
+  verify_optional();
+  return expanded;
+}
+
+uint HeapRegionSeq::find_contiguous(size_t num, bool empty_only) {
+  uint found = 0;
+  size_t length_found = 0;
+  uint cur = 0;
+
+  while (length_found < num && cur < max_length()) {
+    HeapRegion* hr = _regions.get_by_index(cur);
+    if ((!empty_only && !is_available(cur)) || (is_available(cur) && hr != NULL && hr->is_empty())) {
+      // This region is a potential candidate for allocation into.
+      length_found++;
+    } else {
+      // This region is not a candidate. The next region is the next possible one.
+      found = cur + 1;
+      length_found = 0;
+    }
+    cur++;
+  }
+
+  if (length_found == num) {
+    for (uint i = found; i < (found + num); i++) {
+      HeapRegion* hr = _regions.get_by_index(i);
+      // sanity check
+      guarantee((!empty_only && !is_available(i)) || (is_available(i) && hr != NULL && hr->is_empty()),
+                err_msg("Found region sequence starting at " UINT32_FORMAT ", length " SIZE_FORMAT
+                        " that is not empty at " UINT32_FORMAT ". Hr is " PTR_FORMAT, found, num, i, p2i(hr)));
+    }
+    return found;
   } else {
-    // we failed to find enough space for the humongous object
-    return G1_NULL_HRS_INDEX;
+    return G1_NO_HRS_INDEX;
   }
 }
 
-// Public
-
-void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end) {
-  assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0,
-         "bottom should be heap region aligned");
-  assert((uintptr_t) end % HeapRegion::GrainBytes == 0,
-         "end should be heap region aligned");
-
-  _next_search_index = 0;
-  _allocated_length = 0;
-
-  _regions.initialize(bottom, end, HeapRegion::GrainBytes);
-}
-
-MemRegion HeapRegionSeq::expand_by(HeapWord* old_end,
-                                   HeapWord* new_end,
-                                   FreeRegionList* list) {
-  assert(old_end < new_end, "don't call it otherwise");
-  G1CollectedHeap* g1h = G1CollectedHeap::heap();
-
-  HeapWord* next_bottom = old_end;
-  assert(heap_bottom() <= next_bottom, "invariant");
-  while (next_bottom < new_end) {
-    assert(next_bottom < heap_end(), "invariant");
-    uint index = length();
-
-    assert(index < max_length(), "otherwise we cannot expand further");
-    if (index == 0) {
-      // We have not allocated any regions so far
-      assert(next_bottom == heap_bottom(), "invariant");
-    } else {
-      // next_bottom should match the end of the last/previous region
-      assert(next_bottom == at(index - 1)->end(), "invariant");
+HeapRegion* HeapRegionSeq::next_region_in_heap(const HeapRegion* r) const {
+  guarantee(r != NULL, "Start region must be a valid region");
+  guarantee(is_available(r->hrs_index()), err_msg("Trying to iterate starting from region %u which is not in the heap", r->hrs_index()));
+  for (uint i = r->hrs_index() + 1; i < _allocated_heapregions_length; i++) {
+    HeapRegion* hr = _regions.get_by_index(i);
+    if (is_available(i)) {
+      return hr;
     }
-
-    if (index == _allocated_length) {
-      // We have to allocate a new HeapRegion.
-      HeapRegion* new_hr = g1h->new_heap_region(index, next_bottom);
-      if (new_hr == NULL) {
-        // allocation failed, we bail out and return what we have done so far
-        return MemRegion(old_end, next_bottom);
-      }
-      assert(_regions.get_by_index(index) == NULL, "invariant");
-      _regions.set_by_index(index, new_hr);
-      increment_allocated_length();
-    }
-    // Have to increment the length first, otherwise we will get an
-    // assert failure at(index) below.
-    increment_length();
-    HeapRegion* hr = at(index);
-    list->add_as_tail(hr);
-
-    next_bottom = hr->end();
   }
-  assert(next_bottom == new_end, "post-condition");
-  return MemRegion(old_end, next_bottom);
-}
-
-uint HeapRegionSeq::free_suffix() {
-  uint res = 0;
-  uint index = length();
-  while (index > 0) {
-    index -= 1;
-    if (!at(index)->is_empty()) {
-      break;
-    }
-    res += 1;
-  }
-  return res;
-}
-
-uint HeapRegionSeq::find_contiguous(uint num) {
-  assert(num > 1, "use this only for sequences of length 2 or greater");
-  assert(_next_search_index <= length(),
-         err_msg("_next_search_index: %u should be valid and <= than %u",
-                 _next_search_index, length()));
-
-  uint start = _next_search_index;
-  uint res = find_contiguous_from(start, num);
-  if (res == G1_NULL_HRS_INDEX && start > 0) {
-    // Try starting from the beginning. If _next_search_index was 0,
-    // no point in doing this again.
-    res = find_contiguous_from(0, num);
-  }
-  if (res != G1_NULL_HRS_INDEX) {
-    assert(res < length(), err_msg("res: %u should be valid", res));
-    _next_search_index = res + num;
-    assert(_next_search_index <= length(),
-           err_msg("_next_search_index: %u should be valid and <= than %u",
-                   _next_search_index, length()));
-  }
-  return res;
+  return NULL;
 }
 
 void HeapRegionSeq::iterate(HeapRegionClosure* blk) const {
-  iterate_from((HeapRegion*) NULL, blk);
-}
+  uint len = max_length();
 
-void HeapRegionSeq::iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const {
-  uint hr_index = 0;
-  if (hr != NULL) {
-    hr_index = hr->hrs_index();
-  }
-
-  uint len = length();
-  for (uint i = hr_index; i < len; i += 1) {
+  for (uint i = 0; i < len; i++) {
+    if (!is_available(i)) {
+      continue;
+    }
+    guarantee(at(i) != NULL, err_msg("Tried to access region %u that has a NULL HeapRegion*", i));
     bool res = blk->doHeapRegion(at(i));
     if (res) {
       blk->incomplete();
       return;
     }
   }
-  for (uint i = 0; i < hr_index; i += 1) {
-    bool res = blk->doHeapRegion(at(i));
+}
+
+uint HeapRegionSeq::find_unavailable_from_idx(uint start_idx, uint* res_idx) const {
+  guarantee(res_idx != NULL, "checking");
+  guarantee(start_idx <= (max_length() + 1), "checking");
+
+  uint num_regions = 0;
+
+  uint cur = start_idx;
+  while (cur < max_length() && is_available(cur)) {
+    cur++;
+  }
+  if (cur == max_length()) {
+    return num_regions;
+  }
+  *res_idx = cur;
+  while (cur < max_length() && !is_available(cur)) {
+    cur++;
+  }
+  num_regions = cur - *res_idx;
+#ifdef ASSERT
+  for (uint i = *res_idx; i < (*res_idx + num_regions); i++) {
+    assert(!is_available(i), "just checking");
+  }
+  assert(cur == max_length() || num_regions == 0 || is_available(cur),
+         err_msg("The region at the current position %u must be available or at the end of the heap.", cur));
+#endif
+  return num_regions;
+}
+
+uint HeapRegionSeq::start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const {
+  return num_regions * worker_i / num_workers;
+}
+
+void HeapRegionSeq::par_iterate(HeapRegionClosure* blk, uint worker_id, uint num_workers, jint claim_value) const {
+  const uint start_index = start_region_for_worker(worker_id, num_workers, _allocated_heapregions_length);
+
+  // Every worker will actually look at all regions, skipping over regions that
+  // are currently not committed.
+  // This also (potentially) iterates over regions newly allocated during GC. This
+  // is no problem except for some extra work.
+  for (uint count = 0; count < _allocated_heapregions_length; count++) {
+    const uint index = (start_index + count) % _allocated_heapregions_length;
+    assert(0 <= index && index < _allocated_heapregions_length, "sanity");
+    // Skip over unavailable regions
+    if (!is_available(index)) {
+      continue;
+    }
+    HeapRegion* r = _regions.get_by_index(index);
+    // We'll ignore "continues humongous" regions (we'll process them
+    // when we come across their corresponding "start humongous"
+    // region) and regions already claimed.
+    if (r->claim_value() == claim_value || r->continuesHumongous()) {
+      continue;
+    }
+    // OK, try to claim it
+    if (!r->claimHeapRegion(claim_value)) {
+      continue;
+    }
+    // Success!
+    if (r->startsHumongous()) {
+      // If the region is "starts humongous" we'll iterate over its
+      // "continues humongous" first; in fact we'll do them
+      // first. The order is important. In one case, calling the
+      // closure on the "starts humongous" region might de-allocate
+      // and clear all its "continues humongous" regions and, as a
+      // result, we might end up processing them twice. So, we'll do
+      // them first (note: most closures will ignore them anyway) and
+      // then we'll do the "starts humongous" region.
+      for (uint ch_index = index + 1; ch_index < index + r->region_num(); ch_index++) {
+        HeapRegion* chr = _regions.get_by_index(ch_index);
+
+        assert(chr->continuesHumongous(), "Must be humongous region");
+        assert(chr->humongous_start_region() == r,
+               err_msg("Must work on humongous continuation of the original start region "
+                       PTR_FORMAT ", but is " PTR_FORMAT, p2i(r), p2i(chr)));
+        assert(chr->claim_value() != claim_value,
+               "Must not have been claimed yet because claiming of humongous continuation first claims the start region");
+
+        bool claim_result = chr->claimHeapRegion(claim_value);
+        // We should always be able to claim it; no one else should
+        // be trying to claim this region.
+        guarantee(claim_result, "We should always be able to claim the continuesHumongous part of the humongous object");
+
+        bool res2 = blk->doHeapRegion(chr);
+        if (res2) {
+          return;
+        }
+
+        // Right now, this holds (i.e., no closure that actually
+        // does something with "continues humongous" regions
+        // clears them). We might have to weaken it in the future,
+        // but let's leave these two asserts here for extra safety.
+        assert(chr->continuesHumongous(), "should still be the case");
+        assert(chr->humongous_start_region() == r, "sanity");
+      }
+    }
+
+    bool res = blk->doHeapRegion(r);
     if (res) {
-      blk->incomplete();
       return;
     }
   }
 }
 
 uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) {
-  // Reset this in case it's currently pointing into the regions that
-  // we just removed.
-  _next_search_index = 0;
-
   assert(length() > 0, "the region sequence should not be empty");
-  assert(length() <= _allocated_length, "invariant");
-  assert(_allocated_length > 0, "we should have at least one region committed");
+  assert(length() <= _allocated_heapregions_length, "invariant");
+  assert(_allocated_heapregions_length > 0, "we should have at least one region committed");
   assert(num_regions_to_remove < length(), "We should never remove all regions");
 
-  uint i = 0;
-  for (; i < num_regions_to_remove; i++) {
-    HeapRegion* cur = at(length() - 1);
-
-    if (!cur->is_empty()) {
-      // We have to give up if the region can not be moved
-      break;
+  if (num_regions_to_remove == 0) {
+    return 0;
   }
-    assert(!cur->isHumongous(), "Humongous regions should not be empty");
 
-    decrement_length();
+  uint removed = 0;
+  uint cur = _allocated_heapregions_length - 1;
+  uint idx_last_found = 0;
+  uint num_last_found = 0;
+
+  while ((removed < num_regions_to_remove) &&
+      (num_last_found = find_empty_from_idx_reverse(cur, &idx_last_found)) > 0) {
+    // Only allow uncommit from the end of the heap.
+    if ((idx_last_found + num_last_found) != _allocated_heapregions_length) {
+      return 0;
+    }
+    uint to_remove = MIN2(num_regions_to_remove - removed, num_last_found);
+
+    uncommit_regions(idx_last_found + num_last_found - to_remove, to_remove);
+
+    cur -= num_last_found;
+    removed += to_remove;
   }
-  return i;
+
+  verify_optional();
+
+  return removed;
 }
 
-#ifndef PRODUCT
-void HeapRegionSeq::verify_optional() {
-  guarantee(length() <= _allocated_length,
-            err_msg("invariant: _length: %u _allocated_length: %u",
-                    length(), _allocated_length));
-  guarantee(_allocated_length <= max_length(),
-            err_msg("invariant: _allocated_length: %u _max_length: %u",
-                    _allocated_length, max_length()));
-  guarantee(_next_search_index <= length(),
-            err_msg("invariant: _next_search_index: %u _length: %u",
-                    _next_search_index, length()));
+uint HeapRegionSeq::find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const {
+  guarantee(start_idx < _allocated_heapregions_length, "checking");
+  guarantee(res_idx != NULL, "checking");
 
+  uint num_regions_found = 0;
+
+  jlong cur = start_idx;
+  while (cur != -1 && !(is_available(cur) && at(cur)->is_empty())) {
+    cur--;
+  }
+  if (cur == -1) {
+    return num_regions_found;
+  }
+  jlong old_cur = cur;
+  // cur indexes the first empty region
+  while (cur != -1 && is_available(cur) && at(cur)->is_empty()) {
+    cur--;
+  }
+  *res_idx = cur + 1;
+  num_regions_found = old_cur - cur;
+
+#ifdef ASSERT
+  for (uint i = *res_idx; i < (*res_idx + num_regions_found); i++) {
+    assert(at(i)->is_empty(), "just checking");
+  }
+#endif
+  return num_regions_found;
+}
+
+void HeapRegionSeq::verify() {
+  guarantee(length() <= _allocated_heapregions_length,
+            err_msg("invariant: _length: %u _allocated_length: %u",
+                    length(), _allocated_heapregions_length));
+  guarantee(_allocated_heapregions_length <= max_length(),
+            err_msg("invariant: _allocated_length: %u _max_length: %u",
+                    _allocated_heapregions_length, max_length()));
+
+  bool prev_committed = true;
+  uint num_committed = 0;
   HeapWord* prev_end = heap_bottom();
-  for (uint i = 0; i < _allocated_length; i += 1) {
+  for (uint i = 0; i < _allocated_heapregions_length; i++) {
+    if (!is_available(i)) {
+      prev_committed = false;
+      continue;
+    }
+    num_committed++;
     HeapRegion* hr = _regions.get_by_index(i);
     guarantee(hr != NULL, err_msg("invariant: i: %u", i));
-    guarantee(hr->bottom() == prev_end,
+    guarantee(!prev_committed || hr->bottom() == prev_end,
               err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT,
                       i, HR_FORMAT_PARAMS(hr), p2i(prev_end)));
     guarantee(hr->hrs_index() == i,
               err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index()));
-    if (i < length()) {
-      // Asserts will fire if i is >= _length
-      HeapWord* addr = hr->bottom();
-      guarantee(addr_to_region(addr) == hr, "sanity");
-      guarantee(addr_to_region_unsafe(addr) == hr, "sanity");
-    } else {
-      guarantee(hr->is_empty(), "sanity");
-      guarantee(!hr->isHumongous(), "sanity");
-      // using assert instead of guarantee here since containing_set()
-      // is only available in non-product builds.
-      assert(hr->containing_set() == NULL, "sanity");
-    }
+    // Asserts will fire if i is >= _length
+    HeapWord* addr = hr->bottom();
+    guarantee(addr_to_region(addr) == hr, "sanity");
+    // We cannot check whether the region is part of a particular set: at the time
+    // this method may be called, we have only completed allocation of the regions,
+    // but not put into a region set.
+    prev_committed = true;
     if (hr->startsHumongous()) {
       prev_end = hr->orig_end();
     } else {
       prev_end = hr->end();
     }
   }
-  for (uint i = _allocated_length; i < max_length(); i += 1) {
+  for (uint i = _allocated_heapregions_length; i < max_length(); i++) {
     guarantee(_regions.get_by_index(i) == NULL, err_msg("invariant i: %u", i));
   }
+
+  guarantee(num_committed == _num_committed, err_msg("Found %u committed regions, but should be %u", num_committed, _num_committed));
+  _free_list.verify();
+}
+
+#ifndef PRODUCT
+void HeapRegionSeq::verify_optional() {
+  verify();
 }
 #endif // PRODUCT
+
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp
index f58c4f9..1c8ed67 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp
@@ -26,6 +26,8 @@
 #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP
 
 #include "gc_implementation/g1/g1BiasedArray.hpp"
+#include "gc_implementation/g1/g1RegionToSpaceMapper.hpp"
+#include "gc_implementation/g1/heapRegionSet.hpp"
 
 class HeapRegion;
 class HeapRegionClosure;
@@ -33,16 +35,20 @@
 
 class G1HeapRegionTable : public G1BiasedMappedArray<HeapRegion*> {
  protected:
-   virtual HeapRegion* default_value() const { return NULL; }
+  virtual HeapRegion* default_value() const { return NULL; }
 };
 
-// This class keeps track of the region metadata (i.e., HeapRegion
-// instances). They are kept in the _regions array in address
-// order. A region's index in the array corresponds to its index in
-// the heap (i.e., 0 is the region at the bottom of the heap, 1 is
-// the one after it, etc.). Two regions that are consecutive in the
-// array should also be adjacent in the address space (i.e.,
-// region(i).end() == region(i+1).bottom().
+// This class keeps track of the actual heap memory, auxiliary data
+// and its metadata (i.e., HeapRegion instances) and the list of free regions.
+//
+// This allows maximum flexibility for deciding what to commit or uncommit given
+// a request from outside.
+//
+// HeapRegions are kept in the _regions array in address order. A region's
+// index in the array corresponds to its index in the heap (i.e., 0 is the
+// region at the bottom of the heap, 1 is the one after it, etc.). Two
+// regions that are consecutive in the array should also be adjacent in the
+// address space (i.e., region(i).end() == region(i+1).bottom().
 //
 // We create a HeapRegion when we commit the region's address space
 // for the first time. When we uncommit the address space of a
@@ -51,56 +57,94 @@
 //
 // We keep track of three lengths:
 //
-// * _committed_length (returned by length()) is the number of currently
-//   committed regions.
-// * _allocated_length (not exposed outside this class) is the
-//   number of regions for which we have HeapRegions.
+// * _num_committed (returned by length()) is the number of currently
+//   committed regions. These may not be contiguous.
+// * _allocated_heapregions_length (not exposed outside this class) is the
+//   number of regions+1 for which we have HeapRegions.
 // * max_length() returns the maximum number of regions the heap can have.
 //
-// and maintain that: _committed_length <= _allocated_length <= max_length()
 
 class HeapRegionSeq: public CHeapObj<mtGC> {
   friend class VMStructs;
 
   G1HeapRegionTable _regions;
 
-  // The number of regions committed in the heap.
-  uint _committed_length;
+  G1RegionToSpaceMapper* _heap_mapper;
+  G1RegionToSpaceMapper* _prev_bitmap_mapper;
+  G1RegionToSpaceMapper* _next_bitmap_mapper;
+  G1RegionToSpaceMapper* _bot_mapper;
+  G1RegionToSpaceMapper* _cardtable_mapper;
+  G1RegionToSpaceMapper* _card_counts_mapper;
 
-  // A hint for which index to start searching from for humongous
-  // allocations.
-  uint _next_search_index;
+  FreeRegionList _free_list;
 
-  // The number of regions for which we have allocated HeapRegions for.
-  uint _allocated_length;
+  // Each bit in this bitmap indicates that the corresponding region is available
+  // for allocation.
+  BitMap _available_map;
 
-  // Find a contiguous set of empty regions of length num, starting
-  // from the given index.
-  uint find_contiguous_from(uint from, uint num);
+   // The number of regions committed in the heap.
+  uint _num_committed;
 
-  void increment_allocated_length() {
-    assert(_allocated_length < max_length(), "pre-condition");
-    _allocated_length++;
-  }
+  // Internal only. The highest heap region +1 we allocated a HeapRegion instance for.
+  uint _allocated_heapregions_length;
 
-  void increment_length() {
-    assert(length() < max_length(), "pre-condition");
-    _committed_length++;
-  }
+   HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); }
+   HeapWord* heap_end() const {return _regions.end_address_mapped(); }
 
-  void decrement_length() {
-    assert(length() > 0, "pre-condition");
-    _committed_length--;
-  }
+  void make_regions_available(uint index, uint num_regions = 1);
 
-  HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); }
-  HeapWord* heap_end() const {return _regions.end_address_mapped(); }
+  // Pass down commit calls to the VirtualSpace.
+  void commit_regions(uint index, size_t num_regions = 1);
+  void uncommit_regions(uint index, size_t num_regions = 1);
 
- public:
-  // Empty contructor, we'll initialize it with the initialize() method.
-  HeapRegionSeq() : _regions(), _committed_length(0), _next_search_index(0), _allocated_length(0) { }
+  // Notify other data structures about change in the heap layout.
+  void update_committed_space(HeapWord* old_end, HeapWord* new_end);
+  // Calculate the starting region for each worker during parallel iteration so
+  // that they do not all start from the same region.
+  uint start_region_for_worker(uint worker_i, uint num_workers, uint num_regions) const;
 
-  void initialize(HeapWord* bottom, HeapWord* end);
+  // Find a contiguous set of empty or uncommitted regions of length num and return
+  // the index of the first region or G1_NO_HRS_INDEX if the search was unsuccessful.
+  // If only_empty is true, only empty regions are considered.
+  // Searches from bottom to top of the heap, doing a first-fit.
+  uint find_contiguous(size_t num, bool only_empty);
+  // Finds the next sequence of unavailable regions starting from start_idx. Returns the
+  // length of the sequence found. If this result is zero, no such sequence could be found,
+  // otherwise res_idx indicates the start index of these regions.
+  uint find_unavailable_from_idx(uint start_idx, uint* res_idx) const;
+  // Finds the next sequence of empty regions starting from start_idx, going backwards in
+  // the heap. Returns the length of the sequence found. If this value is zero, no
+  // sequence could be found, otherwise res_idx contains the start index of this range.
+  uint find_empty_from_idx_reverse(uint start_idx, uint* res_idx) const;
+  // Allocate a new HeapRegion for the given index.
+  HeapRegion* new_heap_region(uint hrs_index);
+#ifdef ASSERT
+public:
+  bool is_free(HeapRegion* hr) const;
+#endif
+  // Returns whether the given region is available for allocation.
+  bool is_available(uint region) const;
+
+  public:
+   // Empty constructor, we'll initialize it with the initialize() method.
+  HeapRegionSeq() : _regions(), _heap_mapper(NULL), _num_committed(0),
+                    _next_bitmap_mapper(NULL), _prev_bitmap_mapper(NULL), _bot_mapper(NULL),
+                    _allocated_heapregions_length(0), _available_map(),
+                    _free_list("Free list", new MasterFreeRegionListMtSafeChecker())
+  { }
+
+  void initialize(G1RegionToSpaceMapper* heap_storage,
+                  G1RegionToSpaceMapper* prev_bitmap,
+                  G1RegionToSpaceMapper* next_bitmap,
+                  G1RegionToSpaceMapper* bot,
+                  G1RegionToSpaceMapper* cardtable,
+                  G1RegionToSpaceMapper* card_counts);
+
+  // Return the "dummy" region used for G1AllocRegion. This is currently a hardwired
+  // new HeapRegion that owns HeapRegion at index 0. Since at the moment we commit
+  // the heap from the lowest address, this region (and its associated data
+  // structures) are available and we do not need to check further.
+  HeapRegion* get_dummy_region() { return new_heap_region(0); }
 
   // Return the HeapRegion at the given index. Assume that the index
   // is valid.
@@ -110,47 +154,83 @@
   // HeapRegion, otherwise return NULL.
   inline HeapRegion* addr_to_region(HeapWord* addr) const;
 
-  // Return the HeapRegion that corresponds to the given
-  // address. Assume the address is valid.
-  inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const;
+  // Insert the given region into the free region list.
+  inline void insert_into_free_list(HeapRegion* hr);
+
+  // Insert the given region list into the global free region list.
+  void insert_list_into_free_list(FreeRegionList* list) {
+    _free_list.add_ordered(list);
+  }
+
+  HeapRegion* allocate_free_region(bool is_old) {
+    HeapRegion* hr = _free_list.remove_region(is_old);
+
+    if (hr != NULL) {
+      assert(hr->next() == NULL, "Single region should not have next");
+      assert(is_available(hr->hrs_index()), "Must be committed");
+    }
+    return hr;
+  }
+
+  inline void allocate_free_regions_starting_at(uint first, uint num_regions);
+
+  // Remove all regions from the free list.
+  void remove_all_free_regions() {
+    _free_list.remove_all();
+  }
+
+  // Return the number of committed free regions in the heap.
+  uint num_free_regions() const {
+    return _free_list.length();
+  }
+
+  size_t total_capacity_bytes() const {
+    return num_free_regions() * HeapRegion::GrainBytes;
+  }
+
+  // Return the number of available (uncommitted) regions.
+  uint available() const { return max_length() - length(); }
 
   // Return the number of regions that have been committed in the heap.
-  uint length() const { return _committed_length; }
+  uint length() const { return _num_committed; }
 
   // Return the maximum number of regions in the heap.
   uint max_length() const { return (uint)_regions.length(); }
 
-  // Expand the sequence to reflect that the heap has grown from
-  // old_end to new_end. Either create new HeapRegions, or re-use
-  // existing ones, and return them in the given list. Returns the
-  // memory region that covers the newly-created regions. If a
-  // HeapRegion allocation fails, the result memory region might be
-  // smaller than the desired one.
-  MemRegion expand_by(HeapWord* old_end, HeapWord* new_end,
-                      FreeRegionList* list);
+  MemRegion reserved() const { return MemRegion(heap_bottom(), heap_end()); }
 
-  // Return the number of contiguous regions at the end of the sequence
-  // that are available for allocation.
-  uint free_suffix();
+  // Expand the sequence to reflect that the heap has grown. Either create new
+  // HeapRegions, or re-use existing ones. Returns the number of regions the
+  // sequence was expanded by. If a HeapRegion allocation fails, the resulting
+  // number of regions might be smaller than what's desired.
+  uint expand_by(uint num_regions);
 
-  // Find a contiguous set of empty regions of length num and return
-  // the index of the first region or G1_NULL_HRS_INDEX if the
-  // search was unsuccessful.
-  uint find_contiguous(uint num);
+  // Makes sure that the regions from start to start+num_regions-1 are available
+  // for allocation. Returns the number of regions that were committed to achieve
+  // this.
+  uint expand_at(uint start, uint num_regions);
+
+  // Find a contiguous set of empty regions of length num. Returns the start index of
+  // that set, or G1_NO_HRS_INDEX.
+  uint find_contiguous_only_empty(size_t num) { return find_contiguous(num, true); }
+  // Find a contiguous set of empty or unavailable regions of length num. Returns the
+  // start index of that set, or G1_NO_HRS_INDEX.
+  uint find_contiguous_empty_or_unavailable(size_t num) { return find_contiguous(num, false); }
+
+  HeapRegion* next_region_in_heap(const HeapRegion* r) const;
 
   // Apply blk->doHeapRegion() on all committed regions in address order,
   // terminating the iteration early if doHeapRegion() returns true.
   void iterate(HeapRegionClosure* blk) const;
 
-  // As above, but start the iteration from hr and loop around. If hr
-  // is NULL, we start from the first region in the heap.
-  void iterate_from(HeapRegion* hr, HeapRegionClosure* blk) const;
+  void par_iterate(HeapRegionClosure* blk, uint worker_id, uint no_of_par_workers, jint claim_value) const;
 
-  // Tag as uncommitted as many regions that are completely free as
-  // possible, up to num_regions_to_remove, from the suffix of the committed
-  // sequence. Return the actual number of removed regions.
+  // Uncommit up to num_regions_to_remove regions that are completely free.
+  // Return the actual number of uncommitted regions.
   uint shrink_by(uint num_regions_to_remove);
 
+  void verify();
+
   // Do some sanity checking.
   void verify_optional() PRODUCT_RETURN;
 };
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp
index e01c819..f5c1fff 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp
@@ -27,28 +27,32 @@
 
 #include "gc_implementation/g1/heapRegion.hpp"
 #include "gc_implementation/g1/heapRegionSeq.hpp"
+#include "gc_implementation/g1/heapRegionSet.inline.hpp"
 
-inline HeapRegion* HeapRegionSeq::addr_to_region_unsafe(HeapWord* addr) const {
+inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const {
+  assert(addr < heap_end(),
+        err_msg("addr: "PTR_FORMAT" end: "PTR_FORMAT, p2i(addr), p2i(heap_end())));
+  assert(addr >= heap_bottom(),
+        err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, p2i(addr), p2i(heap_bottom())));
+
   HeapRegion* hr = _regions.get_by_address(addr);
-  assert(hr != NULL, "invariant");
   return hr;
 }
 
-inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const {
-  if (addr != NULL && addr < heap_end()) {
-    assert(addr >= heap_bottom(),
-          err_msg("addr: " PTR_FORMAT " bottom: " PTR_FORMAT, p2i(addr), p2i(heap_bottom())));
-    return addr_to_region_unsafe(addr);
-  }
-  return NULL;
-}
-
 inline HeapRegion* HeapRegionSeq::at(uint index) const {
-  assert(index < length(), "pre-condition");
+  assert(is_available(index), "pre-condition");
   HeapRegion* hr = _regions.get_by_index(index);
   assert(hr != NULL, "sanity");
   assert(hr->hrs_index() == index, "sanity");
   return hr;
 }
 
+inline void HeapRegionSeq::insert_into_free_list(HeapRegion* hr) {
+  _free_list.add_ordered(hr);
+}
+
+inline void HeapRegionSeq::allocate_free_regions_starting_at(uint first, uint num_regions) {
+  _free_list.remove_starting_at(at(first), num_regions);
+}
+
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_INLINE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp
index fa5ab14..691ade1 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.cpp
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #include "gc_implementation/g1/heapRegionSet.inline.hpp"
 
@@ -67,7 +68,7 @@
   // Do the basic verification first before we do the checks over the regions.
   HeapRegionSetBase::verify();
 
-  _verify_in_progress        = true;
+  _verify_in_progress = true;
 }
 
 void HeapRegionSetBase::verify_end() {
@@ -103,62 +104,7 @@
 }
 
 void FreeRegionList::fill_in_ext_msg_extra(hrs_ext_msg* msg) {
-  msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, head(), tail());
-}
-
-void FreeRegionList::add_as_head_or_tail(FreeRegionList* from_list, bool as_head) {
-  check_mt_safety();
-  from_list->check_mt_safety();
-
-  verify_optional();
-  from_list->verify_optional();
-
-  if (from_list->is_empty()) {
-    return;
-  }
-
-#ifdef ASSERT
-  FreeRegionListIterator iter(from_list);
-  while (iter.more_available()) {
-    HeapRegion* hr = iter.get_next();
-    // In set_containing_set() we check that we either set the value
-    // from NULL to non-NULL or vice versa to catch bugs. So, we have
-    // to NULL it first before setting it to the value.
-    hr->set_containing_set(NULL);
-    hr->set_containing_set(this);
-  }
-#endif // ASSERT
-
-  if (_head == NULL) {
-    assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
-    _head = from_list->_head;
-    _tail = from_list->_tail;
-  } else {
-    assert(length() > 0 && _tail != NULL, hrs_ext_msg(this, "invariant"));
-    if (as_head) {
-      from_list->_tail->set_next(_head);
-      _head->set_prev(from_list->_tail);
-      _head = from_list->_head;
-    } else {
-      _tail->set_next(from_list->_head);
-      from_list->_head->set_prev(_tail);
-      _tail = from_list->_tail;
-    }
-  }
-
-  _count.increment(from_list->length(), from_list->total_capacity_bytes());
-  from_list->clear();
-
-  verify_optional();
-  from_list->verify_optional();
-}
-
-void FreeRegionList::add_as_head(FreeRegionList* from_list) {
-  add_as_head_or_tail(from_list, true /* as_head */);
-}
-
-void FreeRegionList::add_as_tail(FreeRegionList* from_list) {
-  add_as_head_or_tail(from_list, false /* as_head */);
+  msg->append(" hd: "PTR_FORMAT" tl: "PTR_FORMAT, _head, _tail);
 }
 
 void FreeRegionList::remove_all() {
@@ -191,11 +137,6 @@
     return;
   }
 
-  if (is_empty()) {
-    add_as_head(from_list);
-    return;
-  }
-
   #ifdef ASSERT
   FreeRegionListIterator iter(from_list);
   while (iter.more_available()) {
@@ -208,37 +149,43 @@
   }
   #endif // ASSERT
 
-  HeapRegion* curr_to = _head;
-  HeapRegion* curr_from = from_list->_head;
-
-  while (curr_from != NULL) {
-    while (curr_to != NULL && curr_to->hrs_index() < curr_from->hrs_index()) {
-      curr_to = curr_to->next();
-    }
-
-    if (curr_to == NULL) {
-      // The rest of the from list should be added as tail
-      _tail->set_next(curr_from);
-      curr_from->set_prev(_tail);
-      curr_from = NULL;
-    } else {
-      HeapRegion* next_from = curr_from->next();
-
-      curr_from->set_next(curr_to);
-      curr_from->set_prev(curr_to->prev());
-      if (curr_to->prev() == NULL) {
-        _head = curr_from;
-      } else {
-        curr_to->prev()->set_next(curr_from);
-      }
-      curr_to->set_prev(curr_from);
-
-      curr_from = next_from;
-    }
-  }
-
-  if (_tail->hrs_index() < from_list->_tail->hrs_index()) {
+  if (is_empty()) {
+    assert(length() == 0 && _tail == NULL, hrs_ext_msg(this, "invariant"));
+    _head = from_list->_head;
     _tail = from_list->_tail;
+  } else {
+    HeapRegion* curr_to = _head;
+    HeapRegion* curr_from = from_list->_head;
+
+    while (curr_from != NULL) {
+      while (curr_to != NULL && curr_to->hrs_index() < curr_from->hrs_index()) {
+        curr_to = curr_to->next();
+      }
+
+      if (curr_to == NULL) {
+        // The rest of the from list should be added as tail
+        _tail->set_next(curr_from);
+        curr_from->set_prev(_tail);
+        curr_from = NULL;
+      } else {
+        HeapRegion* next_from = curr_from->next();
+
+        curr_from->set_next(curr_to);
+        curr_from->set_prev(curr_to->prev());
+        if (curr_to->prev() == NULL) {
+          _head = curr_from;
+        } else {
+          curr_to->prev()->set_next(curr_from);
+        }
+        curr_to->set_prev(curr_from);
+
+        curr_from = next_from;
+      }
+    }
+
+    if (_tail->hrs_index() < from_list->_tail->hrs_index()) {
+      _tail = from_list->_tail;
+    }
   }
 
   _count.increment(from_list->length(), from_list->total_capacity_bytes());
@@ -248,68 +195,59 @@
   from_list->verify_optional();
 }
 
-void FreeRegionList::remove_all_pending(uint target_count) {
+void FreeRegionList::remove_starting_at(HeapRegion* first, uint num_regions) {
   check_mt_safety();
-  assert(target_count > 1, hrs_ext_msg(this, "pre-condition"));
+  assert(num_regions >= 1, hrs_ext_msg(this, "pre-condition"));
   assert(!is_empty(), hrs_ext_msg(this, "pre-condition"));
 
   verify_optional();
   DEBUG_ONLY(uint old_length = length();)
 
-  HeapRegion* curr = _head;
+  HeapRegion* curr = first;
   uint count = 0;
-  while (curr != NULL) {
+  while (count < num_regions) {
     verify_region(curr);
     HeapRegion* next = curr->next();
     HeapRegion* prev = curr->prev();
 
-    if (curr->pending_removal()) {
-      assert(count < target_count,
-             hrs_err_msg("[%s] should not come across more regions "
-                         "pending for removal than target_count: %u",
-                         name(), target_count));
+    assert(count < num_regions,
+           hrs_err_msg("[%s] should not come across more regions "
+                       "pending for removal than num_regions: %u",
+                       name(), num_regions));
 
-      if (prev == NULL) {
-        assert(_head == curr, hrs_ext_msg(this, "invariant"));
-        _head = next;
-      } else {
-        assert(_head != curr, hrs_ext_msg(this, "invariant"));
-        prev->set_next(next);
-      }
-      if (next == NULL) {
-        assert(_tail == curr, hrs_ext_msg(this, "invariant"));
-        _tail = prev;
-      } else {
-        assert(_tail != curr, hrs_ext_msg(this, "invariant"));
-        next->set_prev(prev);
-      }
-      if (_last = curr) {
-        _last = NULL;
-      }
-
-      curr->set_next(NULL);
-      curr->set_prev(NULL);
-      remove(curr);
-      curr->set_pending_removal(false);
-
-      count += 1;
-
-      // If we have come across the target number of regions we can
-      // just bail out. However, for debugging purposes, we can just
-      // carry on iterating to make sure there are not more regions
-      // tagged with pending removal.
-      DEBUG_ONLY(if (count == target_count) break;)
+    if (prev == NULL) {
+      assert(_head == curr, hrs_ext_msg(this, "invariant"));
+      _head = next;
+    } else {
+      assert(_head != curr, hrs_ext_msg(this, "invariant"));
+      prev->set_next(next);
     }
+    if (next == NULL) {
+      assert(_tail == curr, hrs_ext_msg(this, "invariant"));
+      _tail = prev;
+    } else {
+      assert(_tail != curr, hrs_ext_msg(this, "invariant"));
+      next->set_prev(prev);
+    }
+    if (_last = curr) {
+      _last = NULL;
+    }
+
+    curr->set_next(NULL);
+    curr->set_prev(NULL);
+    remove(curr);
+
+    count++;
     curr = next;
   }
 
-  assert(count == target_count,
-         hrs_err_msg("[%s] count: %u should be == target_count: %u",
-                     name(), count, target_count));
-  assert(length() + target_count == old_length,
+  assert(count == num_regions,
+         hrs_err_msg("[%s] count: %u should be == num_regions: %u",
+                     name(), count, num_regions));
+  assert(length() + num_regions == old_length,
          hrs_err_msg("[%s] new length should be consistent "
-                     "new length: %u old length: %u target_count: %u",
-                     name(), length(), old_length, target_count));
+                     "new length: %u old length: %u num_regions: %u",
+                     name(), length(), old_length, num_regions));
 
   verify_optional();
 }
@@ -348,10 +286,12 @@
       hr->print_on(out);
     }
   }
+
+  out->cr();
 }
 
 void FreeRegionList::verify_list() {
-  HeapRegion* curr = head();
+  HeapRegion* curr = _head;
   HeapRegion* prev1 = NULL;
   HeapRegion* prev0 = NULL;
   uint count = 0;
@@ -379,7 +319,7 @@
     curr = curr->next();
   }
 
-  guarantee(tail() == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), tail()->hrs_index(), prev0->hrs_index()));
+  guarantee(_tail == prev0, err_msg("Expected %s to end with %u but it ended with %u.", name(), _tail->hrs_index(), prev0->hrs_index()));
   guarantee(_tail == NULL || _tail->next() == NULL, "_tail should not have a next");
   guarantee(length() == count, err_msg("%s count mismatch. Expected %u, actual %u.", name(), length(), count));
   guarantee(total_capacity_bytes() == capacity, err_msg("%s capacity mismatch. Expected " SIZE_FORMAT ", actual " SIZE_FORMAT,
@@ -463,3 +403,41 @@
               "master humongous set MT safety protocol outside a safepoint");
   }
 }
+
+void FreeRegionList_test() {
+  FreeRegionList l("test");
+
+  const uint num_regions_in_test = 5;
+  // Create a fake heap. It does not need to be valid, as the HeapRegion constructor
+  // does not access it.
+  MemRegion heap(NULL, num_regions_in_test * HeapRegion::GrainWords);
+  // Allocate a fake BOT because the HeapRegion constructor initializes
+  // the BOT.
+  size_t bot_size = G1BlockOffsetSharedArray::compute_size(heap.word_size());
+  HeapWord* bot_data = NEW_C_HEAP_ARRAY(HeapWord, bot_size, mtGC);
+  ReservedSpace bot_rs(G1BlockOffsetSharedArray::compute_size(heap.word_size()));
+  G1RegionToSpaceMapper* bot_storage =
+    G1RegionToSpaceMapper::create_mapper(bot_rs,
+                                         os::vm_page_size(),
+                                         HeapRegion::GrainBytes,
+                                         G1BlockOffsetSharedArray::N_bytes,
+                                         mtGC);
+  G1BlockOffsetSharedArray oa(heap, bot_storage);
+  bot_storage->commit_regions(0, num_regions_in_test);
+  HeapRegion hr0(0, &oa, heap);
+  HeapRegion hr1(1, &oa, heap);
+  HeapRegion hr2(2, &oa, heap);
+  HeapRegion hr3(3, &oa, heap);
+  HeapRegion hr4(4, &oa, heap);
+  l.add_ordered(&hr1);
+  l.add_ordered(&hr0);
+  l.add_ordered(&hr3);
+  l.add_ordered(&hr4);
+  l.add_ordered(&hr2);
+  assert(l.length() == num_regions_in_test, "wrong length");
+  l.verify_list();
+
+  bot_storage->uncommit_regions(0, num_regions_in_test);
+  delete bot_storage;
+  FREE_C_HEAP_ARRAY(HeapWord, bot_data, mtGC);
+}
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp
index 222fc69..5bbae91 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.hpp
@@ -119,7 +119,7 @@
 public:
   const char* name() { return _name; }
 
-  uint length() { return _count.length(); }
+  uint length() const { return _count.length(); }
 
   bool is_empty() { return _count.length() == 0; }
 
@@ -162,7 +162,7 @@
 // diagnosing failures.
 class hrs_ext_msg : public hrs_err_msg {
 public:
-  hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("%s","") {
+  hrs_ext_msg(HeapRegionSetBase* set, const char* message) : hrs_err_msg("%s", "") {
     set->fill_in_ext_msg(this, message);
   }
 };
@@ -192,13 +192,9 @@
 };
 
 // A set that links all the regions added to it in a doubly-linked
-// list. We should try to avoid doing operations that iterate over
+// sorted list. We should try to avoid doing operations that iterate over
 // such lists in performance critical paths. Typically we should
-// add / remove one region at a time or concatenate two lists. There are
-// two ways to treat your lists, ordered and un-ordered. All un-ordered
-// operations are done in constant time. To keep a list ordered only use
-// add_ordered() to add elements to the list. If a list is not ordered
-// from start, there is no way to sort it later.
+// add / remove one region at a time or concatenate two lists.
 
 class FreeRegionListIterator;
 
@@ -210,13 +206,13 @@
   HeapRegion* _tail;
 
   // _last is used to keep track of where we added an element the last
-  // time in ordered lists. It helps to improve performance when adding
-  // several ordered items in a row.
+  // time. It helps to improve performance when adding several ordered items in a row.
   HeapRegion* _last;
 
   static uint _unrealistically_long_length;
 
-  void add_as_head_or_tail(FreeRegionList* from_list, bool as_head);
+  inline HeapRegion* remove_from_head_impl();
+  inline HeapRegion* remove_from_tail_impl();
 
 protected:
   virtual void fill_in_ext_msg_extra(hrs_ext_msg* msg);
@@ -232,8 +228,11 @@
 
   void verify_list();
 
-  HeapRegion* head() { return _head; }
-  HeapRegion* tail() { return _tail; }
+#ifdef ASSERT
+  bool contains(HeapRegion* hr) const {
+    return hr->containing_set() == this;
+  }
+#endif
 
   static void set_unrealistically_long_length(uint len);
 
@@ -242,55 +241,20 @@
   // is determined by hrs_index.
   inline void add_ordered(HeapRegion* hr);
 
-  // It adds hr to the list as the new head. The region should not be
-  // a member of another set.
-  inline void add_as_head(HeapRegion* hr);
-
-  // It adds hr to the list as the new tail. The region should not be
-  // a member of another set.
-  inline void add_as_tail(HeapRegion* hr);
-
-  // It removes and returns the head of the list. It assumes that the
-  // list is not empty so it will return a non-NULL value.
-  inline HeapRegion* remove_head();
-
-  // Convenience method.
-  inline HeapRegion* remove_head_or_null();
-
-  // Removes and returns the last element (_tail) of the list. It assumes
-  // that the list isn't empty so that it can return a non-NULL value.
-  inline HeapRegion* remove_tail();
-
-  // Convenience method
-  inline HeapRegion* remove_tail_or_null();
-
   // Removes from head or tail based on the given argument.
-  inline HeapRegion* remove_region(bool from_head);
+  HeapRegion* remove_region(bool from_head);
 
   // Merge two ordered lists. The result is also ordered. The order is
   // determined by hrs_index.
   void add_ordered(FreeRegionList* from_list);
 
-  // It moves the regions from from_list to this list and empties
-  // from_list. The new regions will appear in the same order as they
-  // were in from_list and be linked in the beginning of this list.
-  void add_as_head(FreeRegionList* from_list);
-
-  // It moves the regions from from_list to this list and empties
-  // from_list. The new regions will appear in the same order as they
-  // were in from_list and be linked in the end of this list.
-  void add_as_tail(FreeRegionList* from_list);
-
   // It empties the list by removing all regions from it.
   void remove_all();
 
-  // It removes all regions in the list that are pending for removal
-  // (i.e., they have been tagged with "pending_removal"). The list
-  // must not be empty, target_count should reflect the exact number
-  // of regions that are pending for removal in the list, and
-  // target_count should be > 1 (currently, we never need to remove a
-  // single region using this).
-  void remove_all_pending(uint target_count);
+  // Remove all (contiguous) regions from first to first + num_regions -1 from
+  // this list.
+  // Num_regions must be > 1.
+  void remove_starting_at(HeapRegion* first, uint num_regions);
 
   virtual void verify();
 
@@ -298,7 +262,7 @@
 };
 
 // Iterator class that provides a convenient way to iterate over the
-// regions of a HeapRegionLinkedList instance.
+// regions of a FreeRegionList.
 
 class FreeRegionListIterator : public StackObj {
 private:
@@ -324,7 +288,7 @@
   }
 
   FreeRegionListIterator(FreeRegionList* list) : _curr(NULL), _list(list) {
-    _curr = list->head();
+    _curr = list->_head;
   }
 };
 
diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp
index 08f74a7..683c4c9 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSet.inline.hpp
@@ -30,7 +30,8 @@
 inline void HeapRegionSetBase::add(HeapRegion* hr) {
   check_mt_safety();
   assert(hr->containing_set() == NULL, hrs_ext_msg(this, "should not already have a containing set %u"));
-  assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked"));
+  assert(hr->next() == NULL, hrs_ext_msg(this, "should not already be linked"));
+  assert(hr->prev() == NULL, hrs_ext_msg(this, "should not already be linked"));
 
   _count.increment(1u, hr->capacity());
   hr->set_containing_set(this);
@@ -40,7 +41,8 @@
 inline void HeapRegionSetBase::remove(HeapRegion* hr) {
   check_mt_safety();
   verify_region(hr);
-  assert(hr->next() == NULL && hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked"));
+  assert(hr->next() == NULL, hrs_ext_msg(this, "should already be unlinked"));
+  assert(hr->prev() == NULL, hrs_ext_msg(this, "should already be unlinked"));
 
   hr->set_containing_set(NULL);
   assert(_count.length() > 0, hrs_ext_msg(this, "pre-condition"));
@@ -48,8 +50,7 @@
 }
 
 inline void FreeRegionList::add_ordered(HeapRegion* hr) {
-  check_mt_safety();
-  assert((length() == 0 && _head == NULL && _tail == NULL) ||
+  assert((length() == 0 && _head == NULL && _tail == NULL && _last == NULL) ||
          (length() >  0 && _head != NULL && _tail != NULL),
          hrs_ext_msg(this, "invariant"));
   // add() will verify the region and check mt safety.
@@ -95,89 +96,48 @@
   _last = hr;
 }
 
-inline void FreeRegionList::add_as_head(HeapRegion* hr) {
-  assert((length() == 0 && _head == NULL && _tail == NULL) ||
-         (length() >  0 && _head != NULL && _tail != NULL),
-         hrs_ext_msg(this, "invariant"));
-  // add() will verify the region and check mt safety.
-  add(hr);
-
-  // Now link the region.
-  if (_head != NULL) {
-    hr->set_next(_head);
-    _head->set_prev(hr);
-  } else {
-    _tail = hr;
-  }
-  _head = hr;
-}
-
-inline void FreeRegionList::add_as_tail(HeapRegion* hr) {
-  check_mt_safety();
-  assert((length() == 0 && _head == NULL && _tail == NULL) ||
-         (length() >  0 && _head != NULL && _tail != NULL),
-         hrs_ext_msg(this, "invariant"));
-  // add() will verify the region and check mt safety.
-  add(hr);
-
-  // Now link the region.
-  if (_tail != NULL) {
-    _tail->set_next(hr);
-    hr->set_prev(_tail);
-  } else {
-    _head = hr;
-  }
-  _tail = hr;
-}
-
-inline HeapRegion* FreeRegionList::remove_head() {
-  assert(!is_empty(), hrs_ext_msg(this, "the list should not be empty"));
-  assert(length() > 0 && _head != NULL && _tail != NULL,
-         hrs_ext_msg(this, "invariant"));
-
-  // We need to unlink it first.
-  HeapRegion* hr = _head;
-  _head = hr->next();
+inline HeapRegion* FreeRegionList::remove_from_head_impl() {
+  HeapRegion* result = _head;
+  _head = result->next();
   if (_head == NULL) {
     _tail = NULL;
   } else {
     _head->set_prev(NULL);
   }
-  hr->set_next(NULL);
-
-  if (_last == hr) {
-    _last = NULL;
-  }
-
-  // remove() will verify the region and check mt safety.
-  remove(hr);
-  return hr;
+  result->set_next(NULL);
+  return result;
 }
 
-inline HeapRegion* FreeRegionList::remove_head_or_null() {
-  check_mt_safety();
-  if (!is_empty()) {
-    return remove_head();
-  } else {
-    return NULL;
-  }
-}
+inline HeapRegion* FreeRegionList::remove_from_tail_impl() {
+  HeapRegion* result = _tail;
 
-inline HeapRegion* FreeRegionList::remove_tail() {
-  assert(!is_empty(), hrs_ext_msg(this, "The list should not be empty"));
-  assert(length() > 0 && _head != NULL && _tail != NULL,
-         hrs_ext_msg(this, "invariant"));
-
-  // We need to unlink it first
-  HeapRegion* hr = _tail;
-
-  _tail = hr->prev();
+  _tail = result->prev();
   if (_tail == NULL) {
     _head = NULL;
   } else {
     _tail->set_next(NULL);
   }
-  hr->set_prev(NULL);
+  result->set_prev(NULL);
+  return result;
+}
+
+inline HeapRegion* FreeRegionList::remove_region(bool from_head) {
+  check_mt_safety();
+  verify_optional();
+
+  if (is_empty()) {
+    return NULL;
+  }
+  assert(length() > 0 && _head != NULL && _tail != NULL,
+         hrs_ext_msg(this, "invariant"));
+
+  HeapRegion* hr;
+
+  if (from_head) {
+    hr = remove_from_head_impl();
+  } else {
+    hr = remove_from_tail_impl();
+  }
 
   if (_last == hr) {
     _last = NULL;
@@ -188,22 +148,5 @@
   return hr;
 }
 
-inline HeapRegion* FreeRegionList::remove_tail_or_null() {
-  check_mt_safety();
-
-  if (!is_empty()) {
-    return remove_tail();
-  } else {
-    return NULL;
-  }
-}
-
-inline HeapRegion* FreeRegionList::remove_region(bool from_head) {
-  if (from_head) {
-    return remove_head_or_null();
-  } else {
-    return remove_tail_or_null();
-  }
-}
-
 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSET_INLINE_HPP
+
diff --git a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp
index 3e0c568..64c8d13 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.cpp
@@ -285,37 +285,6 @@
   _par_closures[i] = par_closure;
 }
 
-void SATBMarkQueueSet::iterate_closure_all_threads() {
-  for(JavaThread* t = Threads::first(); t; t = t->next()) {
-    t->satb_mark_queue().apply_closure_and_empty(_closure);
-  }
-  shared_satb_queue()->apply_closure_and_empty(_closure);
-}
-
-void SATBMarkQueueSet::par_iterate_closure_all_threads(uint worker) {
-  SharedHeap* sh = SharedHeap::heap();
-  int parity = sh->strong_roots_parity();
-
-  for(JavaThread* t = Threads::first(); t; t = t->next()) {
-    if (t->claim_oops_do(true, parity)) {
-      t->satb_mark_queue().apply_closure_and_empty(_par_closures[worker]);
-    }
-  }
-
-  // We also need to claim the VMThread so that its parity is updated
-  // otherwise the next call to Thread::possibly_parallel_oops_do inside
-  // a StrongRootsScope might skip the VMThread because it has a stale
-  // parity that matches the parity set by the StrongRootsScope
-  //
-  // Whichever worker succeeds in claiming the VMThread gets to do
-  // the shared queue.
-
-  VMThread* vmt = VMThread::vm_thread();
-  if (vmt->claim_oops_do(true, parity)) {
-    shared_satb_queue()->apply_closure_and_empty(_par_closures[worker]);
-  }
-}
-
 bool SATBMarkQueueSet::apply_closure_to_completed_buffer_work(bool par,
                                                               uint worker) {
   BufferNode* nd = NULL;
diff --git a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp
index dca73d0..4da5447 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/satbQueue.hpp
@@ -33,7 +33,9 @@
 
 // A ptrQueue whose elements are "oops", pointers to object heads.
 class ObjPtrQueue: public PtrQueue {
+  friend class Threads;
   friend class SATBMarkQueueSet;
+  friend class G1RemarkThreadsClosure;
 
 private:
   // Filter out unwanted entries from the buffer.
@@ -119,13 +121,6 @@
   // closures, one for each parallel GC thread.
   void set_par_closure(int i, ObjectClosure* closure);
 
-  // Apply the registered closure to all entries on each
-  // currently-active buffer and then empty the buffer. It should only
-  // be called serially and at a safepoint.
-  void iterate_closure_all_threads();
-  // Parallel version of the above.
-  void par_iterate_closure_all_threads(uint worker);
-
   // If there exists some completed buffer, pop it, then apply the
   // registered closure to all its elements, and return true.  If no
   // completed buffers exist, return false.
diff --git a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp
index 627c680..11f30c3 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/sparsePRT.cpp
@@ -370,7 +370,7 @@
 }
 
 size_t RSHashTable::mem_size() const {
-  return sizeof(this) +
+  return sizeof(RSHashTable) +
     capacity() * (SparsePRTEntry::size() + sizeof(int));
 }
 
@@ -472,7 +472,7 @@
 size_t SparsePRT::mem_size() const {
   // We ignore "_cur" here, because it either = _next, or else it is
   // on the deleted list.
-  return sizeof(this) + _next->mem_size();
+  return sizeof(SparsePRT) + _next->mem_size();
 }
 
 bool SparsePRT::add_card(RegionIdx_t region_id, CardIdx_t card_index) {
diff --git a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp
index d7820f8..4277ab5 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp
@@ -34,6 +34,8 @@
   static_field(HeapRegion, GrainBytes,        size_t)                         \
   static_field(HeapRegion, LogOfHRGrainBytes, int)                            \
                                                                               \
+  nonstatic_field(G1OffsetTableContigSpace, _top,       HeapWord*)            \
+                                                                              \
   nonstatic_field(G1HeapRegionTable, _base,             address)              \
   nonstatic_field(G1HeapRegionTable, _length,           size_t)               \
   nonstatic_field(G1HeapRegionTable, _biased_base,      address)              \
@@ -41,10 +43,9 @@
   nonstatic_field(G1HeapRegionTable, _shift_by,         uint)                 \
                                                                               \
   nonstatic_field(HeapRegionSeq,   _regions,            G1HeapRegionTable)    \
-  nonstatic_field(HeapRegionSeq,   _committed_length,   uint)                 \
+  nonstatic_field(HeapRegionSeq,   _num_committed,      uint)                 \
                                                                               \
   nonstatic_field(G1CollectedHeap, _hrs,                HeapRegionSeq)        \
-  nonstatic_field(G1CollectedHeap, _g1_committed,       MemRegion)            \
   nonstatic_field(G1CollectedHeap, _summary_bytes_used, size_t)               \
   nonstatic_field(G1CollectedHeap, _g1mm,               G1MonitoringSupport*) \
   nonstatic_field(G1CollectedHeap, _old_set,            HeapRegionSetBase)    \
@@ -69,7 +70,8 @@
                                                                               \
   declare_type(G1CollectedHeap, SharedHeap)                                   \
                                                                               \
-  declare_type(HeapRegion, ContiguousSpace)                                   \
+  declare_type(G1OffsetTableContigSpace, CompactibleSpace)                    \
+  declare_type(HeapRegion, G1OffsetTableContigSpace)                          \
   declare_toplevel_type(HeapRegionSeq)                                        \
   declare_toplevel_type(HeapRegionSetBase)                                    \
   declare_toplevel_type(HeapRegionSetCount)                                   \
diff --git a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp
index 9f298da..1c3c17b 100644
--- a/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp
+++ b/hotspot/src/share/vm/gc_implementation/g1/vm_operations_g1.cpp
@@ -226,7 +226,7 @@
 void VM_CGC_Operation::doit() {
   gclog_or_tty->date_stamp(G1Log::fine() && PrintGCDateStamps);
   TraceCPUTime tcpu(G1Log::finer(), true, gclog_or_tty);
-  GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm());
+  GCTraceTime t(_printGCMessage, G1Log::fine(), true, G1CollectedHeap::heap()->gc_timer_cm(), G1CollectedHeap::heap()->concurrent_mark()->concurrent_gc_id());
   SharedHeap* sh = SharedHeap::heap();
   // This could go away if CollectedHeap gave access to _gc_is_active...
   if (sh != NULL) {
diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp
index 897866d..9209f0d 100644
--- a/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parCardTableModRefBS.cpp
@@ -32,6 +32,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/virtualspace.hpp"
 #include "runtime/vmThread.hpp"
 
diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
index 9579fe5..4d407db 100644
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.cpp
@@ -28,12 +28,12 @@
 #include "gc_implementation/parNew/parOopClosures.inline.hpp"
 #include "gc_implementation/shared/adaptiveSizePolicy.hpp"
 #include "gc_implementation/shared/ageTable.hpp"
-#include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_implementation/shared/copyFailedInfo.hpp"
 #include "gc_implementation/shared/gcHeapSummary.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcTraceTime.hpp"
-#include "gc_implementation/shared/copyFailedInfo.hpp"
+#include "gc_implementation/shared/parGCAllocBuffer.inline.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "memory/defNewGeneration.inline.hpp"
 #include "memory/genCollectedHeap.hpp"
@@ -50,7 +50,7 @@
 #include "runtime/handles.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/java.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/workgroup.hpp"
@@ -251,7 +251,7 @@
         plab->set_word_size(buf_size);
         plab->set_buf(buf_space);
         record_survivor_plab(buf_space, buf_size);
-        obj = plab->allocate(word_sz);
+        obj = plab->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
         // Note that we cannot compare buf_size < word_sz below
         // because of AlignmentReserve (see ParGCAllocBuffer::allocate()).
         assert(obj != NULL || plab->words_remaining() < word_sz,
@@ -613,20 +613,21 @@
 
   KlassScanClosure klass_scan_closure(&par_scan_state.to_space_root_closure(),
                                       gch->rem_set()->klass_rem_set());
-
-  int so = SharedHeap::SO_AllClasses | SharedHeap::SO_Strings | SharedHeap::SO_CodeCache;
+  CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
+                                           &par_scan_state.to_space_root_closure(),
+                                           false);
 
   par_scan_state.start_strong_roots();
-  gch->gen_process_strong_roots(_gen->level(),
-                                true,  // Process younger gens, if any,
-                                       // as strong roots.
-                                false, // no scope; this is parallel code
-                                true,  // is scavenging
-                                SharedHeap::ScanningOption(so),
-                                &par_scan_state.to_space_root_closure(),
-                                true,   // walk *all* scavengable nmethods
-                                &par_scan_state.older_gen_closure(),
-                                &klass_scan_closure);
+  gch->gen_process_roots(_gen->level(),
+                         true,  // Process younger gens, if any,
+                                // as strong roots.
+                         false, // no scope; this is parallel code
+                         SharedHeap::SO_ScavengeCodeCache,
+                         GenCollectedHeap::StrongAndWeakRoots,
+                         &par_scan_state.to_space_root_closure(),
+                         &par_scan_state.older_gen_closure(),
+                         &cld_scan_closure);
+
   par_scan_state.end_strong_roots();
 
   // "evacuate followers".
@@ -957,7 +958,7 @@
     size_policy->minor_collection_begin();
   }
 
-  GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL);
+  GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id());
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
@@ -1015,14 +1016,14 @@
     ParNewRefProcTaskExecutor task_executor(*this, thread_state_set);
     stats = rp->process_discovered_references(&is_alive, &keep_alive,
                                               &evacuate_followers, &task_executor,
-                                              _gc_timer);
+                                              _gc_timer, gc_tracer.gc_id());
   } else {
     thread_state_set.flush();
     gch->set_par_threads(0);  // 0 ==> non-parallel.
     gch->save_marks();
     stats = rp->process_discovered_references(&is_alive, &keep_alive,
                                               &evacuate_followers, NULL,
-                                              _gc_timer);
+                                              _gc_timer, gc_tracer.gc_id());
   }
   gc_tracer.report_gc_reference_stats(stats);
   if (!promotion_failed()) {
diff --git a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp
index 6d3b25d..7685353 100644
--- a/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parNew/parNewGeneration.hpp
@@ -69,7 +69,7 @@
   ParScanWithoutBarrierClosure         _to_space_closure; // scan_without_gc_barrier
   ParScanWithBarrierClosure            _old_gen_closure; // scan_with_gc_barrier
   ParRootScanWithoutBarrierClosure     _to_space_root_closure; // scan_root_without_gc_barrier
-  // One of these two will be passed to process_strong_roots, which will
+  // One of these two will be passed to process_roots, which will
   // set its generation.  The first is for two-gen configs where the
   // old gen collects the perm gen; the second is for arbitrary configs.
   // The second isn't used right now (it used to be used for the train, an
@@ -168,7 +168,7 @@
   HeapWord* alloc_in_to_space_slow(size_t word_sz);
 
   HeapWord* alloc_in_to_space(size_t word_sz) {
-    HeapWord* obj = to_space_alloc_buffer()->allocate(word_sz);
+    HeapWord* obj = to_space_alloc_buffer()->allocate_aligned(word_sz, SurvivorAlignmentInBytes);
     if (obj != NULL) return obj;
     else return alloc_in_to_space_slow(word_sz);
   }
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp
index 923a62d..032b144 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/cardTableExtension.cpp
@@ -30,6 +30,7 @@
 #include "gc_implementation/parallelScavenge/psYoungGen.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/oop.psgc.inline.hpp"
+#include "runtime/prefetch.inline.hpp"
 
 // Checks an individual oop for missing precise marks. Mark
 // may be either dirty or newgen.
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp
index ad7391e..4dda503 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/gcTaskManager.cpp
@@ -30,6 +30,7 @@
 #include "memory/allocation.inline.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
index 76a368b..19a055c 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parMarkBitMap.cpp
@@ -71,7 +71,7 @@
   if (_virtual_space != NULL && _virtual_space->expand_by(_reserved_byte_size)) {
     _region_start = covered_region.start();
     _region_size = covered_region.word_size();
-    idx_t* map = (idx_t*)_virtual_space->reserved_low_addr();
+    BitMap::bm_word_t* map = (BitMap::bm_word_t*)_virtual_space->reserved_low_addr();
     _beg_bits.set_map(map);
     _beg_bits.set_size(bits / 2);
     _end_bits.set_map(map + words / 2);
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
index 55e85aa..7a78053 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.cpp
@@ -78,6 +78,7 @@
                         (HeapWord*)(heap_rs.base() + heap_rs.size()));
 
   CardTableExtension* const barrier_set = new CardTableExtension(_reserved, 3);
+  barrier_set->initialize();
   _barrier_set = barrier_set;
   oopDesc::set_bs(_barrier_set);
   if (_barrier_set == NULL) {
@@ -484,10 +485,6 @@
   young_gen()->eden_space()->ensure_parsability();
 }
 
-size_t ParallelScavengeHeap::unsafe_max_alloc() {
-  return young_gen()->eden_space()->free_in_bytes();
-}
-
 size_t ParallelScavengeHeap::tlab_capacity(Thread* thr) const {
   return young_gen()->eden_space()->tlab_capacity(thr);
 }
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
index e24936f..5173ff9 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp
@@ -184,8 +184,6 @@
   void accumulate_statistics_all_tlabs();
   void resize_all_tlabs();
 
-  size_t unsafe_max_alloc();
-
   bool supports_tlab_allocation() const { return true; }
 
   size_t tlab_capacity(Thread* thr) const;
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp
index e062b5c..260dc72 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/pcTasks.cpp
@@ -53,13 +53,13 @@
   ResourceMark rm;
 
   NOT_PRODUCT(GCTraceTime tm("ThreadRootsMarkingTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
 
   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
   CLDToOopClosure mark_and_push_from_clds(&mark_and_push_closure, true);
-  CodeBlobToOopClosure mark_and_push_in_blobs(&mark_and_push_closure, /*do_marking=*/ true);
+  MarkingCodeBlobClosure mark_and_push_in_blobs(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
 
   if (_java_thread != NULL)
     _java_thread->oops_do(
@@ -82,7 +82,7 @@
   assert(Universe::heap()->is_gc_active(), "called outside gc");
 
   NOT_PRODUCT(GCTraceTime tm("MarkFromRootsTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
@@ -100,7 +100,7 @@
     case threads:
     {
       ResourceMark rm;
-      CodeBlobToOopClosure each_active_code_blob(&mark_and_push_closure, /*do_marking=*/ true);
+      MarkingCodeBlobClosure each_active_code_blob(&mark_and_push_closure, !CodeBlobToOopClosure::FixRelocations);
       CLDToOopClosure mark_and_push_from_cld(&mark_and_push_closure);
       Threads::oops_do(&mark_and_push_closure, &mark_and_push_from_cld, &each_active_code_blob);
     }
@@ -153,7 +153,7 @@
   assert(Universe::heap()->is_gc_active(), "called outside gc");
 
   NOT_PRODUCT(GCTraceTime tm("RefProcTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
   PSParallelCompact::MarkAndPushClosure mark_and_push_closure(cm);
@@ -209,7 +209,7 @@
   assert(Universe::heap()->is_gc_active(), "called outside gc");
 
   NOT_PRODUCT(GCTraceTime tm("StealMarkingTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
 
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
@@ -242,7 +242,7 @@
   assert(Universe::heap()->is_gc_active(), "called outside gc");
 
   NOT_PRODUCT(GCTraceTime tm("StealRegionCompactionTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
 
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
@@ -309,7 +309,7 @@
 void UpdateDensePrefixTask::do_it(GCTaskManager* manager, uint which) {
 
   NOT_PRODUCT(GCTraceTime tm("UpdateDensePrefixTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
 
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
@@ -324,7 +324,7 @@
   assert(Universe::heap()->is_gc_active(), "called outside gc");
 
   NOT_PRODUCT(GCTraceTime tm("DrainStacksCompactionTask",
-    PrintGCDetails && TraceParallelOldGCTasks, true, NULL));
+    PrintGCDetails && TraceParallelOldGCTasks, true, NULL, PSParallelCompact::gc_tracer()->gc_id()));
 
   ParCompactionManager* cm =
     ParCompactionManager::gc_thread_compaction_manager(which);
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
index 8d3bd7e..77ab2cb 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.cpp
@@ -169,7 +169,7 @@
 
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL);
+    GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer->gc_id());
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
 
@@ -513,7 +513,7 @@
 
 void PSMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime tm("phase 1", PrintGCDetails && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 1", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace(" 1");
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
@@ -528,14 +528,14 @@
     Universe::oops_do(mark_and_push_closure());
     JNIHandles::oops_do(mark_and_push_closure());   // Global (strong) JNI handles
     CLDToOopClosure mark_and_push_from_cld(mark_and_push_closure());
-    CodeBlobToOopClosure each_active_code_blob(mark_and_push_closure(), /*do_marking=*/ true);
+    MarkingCodeBlobClosure each_active_code_blob(mark_and_push_closure(), !CodeBlobToOopClosure::FixRelocations);
     Threads::oops_do(mark_and_push_closure(), &mark_and_push_from_cld, &each_active_code_blob);
     ObjectSynchronizer::oops_do(mark_and_push_closure());
     FlatProfiler::oops_do(mark_and_push_closure());
     Management::oops_do(mark_and_push_closure());
     JvmtiExport::oops_do(mark_and_push_closure());
     SystemDictionary::always_strong_oops_do(mark_and_push_closure());
-    ClassLoaderDataGraph::always_strong_oops_do(mark_and_push_closure(), follow_klass_closure(), true);
+    ClassLoaderDataGraph::always_strong_cld_do(follow_cld_closure());
     // Do not treat nmethods as strong roots for mark/sweep, since we can unload them.
     //CodeCache::scavenge_root_nmethods_do(CodeBlobToOopClosure(mark_and_push_closure()));
   }
@@ -548,7 +548,7 @@
     ref_processor()->setup_policy(clear_all_softrefs);
     const ReferenceProcessorStats& stats =
       ref_processor()->process_discovered_references(
-        is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer);
+        is_alive_closure(), mark_and_push_closure(), follow_stack_closure(), NULL, _gc_timer, _gc_tracer->gc_id());
     gc_tracer()->report_gc_reference_stats(stats);
   }
 
@@ -574,7 +574,7 @@
 
 
 void PSMarkSweep::mark_sweep_phase2() {
-  GCTraceTime tm("phase 2", PrintGCDetails && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 2", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace("2");
 
   // Now all live objects are marked, compute the new object addresses.
@@ -604,7 +604,7 @@
 
 void PSMarkSweep::mark_sweep_phase3() {
   // Adjust the pointers to reflect the new locations
-  GCTraceTime tm("phase 3", PrintGCDetails && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 3", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace("3");
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
@@ -625,16 +625,16 @@
   FlatProfiler::oops_do(adjust_pointer_closure());
   Management::oops_do(adjust_pointer_closure());
   JvmtiExport::oops_do(adjust_pointer_closure());
-  // SO_AllClasses
   SystemDictionary::oops_do(adjust_pointer_closure());
-  ClassLoaderDataGraph::oops_do(adjust_pointer_closure(), adjust_klass_closure(), true);
+  ClassLoaderDataGraph::cld_do(adjust_cld_closure());
 
   // Now adjust pointers in remaining weak roots.  (All of which should
   // have been cleared if they pointed to non-surviving objects.)
   // Global (weak) JNI handles
   JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure());
 
-  CodeCache::oops_do(adjust_pointer_closure());
+  CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
+  CodeCache::blobs_do(&adjust_from_blobs);
   StringTable::oops_do(adjust_pointer_closure());
   ref_processor()->weak_oops_do(adjust_pointer_closure());
   PSScavenge::reference_processor()->weak_oops_do(adjust_pointer_closure());
@@ -647,7 +647,7 @@
 
 void PSMarkSweep::mark_sweep_phase4() {
   EventMark m("4 compact heap");
-  GCTraceTime tm("phase 4", PrintGCDetails && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 4", PrintGCDetails && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace("4");
 
   // All pointers are now adjusted, move objects accordingly
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp
index 68b3de4..46073f9 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweep.hpp
@@ -40,11 +40,11 @@
   static CollectorCounters*  _counters;
 
   // Closure accessors
-  static OopClosure* mark_and_push_closure() { return &MarkSweep::mark_and_push_closure; }
-  static KlassClosure* follow_klass_closure() { return &MarkSweep::follow_klass_closure; }
-  static VoidClosure* follow_stack_closure() { return (VoidClosure*)&MarkSweep::follow_stack_closure; }
-  static OopClosure* adjust_pointer_closure() { return (OopClosure*)&MarkSweep::adjust_pointer_closure; }
-  static KlassClosure* adjust_klass_closure() { return &MarkSweep::adjust_klass_closure; }
+  static OopClosure* mark_and_push_closure()   { return &MarkSweep::mark_and_push_closure; }
+  static VoidClosure* follow_stack_closure()   { return (VoidClosure*)&MarkSweep::follow_stack_closure; }
+  static CLDClosure* follow_cld_closure()      { return &MarkSweep::follow_cld_closure; }
+  static OopClosure* adjust_pointer_closure()  { return (OopClosure*)&MarkSweep::adjust_pointer_closure; }
+  static CLDClosure* adjust_cld_closure()      { return &MarkSweep::adjust_cld_closure; }
   static BoolObjectClosure* is_alive_closure() { return (BoolObjectClosure*)&MarkSweep::is_alive; }
 
  debug_only(public:)  // Used for PSParallelCompact debugging
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp
index ee43825..dc79821 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psMarkSweepDecorator.cpp
@@ -32,6 +32,7 @@
 #include "gc_implementation/shared/markSweep.inline.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/prefetch.inline.hpp"
 
 PSMarkSweepDecorator* PSMarkSweepDecorator::_destination_decorator = NULL;
 
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
index a56bd2a..e97a041 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.cpp
@@ -978,7 +978,7 @@
   // at each young gen gc.  Do the update unconditionally (even though a
   // promotion failure does not swap spaces) because an unknown number of minor
   // collections will have swapped the spaces an unknown number of times.
-  GCTraceTime tm("pre compact", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("pre compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
   ParallelScavengeHeap* heap = gc_heap();
   _space_info[from_space_id].set_space(heap->young_gen()->from_space());
   _space_info[to_space_id].set_space(heap->young_gen()->to_space());
@@ -1021,7 +1021,7 @@
 
 void PSParallelCompact::post_compact()
 {
-  GCTraceTime tm("post compact", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("post compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   for (unsigned int id = old_space_id; id < last_space_id; ++id) {
     // Clear the marking bitmap, summary data and split info.
@@ -1847,7 +1847,7 @@
 void PSParallelCompact::summary_phase(ParCompactionManager* cm,
                                       bool maximum_compaction)
 {
-  GCTraceTime tm("summary phase", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("summary phase", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
   // trace("2");
 
 #ifdef  ASSERT
@@ -2056,7 +2056,7 @@
 
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL);
+    GCTraceTime t1(GCCauseString("Full GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id());
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(true /* Full GC */,gc_cause);
 
@@ -2351,7 +2351,7 @@
                                       bool maximum_heap_compaction,
                                       ParallelOldTracer *gc_tracer) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime tm("marking phase", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("marking phase", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   ParallelScavengeHeap* heap = gc_heap();
   uint parallel_gc_threads = heap->gc_task_manager()->workers();
@@ -2366,7 +2366,7 @@
   ClassLoaderDataGraph::clear_claimed_marks();
 
   {
-    GCTraceTime tm_m("par mark", print_phases(), true, &_gc_timer);
+    GCTraceTime tm_m("par mark", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
     ParallelScavengeHeap::ParStrongRootsScope psrs;
 
@@ -2395,24 +2395,24 @@
 
   // Process reference objects found during marking
   {
-    GCTraceTime tm_r("reference processing", print_phases(), true, &_gc_timer);
+    GCTraceTime tm_r("reference processing", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
     ReferenceProcessorStats stats;
     if (ref_processor()->processing_is_mt()) {
       RefProcTaskExecutor task_executor;
       stats = ref_processor()->process_discovered_references(
         is_alive_closure(), &mark_and_push_closure, &follow_stack_closure,
-        &task_executor, &_gc_timer);
+        &task_executor, &_gc_timer, _gc_tracer.gc_id());
     } else {
       stats = ref_processor()->process_discovered_references(
         is_alive_closure(), &mark_and_push_closure, &follow_stack_closure, NULL,
-        &_gc_timer);
+        &_gc_timer, _gc_tracer.gc_id());
     }
 
     gc_tracer->report_gc_reference_stats(stats);
   }
 
-  GCTraceTime tm_c("class unloading", print_phases(), true, &_gc_timer);
+  GCTraceTime tm_c("class unloading", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   // This is the point where the entire marking should have completed.
   assert(cm->marking_stacks_empty(), "Marking should have completed");
@@ -2451,7 +2451,7 @@
 
 void PSParallelCompact::adjust_roots() {
   // Adjust the pointers to reflect the new locations
-  GCTraceTime tm("adjust roots", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("adjust roots", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   // Need new claim bits when tracing through and adjusting pointers.
   ClassLoaderDataGraph::clear_claimed_marks();
@@ -2465,7 +2465,6 @@
   FlatProfiler::oops_do(adjust_pointer_closure());
   Management::oops_do(adjust_pointer_closure());
   JvmtiExport::oops_do(adjust_pointer_closure());
-  // SO_AllClasses
   SystemDictionary::oops_do(adjust_pointer_closure());
   ClassLoaderDataGraph::oops_do(adjust_pointer_closure(), adjust_klass_closure(), true);
 
@@ -2474,7 +2473,8 @@
   // Global (weak) JNI handles
   JNIHandles::weak_oops_do(&always_true, adjust_pointer_closure());
 
-  CodeCache::oops_do(adjust_pointer_closure());
+  CodeBlobToOopClosure adjust_from_blobs(adjust_pointer_closure(), CodeBlobToOopClosure::FixRelocations);
+  CodeCache::blobs_do(&adjust_from_blobs);
   StringTable::oops_do(adjust_pointer_closure());
   ref_processor()->weak_oops_do(adjust_pointer_closure());
   // Roots were visited so references into the young gen in roots
@@ -2487,7 +2487,7 @@
 void PSParallelCompact::enqueue_region_draining_tasks(GCTaskQueue* q,
                                                       uint parallel_gc_threads)
 {
-  GCTraceTime tm("drain task setup", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("drain task setup", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   // Find the threads that are active
   unsigned int which = 0;
@@ -2561,7 +2561,7 @@
 
 void PSParallelCompact::enqueue_dense_prefix_tasks(GCTaskQueue* q,
                                                     uint parallel_gc_threads) {
-  GCTraceTime tm("dense prefix task setup", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("dense prefix task setup", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   ParallelCompactData& sd = PSParallelCompact::summary_data();
 
@@ -2643,7 +2643,7 @@
                                      GCTaskQueue* q,
                                      ParallelTaskTerminator* terminator_ptr,
                                      uint parallel_gc_threads) {
-  GCTraceTime tm("steal task setup", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("steal task setup", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   // Once a thread has drained it's stack, it should try to steal regions from
   // other threads.
@@ -2691,7 +2691,7 @@
 
 void PSParallelCompact::compact() {
   // trace("5");
-  GCTraceTime tm("compaction phase", print_phases(), true, &_gc_timer);
+  GCTraceTime tm("compaction phase", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
   ParallelScavengeHeap* heap = (ParallelScavengeHeap*)Universe::heap();
   assert(heap->kind() == CollectedHeap::ParallelScavengeHeap, "Sanity");
@@ -2708,7 +2708,7 @@
   enqueue_region_stealing_tasks(q, &terminator, active_gc_threads);
 
   {
-    GCTraceTime tm_pc("par compact", print_phases(), true, &_gc_timer);
+    GCTraceTime tm_pc("par compact", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
 
     gc_task_manager()->execute_and_wait(q);
 
@@ -2722,7 +2722,7 @@
 
   {
     // Update the deferred objects, if any.  Any compaction manager can be used.
-    GCTraceTime tm_du("deferred updates", print_phases(), true, &_gc_timer);
+    GCTraceTime tm_du("deferred updates", print_phases(), true, &_gc_timer, _gc_tracer.gc_id());
     ParCompactionManager* cm = ParCompactionManager::manager_array(0);
     for (unsigned int id = old_space_id; id < last_space_id; ++id) {
       update_deferred_objects(cm, SpaceId(id));
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
index 0f1b77b..4d83531 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psParallelCompact.hpp
@@ -1004,6 +1004,10 @@
   static bool   _dwl_initialized;
 #endif  // #ifdef ASSERT
 
+
+ public:
+  static ParallelOldTracer* gc_tracer() { return &_gc_tracer; }
+
  private:
 
   static void initialize_space_info();
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp
index e0427ef..3ca7ca3 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.hpp
@@ -26,6 +26,7 @@
 #define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_HPP
 
 #include "gc_implementation/parallelScavenge/objectStartArray.hpp"
+#include "gc_interface/collectedHeap.inline.hpp"
 #include "memory/allocation.hpp"
 
 //
@@ -94,23 +95,9 @@
   PSYoungPromotionLAB() { }
 
   // Not MT safe
-  HeapWord* allocate(size_t size) {
-    // Can't assert this, when young fills, we keep the LAB around, but flushed.
-    // assert(_state != flushed, "Sanity");
-    HeapWord* obj = top();
-    HeapWord* new_top = obj + size;
-    // The 'new_top>obj' check is needed to detect overflow of obj+size.
-    if (new_top > obj && new_top <= end()) {
-      set_top(new_top);
-      assert(is_object_aligned((intptr_t)obj) && is_object_aligned((intptr_t)new_top),
-             "checking alignment");
-      return obj;
-    }
+  inline HeapWord* allocate(size_t size);
 
-    return NULL;
-  }
-
-  debug_only(virtual bool lab_is_valid(MemRegion lab));
+  debug_only(virtual bool lab_is_valid(MemRegion lab);)
 };
 
 class PSOldPromotionLAB : public PSPromotionLAB {
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp
new file mode 100644
index 0000000..0e5d7e7
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP
+
+#include "gc_implementation/parallelScavenge/psPromotionLAB.hpp"
+#include "gc_interface/collectedHeap.inline.hpp"
+
+HeapWord* PSYoungPromotionLAB::allocate(size_t size) {
+  // Can't assert this, when young fills, we keep the LAB around, but flushed.
+  // assert(_state != flushed, "Sanity");
+  HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end(), SurvivorAlignmentInBytes);
+  if (obj == NULL) {
+    return NULL;
+  }
+
+  HeapWord* new_top = obj + size;
+  // The 'new_top>obj' check is needed to detect overflow of obj+size.
+  if (new_top > obj && new_top <= end()) {
+    set_top(new_top);
+    assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_object_aligned((intptr_t)new_top),
+           "checking alignment");
+    return obj;
+  } else {
+    set_top(obj);
+    return NULL;
+  }
+}
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_PSPROMOTIONLAB_INLINE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp
index 356c258..b2de74d 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psPromotionManager.inline.hpp
@@ -27,6 +27,7 @@
 
 #include "gc_implementation/parallelScavenge/psOldGen.hpp"
 #include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
+#include "gc_implementation/parallelScavenge/psPromotionLAB.inline.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
 #include "oops/oop.psgc.inline.hpp"
 
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
index 882376f..7eea946 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psScavenge.cpp
@@ -331,7 +331,7 @@
 
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL);
+    GCTraceTime t1(GCCauseString("GC", gc_cause), PrintGC, !PrintGCDetails, NULL, _gc_tracer.gc_id());
     TraceCollectorStats tcs(counters());
     TraceMemoryManagerStats tms(false /* not full GC */,gc_cause);
 
@@ -397,7 +397,7 @@
     // We'll use the promotion manager again later.
     PSPromotionManager* promotion_manager = PSPromotionManager::vm_thread_promotion_manager();
     {
-      GCTraceTime tm("Scavenge", false, false, &_gc_timer);
+      GCTraceTime tm("Scavenge", false, false, &_gc_timer, _gc_tracer.gc_id());
       ParallelScavengeHeap::ParStrongRootsScope psrs;
 
       GCTaskQueue* q = GCTaskQueue::create();
@@ -439,7 +439,7 @@
 
     // Process reference objects discovered during scavenge
     {
-      GCTraceTime tm("References", false, false, &_gc_timer);
+      GCTraceTime tm("References", false, false, &_gc_timer, _gc_tracer.gc_id());
 
       reference_processor()->setup_policy(false); // not always_clear
       reference_processor()->set_active_mt_degree(active_workers);
@@ -450,10 +450,10 @@
         PSRefProcTaskExecutor task_executor;
         stats = reference_processor()->process_discovered_references(
           &_is_alive_closure, &keep_alive, &evac_followers, &task_executor,
-          &_gc_timer);
+          &_gc_timer, _gc_tracer.gc_id());
       } else {
         stats = reference_processor()->process_discovered_references(
-          &_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer);
+          &_is_alive_closure, &keep_alive, &evac_followers, NULL, &_gc_timer, _gc_tracer.gc_id());
       }
 
       _gc_tracer.report_gc_reference_stats(stats);
@@ -468,7 +468,7 @@
     }
 
     {
-      GCTraceTime tm("StringTable", false, false, &_gc_timer);
+      GCTraceTime tm("StringTable", false, false, &_gc_timer, _gc_tracer.gc_id());
       // Unlink any dead interned Strings and process the remaining live ones.
       PSScavengeRootsClosure root_closure(promotion_manager);
       StringTable::unlink_or_oops_do(&_is_alive_closure, &root_closure);
@@ -638,7 +638,7 @@
     NOT_PRODUCT(reference_processor()->verify_no_references_recorded());
 
     {
-      GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer);
+      GCTraceTime tm("Prune Scavenge Root Methods", false, false, &_gc_timer, _gc_tracer.gc_id());
 
       CodeCache::prune_scavenge_root_nmethods();
     }
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp
index 6470281..f829e93 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/psTasks.cpp
@@ -65,7 +65,7 @@
     case threads:
     {
       ResourceMark rm;
-      CLDToOopClosure* cld_closure = NULL; // Not needed. All CLDs are already visited.
+      CLDClosure* cld_closure = NULL; // Not needed. All CLDs are already visited.
       Threads::oops_do(&roots_closure, cld_closure, NULL);
     }
     break;
@@ -100,7 +100,7 @@
 
     case code_cache:
       {
-        CodeBlobToOopClosure each_scavengable_code_blob(&roots_to_old_closure, /*do_marking=*/ true);
+        MarkingCodeBlobClosure each_scavengable_code_blob(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations);
         CodeCache::scavenge_root_nmethods_do(&each_scavengable_code_blob);
       }
       break;
@@ -122,8 +122,8 @@
 
   PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(which);
   PSScavengeRootsClosure roots_closure(pm);
-  CLDToOopClosure* roots_from_clds = NULL;  // Not needed. All CLDs are already visited.
-  CodeBlobToOopClosure roots_in_blobs(&roots_closure, /*do_marking=*/ true);
+  CLDClosure* roots_from_clds = NULL;  // Not needed. All CLDs are already visited.
+  MarkingCodeBlobClosure roots_in_blobs(&roots_closure, CodeBlobToOopClosure::FixRelocations);
 
   if (_java_thread != NULL)
     _java_thread->oops_do(&roots_closure, roots_from_clds, &roots_in_blobs);
diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp
index aede4e5..3a8f347 100644
--- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp
+++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/vmPSOperations.cpp
@@ -70,7 +70,7 @@
     "must be a ParallelScavengeHeap");
 
   GCCauseSetter gccs(heap, _gc_cause);
-  if (_gc_cause == GCCause::_gc_locker
+  if (_gc_cause == GCCause::_gc_locker || _gc_cause == GCCause::_wb_young_gc
       DEBUG_ONLY(|| _gc_cause == GCCause::_scavenge_alot)) {
     // If (and only if) the scavenge fails, this will invoke a full gc.
     heap->invoke_scavenge();
diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp
index 7b755cb..2de27d7 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.cpp
@@ -36,21 +36,10 @@
 
 int  ConcurrentGCThread::_CGC_flag            = CGC_nil;
 
-SuspendibleThreadSet ConcurrentGCThread::_sts;
-
 ConcurrentGCThread::ConcurrentGCThread() :
   _should_terminate(false), _has_terminated(false) {
-  _sts.initialize();
 };
 
-void ConcurrentGCThread::safepoint_synchronize() {
-  _sts.suspend_all();
-}
-
-void ConcurrentGCThread::safepoint_desynchronize() {
-  _sts.resume_all();
-}
-
 void ConcurrentGCThread::create_and_start() {
   if (os::create_thread(this, os::cgc_thread)) {
     // XXX: need to set this to low priority
@@ -91,78 +80,6 @@
   ThreadLocalStorage::set_thread(NULL);
 }
 
-
-void SuspendibleThreadSet::initialize_work() {
-  MutexLocker x(STS_init_lock);
-  if (!_initialized) {
-    _m             = new Monitor(Mutex::leaf,
-                                 "SuspendibleThreadSetLock", true);
-    _async         = 0;
-    _async_stop    = false;
-    _async_stopped = 0;
-    _initialized   = true;
-  }
-}
-
-void SuspendibleThreadSet::join() {
-  initialize();
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
-  _async++;
-  assert(_async > 0, "Huh.");
-}
-
-void SuspendibleThreadSet::leave() {
-  assert(_initialized, "Must be initialized.");
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  _async--;
-  assert(_async >= 0, "Huh.");
-  if (_async_stop) _m->notify_all();
-}
-
-void SuspendibleThreadSet::yield(const char* id) {
-  assert(_initialized, "Must be initialized.");
-  if (_async_stop) {
-    MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-    if (_async_stop) {
-      _async_stopped++;
-      assert(_async_stopped > 0, "Huh.");
-      if (_async_stopped == _async) {
-        if (ConcGCYieldTimeout > 0) {
-          double now = os::elapsedTime();
-          guarantee((now - _suspend_all_start) * 1000.0 <
-                    (double)ConcGCYieldTimeout,
-                    "Long delay; whodunit?");
-        }
-      }
-      _m->notify_all();
-      while (_async_stop) _m->wait(Mutex::_no_safepoint_check_flag);
-      _async_stopped--;
-      assert(_async >= 0, "Huh");
-      _m->notify_all();
-    }
-  }
-}
-
-void SuspendibleThreadSet::suspend_all() {
-  initialize();  // If necessary.
-  if (ConcGCYieldTimeout > 0) {
-    _suspend_all_start = os::elapsedTime();
-  }
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  assert(!_async_stop, "Only one at a time.");
-  _async_stop = true;
-  while (_async_stopped < _async) _m->wait(Mutex::_no_safepoint_check_flag);
-}
-
-void SuspendibleThreadSet::resume_all() {
-  assert(_initialized, "Must be initialized.");
-  MutexLockerEx x(_m, Mutex::_no_safepoint_check_flag);
-  assert(_async_stopped == _async, "Huh.");
-  _async_stop = false;
-  _m->notify_all();
-}
-
 static void _sltLoop(JavaThread* thread, TRAPS) {
   SurrogateLockerThread* slt = (SurrogateLockerThread*)thread;
   slt->loop();
@@ -282,30 +199,3 @@
   }
   assert(!_monitor.owned_by_self(), "Should unlock before exit.");
 }
-
-
-// ===== STS Access From Outside CGCT =====
-
-void ConcurrentGCThread::stsYield(const char* id) {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  _sts.yield(id);
-}
-
-bool ConcurrentGCThread::stsShouldYield() {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  return _sts.should_yield();
-}
-
-void ConcurrentGCThread::stsJoin() {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  _sts.join();
-}
-
-void ConcurrentGCThread::stsLeave() {
-  assert( Thread::current()->is_ConcurrentGC_thread(),
-          "only a conc GC thread can call this" );
-  _sts.leave();
-}
diff --git a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp
index 4172a95..4b82ed6 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/concurrentGCThread.hpp
@@ -26,55 +26,8 @@
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_CONCURRENTGCTHREAD_HPP
 
 #include "utilities/macros.hpp"
-#if INCLUDE_ALL_GCS
+#include "gc_implementation/shared/suspendibleThreadSet.hpp"
 #include "runtime/thread.hpp"
-#endif // INCLUDE_ALL_GCS
-
-class VoidClosure;
-
-// A SuspendibleThreadSet is (obviously) a set of threads that can be
-// suspended.  A thread can join and later leave the set, and periodically
-// yield.  If some thread (not in the set) requests, via suspend_all, that
-// the threads be suspended, then the requesting thread is blocked until
-// all the threads in the set have yielded or left the set.  (Threads may
-// not enter the set when an attempted suspension is in progress.)  The
-// suspending thread later calls resume_all, allowing the suspended threads
-// to continue.
-
-class SuspendibleThreadSet {
-  Monitor* _m;
-  int      _async;
-  bool     _async_stop;
-  int      _async_stopped;
-  bool     _initialized;
-  double   _suspend_all_start;
-
-  void initialize_work();
-
- public:
-  SuspendibleThreadSet() : _initialized(false) {}
-
-  // Add the current thread to the set.  May block if a suspension
-  // is in progress.
-  void join();
-  // Removes the current thread from the set.
-  void leave();
-  // Returns "true" iff an suspension is in progress.
-  bool should_yield() { return _async_stop; }
-  // Suspends the current thread if a suspension is in progress (for
-  // the duration of the suspension.)
-  void yield(const char* id);
-  // Return when all threads in the set are suspended.
-  void suspend_all();
-  // Allow suspended threads to resume.
-  void resume_all();
-  // Redundant initializations okay.
-  void initialize() {
-    // Double-check dirty read idiom.
-    if (!_initialized) initialize_work();
-  }
-};
-
 
 class ConcurrentGCThread: public NamedThread {
   friend class VMStructs;
@@ -96,9 +49,6 @@
   static int set_CGC_flag(int b)           { return _CGC_flag |= b; }
   static int reset_CGC_flag(int b)         { return _CGC_flag &= ~b; }
 
-  // All instances share this one set.
-  static SuspendibleThreadSet _sts;
-
   // Create and start the thread (setting it's priority high.)
   void create_and_start();
 
@@ -121,25 +71,6 @@
 
   // Tester
   bool is_ConcurrentGC_thread() const          { return true;       }
-
-  static void safepoint_synchronize();
-  static void safepoint_desynchronize();
-
-  // All overridings should probably do _sts::yield, but we allow
-  // overriding for distinguished debugging messages.  Default is to do
-  // nothing.
-  virtual void yield() {}
-
-  bool should_yield() { return _sts.should_yield(); }
-
-  // they are prefixed by sts since there are already yield() and
-  // should_yield() (non-static) methods in this class and it was an
-  // easy way to differentiate them.
-  static void stsYield(const char* id);
-  static bool stsShouldYield();
-  static void stsJoin();
-  static void stsLeave();
-
 };
 
 // The SurrogateLockerThread is used by concurrent GC threads for
diff --git a/nashorn/test/script/maptests/property_delete.js b/hotspot/src/share/vm/gc_implementation/shared/gcId.cpp
similarity index 67%
copy from nashorn/test/script/maptests/property_delete.js
copy to hotspot/src/share/vm/gc_implementation/shared/gcId.cpp
index e2824dd..ced64a4 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcId.cpp
@@ -1,48 +1,42 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
+ *
  */
 
-/**
- * @test
- * @option -Dnashorn.debug=true
- * @fork
- */
+#include "precompiled.hpp"
+#include "gc_implementation/shared/gcId.hpp"
+#include "runtime/safepoint.hpp"
 
-load(__DIR__ + "maputil.js");
+uint GCId::_next_id = 0;
 
-function Foo() {
-    this.x = 33;
+const GCId GCId::create() {
+  return GCId(_next_id++);
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
+const GCId GCId::peek() {
+  return GCId(_next_id);
 }
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
+const GCId GCId::undefined() {
+  return GCId(UNDEFINED);
+}
+bool GCId::is_undefined() const {
+  return _id == UNDEFINED;
+}
diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcId.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcId.hpp
new file mode 100644
index 0000000..1d2decc
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcId.hpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCID_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCID_HPP
+
+#include "memory/allocation.hpp"
+
+class GCId VALUE_OBJ_CLASS_SPEC {
+ private:
+  uint _id;
+  GCId(uint id) : _id(id) {}
+  GCId() { } // Unused
+
+  static uint _next_id;
+  static const uint UNDEFINED = (uint)-1;
+
+ public:
+  uint id() const {
+    assert(_id != UNDEFINED, "Using undefined GC ID");
+    return _id;
+  }
+  bool is_undefined() const;
+
+  static const GCId create();
+  static const GCId peek();
+  static const GCId undefined();
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_GCID_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp
index 994d468..ddac953 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.cpp
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "gc_implementation/shared/copyFailedInfo.hpp"
 #include "gc_implementation/shared/gcHeapSummary.hpp"
+#include "gc_implementation/shared/gcId.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
 #include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/objectCountEventSender.hpp"
@@ -38,19 +39,14 @@
 #include "gc_implementation/g1/evacuationInfo.hpp"
 #endif
 
-#define assert_unset_gc_id() assert(_shared_gc_info.id() == SharedGCInfo::UNSET_GCID, "GC already started?")
-#define assert_set_gc_id() assert(_shared_gc_info.id() != SharedGCInfo::UNSET_GCID, "GC not started?")
-
-static GCId GCTracer_next_gc_id = 0;
-static GCId create_new_gc_id() {
-  return GCTracer_next_gc_id++;
-}
+#define assert_unset_gc_id() assert(_shared_gc_info.gc_id().is_undefined(), "GC already started?")
+#define assert_set_gc_id() assert(!_shared_gc_info.gc_id().is_undefined(), "GC not started?")
 
 void GCTracer::report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp) {
   assert_unset_gc_id();
 
-  GCId gc_id = create_new_gc_id();
-  _shared_gc_info.set_id(gc_id);
+  GCId gc_id = GCId::create();
+  _shared_gc_info.set_gc_id(gc_id);
   _shared_gc_info.set_cause(cause);
   _shared_gc_info.set_start_timestamp(timestamp);
 }
@@ -62,7 +58,7 @@
 }
 
 bool GCTracer::has_reported_gc_start() const {
-  return _shared_gc_info.id() != SharedGCInfo::UNSET_GCID;
+  return !_shared_gc_info.gc_id().is_undefined();
 }
 
 void GCTracer::report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions) {
@@ -81,7 +77,7 @@
 
   report_gc_end_impl(timestamp, time_partitions);
 
-  _shared_gc_info.set_id(SharedGCInfo::UNSET_GCID);
+  _shared_gc_info.set_gc_id(GCId::undefined());
 }
 
 void GCTracer::report_gc_reference_stats(const ReferenceProcessorStats& rps) const {
@@ -132,7 +128,7 @@
     if (!cit.allocation_failed()) {
       HeapInspection hi(false, false, false, NULL);
       hi.populate_table(&cit, is_alive_cl);
-      ObjectCountEventSenderClosure event_sender(_shared_gc_info.id(), cit.size_of_instances_in_words(), Ticks::now());
+      ObjectCountEventSenderClosure event_sender(_shared_gc_info.gc_id(), cit.size_of_instances_in_words(), Ticks::now());
       cit.iterate(&event_sender);
     }
   }
diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp
index 3b55211..dd13344 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTrace.hpp
@@ -27,6 +27,7 @@
 
 #include "gc_interface/gcCause.hpp"
 #include "gc_interface/gcName.hpp"
+#include "gc_implementation/shared/gcId.hpp"
 #include "gc_implementation/shared/gcWhen.hpp"
 #include "gc_implementation/shared/copyFailedInfo.hpp"
 #include "memory/allocation.hpp"
@@ -38,7 +39,6 @@
 #include "utilities/macros.hpp"
 #include "utilities/ticks.hpp"
 
-typedef uint GCId;
 
 class EvacuationInfo;
 class GCHeapSummary;
@@ -50,11 +50,8 @@
 class BoolObjectClosure;
 
 class SharedGCInfo VALUE_OBJ_CLASS_SPEC {
- public:
-  static const GCId UNSET_GCID = (GCId)-1;
-
  private:
-  GCId _id;
+  GCId _gc_id;
   GCName _name;
   GCCause::Cause _cause;
   Ticks     _start_timestamp;
@@ -64,7 +61,7 @@
 
  public:
   SharedGCInfo(GCName name) :
-    _id(UNSET_GCID),
+    _gc_id(GCId::undefined()),
     _name(name),
     _cause(GCCause::_last_gc_cause),
     _start_timestamp(),
@@ -73,8 +70,8 @@
     _longest_pause() {
   }
 
-  void set_id(GCId id) { _id = id; }
-  GCId id() const { return _id; }
+  void set_gc_id(GCId gc_id) { _gc_id = gc_id; }
+  const GCId& gc_id() const { return _gc_id; }
 
   void set_start_timestamp(const Ticks& timestamp) { _start_timestamp = timestamp; }
   const Ticks start_timestamp() const { return _start_timestamp; }
@@ -131,10 +128,11 @@
   void report_gc_reference_stats(const ReferenceProcessorStats& rp) const;
   void report_object_count_after_gc(BoolObjectClosure* object_filter) NOT_SERVICES_RETURN;
   bool has_reported_gc_start() const;
+  const GCId& gc_id() { return _shared_gc_info.gc_id(); }
 
  protected:
   GCTracer(GCName name) : _shared_gc_info(name) {}
-  virtual void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp);
+  void report_gc_start_impl(GCCause::Cause cause, const Ticks& timestamp);
   virtual void report_gc_end_impl(const Ticks& timestamp, TimePartitions* time_partitions);
 
  private:
diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp
index 95ca83a..5462135 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp
@@ -43,7 +43,7 @@
 void GCTracer::send_garbage_collection_event() const {
   EventGCGarbageCollection event(UNTIMED);
   if (event.should_commit()) {
-    event.set_gcId(_shared_gc_info.id());
+    event.set_gcId(_shared_gc_info.gc_id().id());
     event.set_name(_shared_gc_info.name());
     event.set_cause((u2) _shared_gc_info.cause());
     event.set_sumOfPauses(_shared_gc_info.sum_of_pauses());
@@ -57,7 +57,7 @@
 void GCTracer::send_reference_stats_event(ReferenceType type, size_t count) const {
   EventGCReferenceStatistics e;
   if (e.should_commit()) {
-      e.set_gcId(_shared_gc_info.id());
+      e.set_gcId(_shared_gc_info.gc_id().id());
       e.set_type((u1)type);
       e.set_count(count);
       e.commit();
@@ -68,7 +68,7 @@
                                                       const MetaspaceChunkFreeListSummary& summary) const {
   EventMetaspaceChunkFreeListSummary e;
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_when(when);
     e.set_metadataType(mdtype);
 
@@ -91,7 +91,7 @@
 void ParallelOldTracer::send_parallel_old_event() const {
   EventGCParallelOld e(UNTIMED);
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_densePrefix((TraceAddress)_parallel_old_gc_info.dense_prefix());
     e.set_starttime(_shared_gc_info.start_timestamp());
     e.set_endtime(_shared_gc_info.end_timestamp());
@@ -102,7 +102,7 @@
 void YoungGCTracer::send_young_gc_event() const {
   EventGCYoungGarbageCollection e(UNTIMED);
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_tenuringThreshold(_tenuring_threshold);
     e.set_starttime(_shared_gc_info.start_timestamp());
     e.set_endtime(_shared_gc_info.end_timestamp());
@@ -113,7 +113,7 @@
 void OldGCTracer::send_old_gc_event() const {
   EventGCOldGarbageCollection e(UNTIMED);
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_starttime(_shared_gc_info.start_timestamp());
     e.set_endtime(_shared_gc_info.end_timestamp());
     e.commit();
@@ -132,7 +132,7 @@
 void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_info) const {
   EventPromotionFailed e;
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_data(to_trace_struct(pf_info));
     e.set_thread(pf_info.thread()->thread_id());
     e.commit();
@@ -143,7 +143,7 @@
 void OldGCTracer::send_concurrent_mode_failure_event() {
   EventConcurrentModeFailure e;
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.commit();
   }
 }
@@ -152,7 +152,7 @@
 void G1NewTracer::send_g1_young_gc_event() {
   EventGCG1GarbageCollection e(UNTIMED);
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_type(_g1_young_gc_info.type());
     e.set_starttime(_shared_gc_info.start_timestamp());
     e.set_endtime(_shared_gc_info.end_timestamp());
@@ -163,7 +163,7 @@
 void G1NewTracer::send_evacuation_info_event(EvacuationInfo* info) {
   EventEvacuationInfo e;
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_cSetRegions(info->collectionset_regions());
     e.set_cSetUsedBefore(info->collectionset_used_before());
     e.set_cSetUsedAfter(info->collectionset_used_after());
@@ -179,7 +179,7 @@
 void G1NewTracer::send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const {
   EventEvacuationFailed e;
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_data(to_trace_struct(ef_info));
     e.commit();
   }
@@ -206,17 +206,17 @@
 }
 
 class GCHeapSummaryEventSender : public GCHeapSummaryVisitor {
-  GCId _id;
+  GCId _gc_id;
   GCWhen::Type _when;
  public:
-  GCHeapSummaryEventSender(GCId id, GCWhen::Type when) : _id(id), _when(when) {}
+  GCHeapSummaryEventSender(GCId gc_id, GCWhen::Type when) : _gc_id(gc_id), _when(when) {}
 
   void visit(const GCHeapSummary* heap_summary) const {
     const VirtualSpaceSummary& heap_space = heap_summary->heap();
 
     EventGCHeapSummary e;
     if (e.should_commit()) {
-      e.set_gcId(_id);
+      e.set_gcId(_gc_id.id());
       e.set_when((u1)_when);
       e.set_heapSpace(to_trace_struct(heap_space));
       e.set_heapUsed(heap_summary->used());
@@ -236,7 +236,7 @@
 
     EventPSHeapSummary e;
     if (e.should_commit()) {
-      e.set_gcId(_id);
+      e.set_gcId(_gc_id.id());
       e.set_when((u1)_when);
 
       e.set_oldSpace(to_trace_struct(ps_heap_summary->old()));
@@ -251,7 +251,7 @@
 };
 
 void GCTracer::send_gc_heap_summary_event(GCWhen::Type when, const GCHeapSummary& heap_summary) const {
-  GCHeapSummaryEventSender visitor(_shared_gc_info.id(), when);
+  GCHeapSummaryEventSender visitor(_shared_gc_info.gc_id(), when);
   heap_summary.accept(&visitor);
 }
 
@@ -268,7 +268,7 @@
 void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const {
   EventMetaspaceSummary e;
   if (e.should_commit()) {
-    e.set_gcId(_shared_gc_info.id());
+    e.set_gcId(_shared_gc_info.gc_id().id());
     e.set_when((u1) when);
     e.set_gcThreshold(meta_space_summary.capacity_until_GC());
     e.set_metaspace(to_trace_struct(meta_space_summary.meta_space()));
@@ -287,7 +287,7 @@
   void send_phase(PausePhase* pause) {
     T event(UNTIMED);
     if (event.should_commit()) {
-      event.set_gcId(_gc_id);
+      event.set_gcId(_gc_id.id());
       event.set_name(pause->name());
       event.set_starttime(pause->start());
       event.set_endtime(pause->end());
@@ -311,7 +311,7 @@
 };
 
 void GCTracer::send_phase_events(TimePartitions* time_partitions) const {
-  PhaseSender phase_reporter(_shared_gc_info.id());
+  PhaseSender phase_reporter(_shared_gc_info.gc_id());
 
   TimePartitionPhasesIterator iter(time_partitions);
   while (iter.has_next()) {
diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp
index 033ca6b..8389061 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.cpp
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "gc_implementation/shared/gcTimer.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcTraceTime.hpp"
 #include "runtime/globals.hpp"
 #include "runtime/os.hpp"
@@ -34,7 +35,7 @@
 #include "utilities/ticks.inline.hpp"
 
 
-GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer) :
+GCTraceTime::GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id) :
     _title(title), _doit(doit), _print_cr(print_cr), _timer(timer), _start_counter() {
   if (_doit || _timer != NULL) {
     _start_counter.stamp();
@@ -52,6 +53,9 @@
       gclog_or_tty->stamp();
       gclog_or_tty->print(": ");
     }
+    if (PrintGCID) {
+      gclog_or_tty->print("#%u: ", gc_id.id());
+    }
     gclog_or_tty->print("[%s", title);
     gclog_or_tty->flush();
   }
diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp
index 83df182..30e494b 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceTime.hpp
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_SHARED_GCTRACETIME_HPP
 
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "prims/jni_md.h"
 #include "utilities/ticks.hpp"
 
@@ -38,7 +39,7 @@
   Ticks _start_counter;
 
  public:
-  GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer);
+  GCTraceTime(const char* title, bool doit, bool print_cr, GCTimer* timer, GCId gc_id);
   ~GCTraceTime();
 };
 
diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp
index d262695..e2629b6 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.cpp
@@ -49,27 +49,19 @@
 SerialOldTracer*        MarkSweep::_gc_tracer       = NULL;
 
 MarkSweep::FollowRootClosure  MarkSweep::follow_root_closure;
-CodeBlobToOopClosure MarkSweep::follow_code_root_closure(&MarkSweep::follow_root_closure, /*do_marking=*/ true);
 
 void MarkSweep::FollowRootClosure::do_oop(oop* p)       { follow_root(p); }
 void MarkSweep::FollowRootClosure::do_oop(narrowOop* p) { follow_root(p); }
 
 MarkSweep::MarkAndPushClosure MarkSweep::mark_and_push_closure;
-MarkSweep::FollowKlassClosure MarkSweep::follow_klass_closure;
-MarkSweep::AdjustKlassClosure MarkSweep::adjust_klass_closure;
+CLDToOopClosure               MarkSweep::follow_cld_closure(&mark_and_push_closure);
+CLDToOopClosure               MarkSweep::adjust_cld_closure(&adjust_pointer_closure);
 
 void MarkSweep::MarkAndPushClosure::do_oop(oop* p)       { mark_and_push(p); }
 void MarkSweep::MarkAndPushClosure::do_oop(narrowOop* p) { mark_and_push(p); }
 
-void MarkSweep::FollowKlassClosure::do_klass(Klass* klass) {
-  klass->oops_do(&MarkSweep::mark_and_push_closure);
-}
-void MarkSweep::AdjustKlassClosure::do_klass(Klass* klass) {
-  klass->oops_do(&MarkSweep::adjust_pointer_closure);
-}
-
 void MarkSweep::follow_class_loader(ClassLoaderData* cld) {
-  cld->oops_do(&MarkSweep::mark_and_push_closure, &MarkSweep::follow_klass_closure, true);
+  MarkSweep::follow_cld_closure.do_cld(cld);
 }
 
 void MarkSweep::follow_stack() {
diff --git a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp
index 38fc8e7..462643e 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/markSweep.hpp
@@ -65,17 +65,6 @@
     virtual void do_oop(narrowOop* p);
   };
 
-  // The one and only place to start following the classes.
-  // Should only be applied to the ClassLoaderData klasses list.
-  class FollowKlassClosure : public KlassClosure {
-   public:
-    void do_klass(Klass* klass);
-  };
-  class AdjustKlassClosure : public KlassClosure {
-   public:
-    void do_klass(Klass* klass);
-  };
-
   class FollowStackClosure: public VoidClosure {
    public:
     virtual void do_void();
@@ -143,12 +132,11 @@
   // Public closures
   static IsAliveClosure       is_alive;
   static FollowRootClosure    follow_root_closure;
-  static CodeBlobToOopClosure follow_code_root_closure; // => follow_root_closure
   static MarkAndPushClosure   mark_and_push_closure;
-  static FollowKlassClosure   follow_klass_closure;
   static FollowStackClosure   follow_stack_closure;
+  static CLDToOopClosure      follow_cld_closure;
   static AdjustPointerClosure adjust_pointer_closure;
-  static AdjustKlassClosure   adjust_klass_closure;
+  static CLDToOopClosure      adjust_cld_closure;
 
   // Accessors
   static uint total_invocations() { return _total_invocations; }
diff --git a/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp
index 7504a21..4e0dc60 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/objectCountEventSender.cpp
@@ -24,6 +24,7 @@
 
 
 #include "precompiled.hpp"
+#include "gc_implementation/shared/gcId.hpp"
 #include "gc_implementation/shared/objectCountEventSender.hpp"
 #include "memory/heapInspection.hpp"
 #include "trace/tracing.hpp"
@@ -38,7 +39,7 @@
          "Only call this method if the event is enabled");
 
   EventObjectCountAfterGC event(UNTIMED);
-  event.set_gcId(gc_id);
+  event.set_gcId(gc_id.id());
   event.set_class(entry->klass());
   event.set_count(entry->count());
   event.set_totalSize(entry->words() * BytesPerWord);
diff --git a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp
index aac3e98..9bce2a3 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.hpp
@@ -24,7 +24,7 @@
 
 #ifndef SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
 #define SHARE_VM_GC_IMPLEMENTATION_PARNEW_PARGCALLOCBUFFER_HPP
-
+#include "gc_interface/collectedHeap.hpp"
 #include "memory/allocation.hpp"
 #include "memory/blockOffsetTable.hpp"
 #include "memory/threadLocalAllocBuffer.hpp"
@@ -60,6 +60,7 @@
   // Initializes the buffer to be empty, but with the given "word_sz".
   // Must get initialized with "set_buf" for an allocation to succeed.
   ParGCAllocBuffer(size_t word_sz);
+  virtual ~ParGCAllocBuffer() {}
 
   static const size_t min_size() {
     return ThreadLocalAllocBuffer::min_size();
@@ -83,6 +84,9 @@
     }
   }
 
+  // Allocate the object aligned to "alignment_in_bytes".
+  HeapWord* allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes);
+
   // Undo the last allocation in the buffer, which is required to be of the
   // "obj" of the given "word_sz".
   void undo_allocation(HeapWord* obj, size_t word_sz) {
@@ -113,7 +117,7 @@
   }
 
   // Sets the space of the buffer to be [buf, space+word_sz()).
-  void set_buf(HeapWord* buf) {
+  virtual void set_buf(HeapWord* buf) {
     _bottom   = buf;
     _top      = _bottom;
     _hard_end = _bottom + word_sz();
@@ -158,7 +162,7 @@
   // Fills in the unallocated portion of the buffer with a garbage object.
   // If "end_of_gc" is TRUE, is after the last use in the GC.  IF "retain"
   // is true, attempt to re-use the unused portion in the next GC.
-  void retire(bool end_of_gc, bool retain);
+  virtual void retire(bool end_of_gc, bool retain);
 
   void print() PRODUCT_RETURN;
 };
@@ -238,14 +242,14 @@
 
   void undo_allocation(HeapWord* obj, size_t word_sz);
 
-  void set_buf(HeapWord* buf_start) {
+  virtual void set_buf(HeapWord* buf_start) {
     ParGCAllocBuffer::set_buf(buf_start);
     _true_end = _hard_end;
     _bt.set_region(MemRegion(buf_start, word_sz()));
     _bt.initialize_threshold();
   }
 
-  void retire(bool end_of_gc, bool retain);
+  virtual void retire(bool end_of_gc, bool retain);
 
   MemRegion range() {
     return MemRegion(_top, _true_end);
diff --git a/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp
new file mode 100644
index 0000000..352ce05
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/shared/parGCAllocBuffer.inline.hpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
+
+#include "gc_implementation/shared/parGCAllocBuffer.hpp"
+#include "gc_interface/collectedHeap.inline.hpp"
+
+HeapWord* ParGCAllocBuffer::allocate_aligned(size_t word_sz, unsigned short alignment_in_bytes) {
+
+  HeapWord* res = CollectedHeap::align_allocation_or_fail(_top, _end, alignment_in_bytes);
+  if (res == NULL) {
+    return NULL;
+  }
+
+  // Set _top so that allocate(), which expects _top to be correctly set,
+  // can be used below.
+  _top = res;
+  return allocate(word_sz);
+}
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_PARGCALLOCBUFFER_INLINE_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp
new file mode 100644
index 0000000..6bb7197
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "gc_implementation/shared/suspendibleThreadSet.hpp"
+#include "runtime/mutexLocker.hpp"
+#include "runtime/thread.inline.hpp"
+
+uint   SuspendibleThreadSet::_nthreads          = 0;
+uint   SuspendibleThreadSet::_nthreads_stopped  = 0;
+bool   SuspendibleThreadSet::_suspend_all       = false;
+double SuspendibleThreadSet::_suspend_all_start = 0.0;
+
+void SuspendibleThreadSet::join() {
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  while (_suspend_all) {
+    ml.wait(Mutex::_no_safepoint_check_flag);
+  }
+  _nthreads++;
+}
+
+void SuspendibleThreadSet::leave() {
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  assert(_nthreads > 0, "Invalid");
+  _nthreads--;
+  if (_suspend_all) {
+    ml.notify_all();
+  }
+}
+
+void SuspendibleThreadSet::yield() {
+  if (_suspend_all) {
+    MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+    if (_suspend_all) {
+      _nthreads_stopped++;
+      if (_nthreads_stopped == _nthreads) {
+        if (ConcGCYieldTimeout > 0) {
+          double now = os::elapsedTime();
+          guarantee((now - _suspend_all_start) * 1000.0 < (double)ConcGCYieldTimeout, "Long delay");
+        }
+      }
+      ml.notify_all();
+      while (_suspend_all) {
+        ml.wait(Mutex::_no_safepoint_check_flag);
+      }
+      assert(_nthreads_stopped > 0, "Invalid");
+      _nthreads_stopped--;
+      ml.notify_all();
+    }
+  }
+}
+
+void SuspendibleThreadSet::synchronize() {
+  assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
+  if (ConcGCYieldTimeout > 0) {
+    _suspend_all_start = os::elapsedTime();
+  }
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  assert(!_suspend_all, "Only one at a time");
+  _suspend_all = true;
+  while (_nthreads_stopped < _nthreads) {
+    ml.wait(Mutex::_no_safepoint_check_flag);
+  }
+}
+
+void SuspendibleThreadSet::desynchronize() {
+  assert(Thread::current()->is_VM_thread(), "Must be the VM thread");
+  MonitorLockerEx ml(STS_lock, Mutex::_no_safepoint_check_flag);
+  assert(_nthreads_stopped == _nthreads, "Invalid");
+  _suspend_all = false;
+  ml.notify_all();
+}
diff --git a/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp
new file mode 100644
index 0000000..5d76ef2
--- /dev/null
+++ b/hotspot/src/share/vm/gc_implementation/shared/suspendibleThreadSet.hpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
+#define SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
+
+#include "memory/allocation.hpp"
+
+// A SuspendibleThreadSet is a set of threads that can be suspended.
+// A thread can join and later leave the set, and periodically yield.
+// If some thread (not in the set) requests, via synchronize(), that
+// the threads be suspended, then the requesting thread is blocked
+// until all the threads in the set have yielded or left the set. Threads
+// may not enter the set when an attempted suspension is in progress. The
+// suspending thread later calls desynchronize(), allowing the suspended
+// threads to continue.
+class SuspendibleThreadSet : public AllStatic {
+private:
+  static uint   _nthreads;
+  static uint   _nthreads_stopped;
+  static bool   _suspend_all;
+  static double _suspend_all_start;
+
+public:
+  // Add the current thread to the set. May block if a suspension is in progress.
+  static void join();
+
+  // Removes the current thread from the set.
+  static void leave();
+
+  // Returns true if an suspension is in progress.
+  static bool should_yield() { return _suspend_all; }
+
+  // Suspends the current thread if a suspension is in progress.
+  static void yield();
+
+  // Returns when all threads in the set are suspended.
+  static void synchronize();
+
+  // Resumes all suspended threads in the set.
+  static void desynchronize();
+};
+
+class SuspendibleThreadSetJoiner : public StackObj {
+public:
+  SuspendibleThreadSetJoiner() {
+    SuspendibleThreadSet::join();
+  }
+
+  ~SuspendibleThreadSetJoiner() {
+    SuspendibleThreadSet::leave();
+  }
+
+  bool should_yield() {
+    return SuspendibleThreadSet::should_yield();
+  }
+
+  void yield() {
+    SuspendibleThreadSet::yield();
+  }
+};
+
+#endif // SHARE_VM_GC_IMPLEMENTATION_SHARED_SUSPENDIBLETHREADSET_HPP
diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
index d901ddf..ea1760e 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -209,6 +209,45 @@
   gch->do_full_collection(gch->must_clear_all_soft_refs(), _max_level);
 }
 
+// Returns true iff concurrent GCs unloads metadata.
+bool VM_CollectForMetadataAllocation::initiate_concurrent_GC() {
+#if INCLUDE_ALL_GCS
+  if (UseConcMarkSweepGC && CMSClassUnloadingEnabled) {
+    MetaspaceGC::set_should_concurrent_collect(true);
+    return true;
+  }
+
+  if (UseG1GC && ClassUnloadingWithConcurrentMark) {
+    G1CollectedHeap* g1h = G1CollectedHeap::heap();
+    g1h->g1_policy()->set_initiate_conc_mark_if_possible();
+
+    GCCauseSetter x(g1h, _gc_cause);
+
+    // At this point we are supposed to start a concurrent cycle. We
+    // will do so if one is not already in progress.
+    bool should_start = g1h->g1_policy()->force_initial_mark_if_outside_cycle(_gc_cause);
+
+    if (should_start) {
+      double pause_target = g1h->g1_policy()->max_pause_time_ms();
+      g1h->do_collection_pause_at_safepoint(pause_target);
+    }
+    return true;
+  }
+#endif
+
+  return false;
+}
+
+static void log_metaspace_alloc_failure_for_concurrent_GC() {
+  if (Verbose && PrintGCDetails) {
+    if (UseConcMarkSweepGC) {
+      gclog_or_tty->print_cr("\nCMS full GC for Metaspace");
+    } else if (UseG1GC) {
+      gclog_or_tty->print_cr("\nG1 full GC for Metaspace");
+    }
+  }
+}
+
 void VM_CollectForMetadataAllocation::doit() {
   SvcGCMarker sgcm(SvcGCMarker::FULL);
 
@@ -220,54 +259,57 @@
   // a GC that freed space for the allocation.
   if (!MetadataAllocationFailALot) {
     _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
-  }
-
-  if (_result == NULL) {
-    if (UseConcMarkSweepGC) {
-      if (CMSClassUnloadingEnabled) {
-        MetaspaceGC::set_should_concurrent_collect(true);
-      }
-      // For CMS expand since the collection is going to be concurrent.
-      _result =
-        _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype);
-    }
-    if (_result == NULL) {
-      // Don't clear the soft refs yet.
-      if (Verbose && PrintGCDetails && UseConcMarkSweepGC) {
-        gclog_or_tty->print_cr("\nCMS full GC for Metaspace");
-      }
-      heap->collect_as_vm_thread(GCCause::_metadata_GC_threshold);
-      // After a GC try to allocate without expanding.  Could fail
-      // and expansion will be tried below.
-      _result =
-        _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
-    }
-    if (_result == NULL) {
-      // If still failing, allow the Metaspace to expand.
-      // See delta_capacity_until_GC() for explanation of the
-      // amount of the expansion.
-      // This should work unless there really is no more space
-      // or a MaxMetaspaceSize has been specified on the command line.
-      _result =
-        _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype);
-      if (_result == NULL) {
-        // If expansion failed, do a last-ditch collection and try allocating
-        // again.  A last-ditch collection will clear softrefs.  This
-        // behavior is similar to the last-ditch collection done for perm
-        // gen when it was full and a collection for failed allocation
-        // did not free perm gen space.
-        heap->collect_as_vm_thread(GCCause::_last_ditch_collection);
-        _result =
-          _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
-      }
-    }
-    if (Verbose && PrintGCDetails && _result == NULL) {
-      gclog_or_tty->print_cr("\nAfter Metaspace GC failed to allocate size "
-                             SIZE_FORMAT, _size);
+    if (_result != NULL) {
+      return;
     }
   }
 
-  if (_result == NULL && GC_locker::is_active_and_needs_gc()) {
+  if (initiate_concurrent_GC()) {
+    // For CMS and G1 expand since the collection is going to be concurrent.
+    _result = _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype);
+    if (_result != NULL) {
+      return;
+    }
+
+    log_metaspace_alloc_failure_for_concurrent_GC();
+  }
+
+  // Don't clear the soft refs yet.
+  heap->collect_as_vm_thread(GCCause::_metadata_GC_threshold);
+  // After a GC try to allocate without expanding.  Could fail
+  // and expansion will be tried below.
+  _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
+  if (_result != NULL) {
+    return;
+  }
+
+  // If still failing, allow the Metaspace to expand.
+  // See delta_capacity_until_GC() for explanation of the
+  // amount of the expansion.
+  // This should work unless there really is no more space
+  // or a MaxMetaspaceSize has been specified on the command line.
+  _result = _loader_data->metaspace_non_null()->expand_and_allocate(_size, _mdtype);
+  if (_result != NULL) {
+    return;
+  }
+
+  // If expansion failed, do a last-ditch collection and try allocating
+  // again.  A last-ditch collection will clear softrefs.  This
+  // behavior is similar to the last-ditch collection done for perm
+  // gen when it was full and a collection for failed allocation
+  // did not free perm gen space.
+  heap->collect_as_vm_thread(GCCause::_last_ditch_collection);
+  _result = _loader_data->metaspace_non_null()->allocate(_size, _mdtype);
+  if (_result != NULL) {
+    return;
+  }
+
+  if (Verbose && PrintGCDetails) {
+    gclog_or_tty->print_cr("\nAfter Metaspace GC failed to allocate size "
+                           SIZE_FORMAT, _size);
+  }
+
+  if (GC_locker::is_active_and_needs_gc()) {
     set_gc_locked();
   }
 }
diff --git a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp
index 82cbf23..8f60dcb 100644
--- a/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp
+++ b/hotspot/src/share/vm/gc_implementation/shared/vmGCOperations.hpp
@@ -217,6 +217,8 @@
   virtual VMOp_Type type() const { return VMOp_CollectForMetadataAllocation; }
   virtual void doit();
   MetaWord* result() const       { return _result; }
+
+  bool initiate_concurrent_GC();
 };
 
 class SvcGCMarker : public StackObj {
diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp
index 1304092..ddad402 100644
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp
@@ -558,13 +558,13 @@
 
 void CollectedHeap::pre_full_gc_dump(GCTimer* timer) {
   if (HeapDumpBeforeFullGC) {
-    GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer);
+    GCTraceTime tt("Heap Dump (before full gc): ", PrintGCDetails, false, timer, GCId::create());
     // We are doing a "major" collection and a heap dump before
     // major collection has been requested.
     HeapDumper::dump_heap();
   }
   if (PrintClassHistogramBeforeFullGC) {
-    GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer);
+    GCTraceTime tt("Class Histogram (before full gc): ", PrintGCDetails, true, timer, GCId::create());
     VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */);
     inspector.doit();
   }
@@ -572,11 +572,11 @@
 
 void CollectedHeap::post_full_gc_dump(GCTimer* timer) {
   if (HeapDumpAfterFullGC) {
-    GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer);
+    GCTraceTime tt("Heap Dump (after full gc): ", PrintGCDetails, false, timer, GCId::create());
     HeapDumper::dump_heap();
   }
   if (PrintClassHistogramAfterFullGC) {
-    GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer);
+    GCTraceTime tt("Class Histogram (after full gc): ", PrintGCDetails, true, timer, GCId::create());
     VM_GC_HeapInspection inspector(gclog_or_tty, false /* ! full gc */);
     inspector.doit();
   }
diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp
index 4b56f00..d4fa7ff 100644
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.hpp
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.hpp
@@ -351,6 +351,12 @@
     fill_with_object(start, pointer_delta(end, start), zap);
   }
 
+  // Return the address "addr" aligned by "alignment_in_bytes" if such
+  // an address is below "end".  Return NULL otherwise.
+  inline static HeapWord* align_allocation_or_fail(HeapWord* addr,
+                                                   HeapWord* end,
+                                                   unsigned short alignment_in_bytes);
+
   // Some heaps may offer a contiguous region for shared non-blocking
   // allocation, via inlined code (by exporting the address of the top and
   // end fields defining the extent of the contiguous allocation region.)
@@ -389,15 +395,6 @@
   // allocation from them and necessitating allocation of new TLABs.
   virtual void ensure_parsability(bool retire_tlabs);
 
-  // Return an estimate of the maximum allocation that could be performed
-  // without triggering any collection or expansion activity.  In a
-  // generational collector, for example, this is probably the largest
-  // allocation that could be supported (without expansion) in the youngest
-  // generation.  It is "unsafe" because no locks are taken; the result
-  // should be treated as an approximation, not a guarantee, for use in
-  // heuristic resizing decisions.
-  virtual size_t unsafe_max_alloc() = 0;
-
   // Section on thread-local allocation buffers (TLABs)
   // If the heap supports thread-local allocation buffers, it should override
   // the following methods:
diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp
index 89315a9..302d0c7 100644
--- a/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp
+++ b/hotspot/src/share/vm/gc_interface/collectedHeap.inline.hpp
@@ -241,6 +241,44 @@
   oop_iterate(&no_header_cl);
 }
 
+
+inline HeapWord* CollectedHeap::align_allocation_or_fail(HeapWord* addr,
+                                                         HeapWord* end,
+                                                         unsigned short alignment_in_bytes) {
+  if (alignment_in_bytes <= ObjectAlignmentInBytes) {
+    return addr;
+  }
+
+  assert(is_ptr_aligned(addr, HeapWordSize),
+    err_msg("Address " PTR_FORMAT " is not properly aligned.", p2i(addr)));
+  assert(is_size_aligned(alignment_in_bytes, HeapWordSize),
+    err_msg("Alignment size %u is incorrect.", alignment_in_bytes));
+
+  HeapWord* new_addr = (HeapWord*) align_pointer_up(addr, alignment_in_bytes);
+  size_t padding = pointer_delta(new_addr, addr);
+
+  if (padding == 0) {
+    return addr;
+  }
+
+  if (padding < CollectedHeap::min_fill_size()) {
+    padding += alignment_in_bytes / HeapWordSize;
+    assert(padding >= CollectedHeap::min_fill_size(),
+      err_msg("alignment_in_bytes %u is expect to be larger "
+      "than the minimum object size", alignment_in_bytes));
+    new_addr = addr + padding;
+  }
+
+  assert(new_addr > addr, err_msg("Unexpected arithmetic overflow "
+    PTR_FORMAT " not greater than " PTR_FORMAT, p2i(new_addr), p2i(addr)));
+  if(new_addr < end) {
+    CollectedHeap::fill_with_object(addr, padding);
+    return new_addr;
+  } else {
+    return NULL;
+  }
+}
+
 #ifndef PRODUCT
 
 inline bool
diff --git a/hotspot/src/share/vm/gc_interface/gcCause.cpp b/hotspot/src/share/vm/gc_interface/gcCause.cpp
index 2588621..879bce1 100644
--- a/hotspot/src/share/vm/gc_interface/gcCause.cpp
+++ b/hotspot/src/share/vm/gc_interface/gcCause.cpp
@@ -51,6 +51,9 @@
     case _heap_dump:
       return "Heap Dump Initiated GC";
 
+    case _wb_young_gc:
+      return "WhiteBox Initiated Young GC";
+
     case _no_gc:
       return "No GC";
 
diff --git a/hotspot/src/share/vm/gc_interface/gcCause.hpp b/hotspot/src/share/vm/gc_interface/gcCause.hpp
index 809bab4..3104f67 100644
--- a/hotspot/src/share/vm/gc_interface/gcCause.hpp
+++ b/hotspot/src/share/vm/gc_interface/gcCause.hpp
@@ -46,6 +46,7 @@
     _gc_locker,
     _heap_inspection,
     _heap_dump,
+    _wb_young_gc,
 
     /* implementation independent, but reserved for GC use */
     _no_gc,
diff --git a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
index 06261c8..94d9804 100644
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
@@ -41,43 +41,10 @@
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/threadCritical.hpp"
 #include "utilities/exceptions.hpp"
-#ifdef TARGET_OS_ARCH_linux_x86
-# include "orderAccess_linux_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_sparc
-# include "orderAccess_linux_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_zero
-# include "orderAccess_linux_zero.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_x86
-# include "orderAccess_solaris_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_sparc
-# include "orderAccess_solaris_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_windows_x86
-# include "orderAccess_windows_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_arm
-# include "orderAccess_linux_arm.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_ppc
-# include "orderAccess_linux_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_aix_ppc
-# include "orderAccess_aix_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_x86
-# include "orderAccess_bsd_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_zero
-# include "orderAccess_bsd_zero.inline.hpp"
-#endif
-
 
 // no precompiled headers
 #ifdef CC_INTERP
diff --git a/hotspot/src/share/vm/memory/allocation.cpp b/hotspot/src/share/vm/memory/allocation.cpp
index 5bc2bc1..97143e8 100644
--- a/hotspot/src/share/vm/memory/allocation.cpp
+++ b/hotspot/src/share/vm/memory/allocation.cpp
@@ -438,24 +438,22 @@
 }
 
 //------------------------------Arena------------------------------------------
-NOT_PRODUCT(volatile jint Arena::_instance_count = 0;)
-
-Arena::Arena(size_t init_size) {
+Arena::Arena(MEMFLAGS flag, size_t init_size) : _flags(flag), _size_in_bytes(0)  {
   size_t round_size = (sizeof (char *)) - 1;
   init_size = (init_size+round_size) & ~round_size;
   _first = _chunk = new (AllocFailStrategy::EXIT_OOM, init_size) Chunk(init_size);
   _hwm = _chunk->bottom();      // Save the cached hwm, max
   _max = _chunk->top();
+  MemTracker::record_new_arena(flag);
   set_size_in_bytes(init_size);
-  NOT_PRODUCT(Atomic::inc(&_instance_count);)
 }
 
-Arena::Arena() {
+Arena::Arena(MEMFLAGS flag) : _flags(flag), _size_in_bytes(0) {
   _first = _chunk = new (AllocFailStrategy::EXIT_OOM, Chunk::init_size) Chunk(Chunk::init_size);
   _hwm = _chunk->bottom();      // Save the cached hwm, max
   _max = _chunk->top();
+  MemTracker::record_new_arena(flag);
   set_size_in_bytes(Chunk::init_size);
-  NOT_PRODUCT(Atomic::inc(&_instance_count);)
 }
 
 Arena *Arena::move_contents(Arena *copy) {
@@ -477,7 +475,7 @@
 
 Arena::~Arena() {
   destruct_contents();
-  NOT_PRODUCT(Atomic::dec(&_instance_count);)
+  MemTracker::record_arena_free(_flags);
 }
 
 void* Arena::operator new(size_t size) throw() {
@@ -493,21 +491,21 @@
   // dynamic memory type binding
 void* Arena::operator new(size_t size, MEMFLAGS flags) throw() {
 #ifdef ASSERT
-  void* p = (void*)AllocateHeap(size, flags|otArena, CALLER_PC);
+  void* p = (void*)AllocateHeap(size, flags, CALLER_PC);
   if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
   return p;
 #else
-  return (void *) AllocateHeap(size, flags|otArena, CALLER_PC);
+  return (void *) AllocateHeap(size, flags, CALLER_PC);
 #endif
 }
 
 void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw() {
 #ifdef ASSERT
-  void* p = os::malloc(size, flags|otArena, CALLER_PC);
+  void* p = os::malloc(size, flags, CALLER_PC);
   if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p);
   return p;
 #else
-  return os::malloc(size, flags|otArena, CALLER_PC);
+  return os::malloc(size, flags, CALLER_PC);
 #endif
 }
 
@@ -532,8 +530,9 @@
 // change the size
 void Arena::set_size_in_bytes(size_t size) {
   if (_size_in_bytes != size) {
+    long delta = (long)(size - size_in_bytes());
     _size_in_bytes = size;
-    MemTracker::record_arena_size((address)this, size);
+    MemTracker::record_arena_size_change(delta, _flags);
   }
 }
 
diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp
index d635a07..0223117 100644
--- a/hotspot/src/share/vm/memory/allocation.hpp
+++ b/hotspot/src/share/vm/memory/allocation.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -133,51 +133,34 @@
 
 
 /*
- * MemoryType bitmap layout:
- * | 16 15 14 13 12 11 10 09 | 08 07 06 05 | 04 03 02 01 |
- * |      memory type        |   object    | reserved    |
- * |                         |     type    |             |
+ * Memory types
  */
 enum MemoryType {
   // Memory type by sub systems. It occupies lower byte.
-  mtNone              = 0x0000,  // undefined
-  mtClass             = 0x0100,  // memory class for Java classes
-  mtThread            = 0x0200,  // memory for thread objects
-  mtThreadStack       = 0x0300,
-  mtCode              = 0x0400,  // memory for generated code
-  mtGC                = 0x0500,  // memory for GC
-  mtCompiler          = 0x0600,  // memory for compiler
-  mtInternal          = 0x0700,  // memory used by VM, but does not belong to
+  mtJavaHeap          = 0x00,  // Java heap
+  mtClass             = 0x01,  // memory class for Java classes
+  mtThread            = 0x02,  // memory for thread objects
+  mtThreadStack       = 0x03,
+  mtCode              = 0x04,  // memory for generated code
+  mtGC                = 0x05,  // memory for GC
+  mtCompiler          = 0x06,  // memory for compiler
+  mtInternal          = 0x07,  // memory used by VM, but does not belong to
                                  // any of above categories, and not used for
                                  // native memory tracking
-  mtOther             = 0x0800,  // memory not used by VM
-  mtSymbol            = 0x0900,  // symbol
-  mtNMT               = 0x0A00,  // memory used by native memory tracking
-  mtChunk             = 0x0B00,  // chunk that holds content of arenas
-  mtJavaHeap          = 0x0C00,  // Java heap
-  mtClassShared       = 0x0D00,  // class data sharing
-  mtTest              = 0x0E00,  // Test type for verifying NMT
-  mtTracing           = 0x0F00,  // memory used for Tracing
-  mt_number_of_types  = 0x000F,  // number of memory types (mtDontTrack
+  mtOther             = 0x08,  // memory not used by VM
+  mtSymbol            = 0x09,  // symbol
+  mtNMT               = 0x0A,  // memory used by native memory tracking
+  mtClassShared       = 0x0B,  // class data sharing
+  mtChunk             = 0x0C,  // chunk that holds content of arenas
+  mtTest              = 0x0D,  // Test type for verifying NMT
+  mtTracing           = 0x0E,  // memory used for Tracing
+  mtNone              = 0x0F,  // undefined
+  mt_number_of_types  = 0x10   // number of memory types (mtDontTrack
                                  // is not included as validate type)
-  mtDontTrack         = 0x0F00,  // memory we do not or cannot track
-  mt_masks            = 0x7F00,
-
-  // object type mask
-  otArena             = 0x0010, // an arena object
-  otNMTRecorder       = 0x0020, // memory recorder object
-  ot_masks            = 0x00F0
 };
 
-#define IS_MEMORY_TYPE(flags, type) ((flags & mt_masks) == type)
-#define HAS_VALID_MEMORY_TYPE(flags)((flags & mt_masks) != mtNone)
-#define FLAGS_TO_MEMORY_TYPE(flags) (flags & mt_masks)
+typedef MemoryType MEMFLAGS;
 
-#define IS_ARENA_OBJ(flags)         ((flags & ot_masks) == otArena)
-#define IS_NMT_RECORDER(flags)      ((flags & ot_masks) == otNMTRecorder)
-#define NMT_CAN_TRACK(flags)        (!IS_NMT_RECORDER(flags) && !(IS_MEMORY_TYPE(flags, mtDontTrack)))
-
-typedef unsigned short MEMFLAGS;
 
 #if INCLUDE_NMT
 
@@ -189,27 +172,23 @@
 
 #endif // INCLUDE_NMT
 
-// debug build does not inline
-#if defined(_NMT_NOINLINE_)
-  #define CURRENT_PC       (NMT_track_callsite ? os::get_caller_pc(1) : 0)
-  #define CALLER_PC        (NMT_track_callsite ? os::get_caller_pc(2) : 0)
-  #define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(3) : 0)
-#else
-  #define CURRENT_PC      (NMT_track_callsite? os::get_caller_pc(0) : 0)
-  #define CALLER_PC       (NMT_track_callsite ? os::get_caller_pc(1) : 0)
-  #define CALLER_CALLER_PC (NMT_track_callsite ? os::get_caller_pc(2) : 0)
-#endif
-
+class NativeCallStack;
 
 
 template <MEMFLAGS F> class CHeapObj ALLOCATION_SUPER_CLASS_SPEC {
  public:
-  _NOINLINE_ void* operator new(size_t size, address caller_pc = 0) throw();
+  _NOINLINE_ void* operator new(size_t size, const NativeCallStack& stack) throw();
+  _NOINLINE_ void* operator new(size_t size) throw();
   _NOINLINE_ void* operator new (size_t size, const std::nothrow_t&  nothrow_constant,
-                               address caller_pc = 0) throw();
-  _NOINLINE_ void* operator new [](size_t size, address caller_pc = 0) throw();
+                               const NativeCallStack& stack) throw();
+  _NOINLINE_ void* operator new (size_t size, const std::nothrow_t&  nothrow_constant)
+                               throw();
+  _NOINLINE_ void* operator new [](size_t size, const NativeCallStack& stack) throw();
+  _NOINLINE_ void* operator new [](size_t size) throw();
   _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t&  nothrow_constant,
-                               address caller_pc = 0) throw();
+                               const NativeCallStack& stack) throw();
+  _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t&  nothrow_constant)
+                               throw();
   void  operator delete(void* p);
   void  operator delete [] (void* p);
 };
@@ -384,13 +363,15 @@
 
 //------------------------------Arena------------------------------------------
 // Fast allocation of memory
-class Arena : public CHeapObj<mtNone|otArena> {
+class Arena : public CHeapObj<mtNone> {
 protected:
   friend class ResourceMark;
   friend class HandleMark;
   friend class NoHandleMark;
   friend class VMStructs;
 
+  MEMFLAGS    _flags;           // Memory tracking flags
+
   Chunk *_first;                // First chunk
   Chunk *_chunk;                // current chunk
   char *_hwm, *_max;            // High water mark and max in current chunk
@@ -418,8 +399,8 @@
  }
 
  public:
-  Arena();
-  Arena(size_t init_size);
+  Arena(MEMFLAGS memflag);
+  Arena(MEMFLAGS memflag, size_t init_size);
   ~Arena();
   void  destruct_contents();
   char* hwm() const             { return _hwm; }
@@ -518,8 +499,6 @@
   static void free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2)  PRODUCT_RETURN;
   static void free_all(char** start, char** end)                                     PRODUCT_RETURN;
 
-  // how many arena instances
-  NOT_PRODUCT(static volatile jint _instance_count;)
 private:
   // Reset this Arena to empty, access will trigger grow if necessary
   void   reset(void) {
@@ -681,7 +660,7 @@
   NEW_C_HEAP_ARRAY3(type, (size), memflags, pc, AllocFailStrategy::RETURN_NULL)
 
 #define NEW_C_HEAP_ARRAY_RETURN_NULL(type, size, memflags)\
-  NEW_C_HEAP_ARRAY3(type, (size), memflags, (address)0, AllocFailStrategy::RETURN_NULL)
+  NEW_C_HEAP_ARRAY3(type, (size), memflags, CURRENT_PC, AllocFailStrategy::RETURN_NULL)
 
 #define REALLOC_C_HEAP_ARRAY(type, old, size, memflags)\
   (type*) (ReallocateHeap((char*)(old), (size) * sizeof(type), memflags))
diff --git a/hotspot/src/share/vm/memory/allocation.inline.hpp b/hotspot/src/share/vm/memory/allocation.inline.hpp
index d8f1940..d527237 100644
--- a/hotspot/src/share/vm/memory/allocation.inline.hpp
+++ b/hotspot/src/share/vm/memory/allocation.inline.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -27,6 +27,7 @@
 
 #include "runtime/atomic.inline.hpp"
 #include "runtime/os.hpp"
+#include "services/memTracker.hpp"
 
 // Explicit C-heap memory management
 
@@ -49,12 +50,10 @@
 #endif
 
 // allocate using malloc; will fail if no memory available
-inline char* AllocateHeap(size_t size, MEMFLAGS flags, address pc = 0,
+inline char* AllocateHeap(size_t size, MEMFLAGS flags,
+    const NativeCallStack& stack,
     AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
-  if (pc == 0) {
-    pc = CURRENT_PC;
-  }
-  char* p = (char*) os::malloc(size, flags, pc);
+  char* p = (char*) os::malloc(size, flags, stack);
   #ifdef ASSERT
   if (PrintMallocFree) trace_heap_malloc(size, "AllocateHeap", p);
   #endif
@@ -63,10 +62,14 @@
   }
   return p;
 }
-
-inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flags,
+inline char* AllocateHeap(size_t size, MEMFLAGS flags,
     AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
-  char* p = (char*) os::realloc(old, size, flags, CURRENT_PC);
+  return AllocateHeap(size, flags, CURRENT_PC, alloc_failmode);
+}
+
+inline char* ReallocateHeap(char *old, size_t size, MEMFLAGS flag,
+    AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) {
+  char* p = (char*) os::realloc(old, size, flag, CURRENT_PC);
   #ifdef ASSERT
   if (PrintMallocFree) trace_heap_malloc(size, "ReallocateHeap", p);
   #endif
@@ -85,8 +88,22 @@
 
 
 template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size,
-      address caller_pc) throw() {
-    void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC));
+      const NativeCallStack& stack) throw() {
+  void* p = (void*)AllocateHeap(size, F, stack);
+#ifdef ASSERT
+  if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
+#endif
+  return p;
+}
+
+template <MEMFLAGS F> void* CHeapObj<F>::operator new(size_t size) throw() {
+  return CHeapObj<F>::operator new(size, CALLER_PC);
+}
+
+template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
+  const std::nothrow_t&  nothrow_constant, const NativeCallStack& stack) throw() {
+  void* p = (void*)AllocateHeap(size, F, stack,
+      AllocFailStrategy::RETURN_NULL);
 #ifdef ASSERT
     if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
 #endif
@@ -94,23 +111,28 @@
   }
 
 template <MEMFLAGS F> void* CHeapObj<F>::operator new (size_t size,
-  const std::nothrow_t&  nothrow_constant, address caller_pc) throw() {
-  void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC),
-      AllocFailStrategy::RETURN_NULL);
-#ifdef ASSERT
-    if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p);
-#endif
-    return p;
+  const std::nothrow_t& nothrow_constant) throw() {
+  return CHeapObj<F>::operator new(size, nothrow_constant, CALLER_PC);
 }
 
 template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size,
-      address caller_pc) throw() {
-    return CHeapObj<F>::operator new(size, caller_pc);
+      const NativeCallStack& stack) throw() {
+  return CHeapObj<F>::operator new(size, stack);
+}
+
+template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size)
+  throw() {
+  return CHeapObj<F>::operator new(size, CALLER_PC);
 }
 
 template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size,
-  const std::nothrow_t&  nothrow_constant, address caller_pc) throw() {
-    return CHeapObj<F>::operator new(size, nothrow_constant, caller_pc);
+  const std::nothrow_t&  nothrow_constant, const NativeCallStack& stack) throw() {
+  return CHeapObj<F>::operator new(size, nothrow_constant, stack);
+}
+
+template <MEMFLAGS F> void* CHeapObj<F>::operator new [](size_t size,
+  const std::nothrow_t& nothrow_constant) throw() {
+  return CHeapObj<F>::operator new(size, nothrow_constant, CALLER_PC);
 }
 
 template <MEMFLAGS F> void CHeapObj<F>::operator delete(void* p){
diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp
index 626c4c1..eebd63e 100644
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.cpp
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.cpp
@@ -44,13 +44,6 @@
 // enumerate ref fields that have been modified (since the last
 // enumeration.)
 
-size_t CardTableModRefBS::cards_required(size_t covered_words)
-{
-  // Add one for a guard card, used to detect errors.
-  const size_t words = align_size_up(covered_words, card_size_in_words);
-  return words / card_size_in_words + 1;
-}
-
 size_t CardTableModRefBS::compute_byte_map_size()
 {
   assert(_guard_index == cards_required(_whole_heap.word_size()) - 1,
@@ -64,27 +57,50 @@
                                      int max_covered_regions):
   ModRefBarrierSet(max_covered_regions),
   _whole_heap(whole_heap),
-  _guard_index(cards_required(whole_heap.word_size()) - 1),
-  _last_valid_index(_guard_index - 1),
+  _guard_index(0),
+  _guard_region(),
+  _last_valid_index(0),
   _page_size(os::vm_page_size()),
-  _byte_map_size(compute_byte_map_size())
+  _byte_map_size(0),
+  _covered(NULL),
+  _committed(NULL),
+  _cur_covered_regions(0),
+  _byte_map(NULL),
+  byte_map_base(NULL),
+  // LNC functionality
+  _lowest_non_clean(NULL),
+  _lowest_non_clean_chunk_size(NULL),
+  _lowest_non_clean_base_chunk_index(NULL),
+  _last_LNC_resizing_collection(NULL)
 {
   _kind = BarrierSet::CardTableModRef;
 
-  HeapWord* low_bound  = _whole_heap.start();
-  HeapWord* high_bound = _whole_heap.end();
-  assert((uintptr_t(low_bound)  & (card_size - 1))  == 0, "heap must start at card boundary");
-  assert((uintptr_t(high_bound) & (card_size - 1))  == 0, "heap must end at card boundary");
+  assert((uintptr_t(_whole_heap.start())  & (card_size - 1))  == 0, "heap must start at card boundary");
+  assert((uintptr_t(_whole_heap.end()) & (card_size - 1))  == 0, "heap must end at card boundary");
 
   assert(card_size <= 512, "card_size must be less than 512"); // why?
 
-  _covered   = new MemRegion[max_covered_regions];
-  _committed = new MemRegion[max_covered_regions];
-  if (_covered == NULL || _committed == NULL) {
-    vm_exit_during_initialization("couldn't alloc card table covered region set.");
+  _covered   = new MemRegion[_max_covered_regions];
+  if (_covered == NULL) {
+    vm_exit_during_initialization("Could not allocate card table covered region set.");
   }
+}
+
+void CardTableModRefBS::initialize() {
+  _guard_index = cards_required(_whole_heap.word_size()) - 1;
+  _last_valid_index = _guard_index - 1;
+
+  _byte_map_size = compute_byte_map_size();
+
+  HeapWord* low_bound  = _whole_heap.start();
+  HeapWord* high_bound = _whole_heap.end();
 
   _cur_covered_regions = 0;
+  _committed = new MemRegion[_max_covered_regions];
+  if (_committed == NULL) {
+    vm_exit_during_initialization("Could not allocate card table committed region set.");
+  }
+
   const size_t rs_align = _page_size == (size_t) os::vm_page_size() ? 0 :
     MAX2(_page_size, (size_t) os::vm_allocation_granularity());
   ReservedSpace heap_rs(_byte_map_size, rs_align, false);
@@ -114,20 +130,20 @@
                             !ExecMem, "card table last card");
   *guard_card = last_card;
 
-   _lowest_non_clean =
-    NEW_C_HEAP_ARRAY(CardArr, max_covered_regions, mtGC);
+  _lowest_non_clean =
+    NEW_C_HEAP_ARRAY(CardArr, _max_covered_regions, mtGC);
   _lowest_non_clean_chunk_size =
-    NEW_C_HEAP_ARRAY(size_t, max_covered_regions, mtGC);
+    NEW_C_HEAP_ARRAY(size_t, _max_covered_regions, mtGC);
   _lowest_non_clean_base_chunk_index =
-    NEW_C_HEAP_ARRAY(uintptr_t, max_covered_regions, mtGC);
+    NEW_C_HEAP_ARRAY(uintptr_t, _max_covered_regions, mtGC);
   _last_LNC_resizing_collection =
-    NEW_C_HEAP_ARRAY(int, max_covered_regions, mtGC);
+    NEW_C_HEAP_ARRAY(int, _max_covered_regions, mtGC);
   if (_lowest_non_clean == NULL
       || _lowest_non_clean_chunk_size == NULL
       || _lowest_non_clean_base_chunk_index == NULL
       || _last_LNC_resizing_collection == NULL)
     vm_exit_during_initialization("couldn't allocate an LNC array.");
-  for (int i = 0; i < max_covered_regions; i++) {
+  for (int i = 0; i < _max_covered_regions; i++) {
     _lowest_non_clean[i] = NULL;
     _lowest_non_clean_chunk_size[i] = 0;
     _last_LNC_resizing_collection[i] = -1;
@@ -429,7 +445,7 @@
                                                                  OopsInGenClosure* cl,
                                                                  CardTableRS* ct) {
   if (!mr.is_empty()) {
-    // Caller (process_strong_roots()) claims that all GC threads
+    // Caller (process_roots()) claims that all GC threads
     // execute this call.  With UseDynamicNumberOfGCThreads now all
     // active GC threads execute this call.  The number of active GC
     // threads needs to be passed to par_non_clean_card_iterate_work()
@@ -438,7 +454,7 @@
     // This is an example of where n_par_threads() is used instead
     // of workers()->active_workers().  n_par_threads can be set to 0 to
     // turn off parallelism.  For example when this code is called as
-    // part of verification and SharedHeap::process_strong_roots() is being
+    // part of verification and SharedHeap::process_roots() is being
     // used, then n_par_threads() may have been set to 0.  active_workers
     // is not overloaded with the meaning that it is a switch to disable
     // parallelism and so keeps the meaning of the number of
@@ -650,7 +666,7 @@
                                       jbyte val, bool val_equals) {
   jbyte* start    = byte_for(mr.start());
   jbyte* end      = byte_for(mr.last());
-  bool   failures = false;
+  bool failures = false;
   for (jbyte* curr = start; curr <= end; ++curr) {
     jbyte curr_val = *curr;
     bool failed = (val_equals) ? (curr_val != val) : (curr_val == val);
diff --git a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp
index 5e72b46..c824e61 100644
--- a/hotspot/src/share/vm/memory/cardTableModRefBS.hpp
+++ b/hotspot/src/share/vm/memory/cardTableModRefBS.hpp
@@ -96,12 +96,12 @@
   // The declaration order of these const fields is important; see the
   // constructor before changing.
   const MemRegion _whole_heap;       // the region covered by the card table
-  const size_t    _guard_index;      // index of very last element in the card
+  size_t          _guard_index;      // index of very last element in the card
                                      // table; it is set to a guard value
                                      // (last_card) and should never be modified
-  const size_t    _last_valid_index; // index of the last valid element
+  size_t          _last_valid_index; // index of the last valid element
   const size_t    _page_size;        // page size used when mapping _byte_map
-  const size_t    _byte_map_size;    // in bytes
+  size_t          _byte_map_size;    // in bytes
   jbyte*          _byte_map;         // the card marking array
 
   int _cur_covered_regions;
@@ -123,7 +123,12 @@
  protected:
   // Initialization utilities; covered_words is the size of the covered region
   // in, um, words.
-  inline size_t cards_required(size_t covered_words);
+  inline size_t cards_required(size_t covered_words) {
+    // Add one for a guard card, used to detect errors.
+    const size_t words = align_size_up(covered_words, card_size_in_words);
+    return words / card_size_in_words + 1;
+  }
+
   inline size_t compute_byte_map_size();
 
   // Finds and return the index of the region, if any, to which the given
@@ -137,7 +142,7 @@
   int find_covering_region_containing(HeapWord* addr);
 
   // Resize one of the regions covered by the remembered set.
-  void resize_covered_region(MemRegion new_region);
+  virtual void resize_covered_region(MemRegion new_region);
 
   // Returns the leftmost end of a committed region corresponding to a
   // covered region before covered region "ind", or else "NULL" if "ind" is
@@ -282,6 +287,8 @@
   CardTableModRefBS(MemRegion whole_heap, int max_covered_regions);
   ~CardTableModRefBS();
 
+  virtual void initialize();
+
   // *** Barrier set functions.
 
   bool has_write_ref_pre_barrier() { return false; }
diff --git a/hotspot/src/share/vm/memory/cardTableRS.cpp b/hotspot/src/share/vm/memory/cardTableRS.cpp
index 953643c..fb33a70 100644
--- a/hotspot/src/share/vm/memory/cardTableRS.cpp
+++ b/hotspot/src/share/vm/memory/cardTableRS.cpp
@@ -53,9 +53,10 @@
 #else
   _ct_bs = new CardTableModRefBSForCTRS(whole_heap, max_covered_regions);
 #endif
+  _ct_bs->initialize();
   set_bs(_ct_bs);
   _last_cur_val_in_gen = NEW_C_HEAP_ARRAY3(jbyte, GenCollectedHeap::max_gens + 1,
-                         mtGC, 0, AllocFailStrategy::RETURN_NULL);
+                         mtGC, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
   if (_last_cur_val_in_gen == NULL) {
     vm_exit_during_initialization("Could not create last_cur_val_in_gen array.");
   }
diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp
index 7c25b92..53fcf4f 100644
--- a/hotspot/src/share/vm/memory/collectorPolicy.cpp
+++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp
@@ -969,7 +969,8 @@
 }
 
 void MarkSweepPolicy::initialize_generations() {
-  _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, 0, AllocFailStrategy::RETURN_NULL);
+  _generations = NEW_C_HEAP_ARRAY3(GenerationSpecPtr, number_of_generations(), mtGC, CURRENT_PC,
+    AllocFailStrategy::RETURN_NULL);
   if (_generations == NULL) {
     vm_exit_during_initialization("Unable to allocate gen spec");
   }
diff --git a/hotspot/src/share/vm/memory/defNewGeneration.cpp b/hotspot/src/share/vm/memory/defNewGeneration.cpp
index b38f780..ac41f33 100644
--- a/hotspot/src/share/vm/memory/defNewGeneration.cpp
+++ b/hotspot/src/share/vm/memory/defNewGeneration.cpp
@@ -42,6 +42,7 @@
 #include "oops/instanceRefKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/java.hpp"
+#include "runtime/prefetch.inline.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/stack.inline.hpp"
@@ -584,7 +585,7 @@
 
   init_assuming_no_promotion_failure();
 
-  GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL);
+  GCTraceTime t1(GCCauseString("GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, gc_tracer.gc_id());
   // Capture heap used before collection (for printing).
   size_t gch_prev_used = gch->used();
 
@@ -612,6 +613,9 @@
 
   KlassScanClosure klass_scan_closure(&fsc_with_no_gc_barrier,
                                       gch->rem_set()->klass_rem_set());
+  CLDToKlassAndOopClosure cld_scan_closure(&klass_scan_closure,
+                                           &fsc_with_no_gc_barrier,
+                                           false);
 
   set_promo_failure_scan_stack_closure(&fsc_with_no_gc_barrier);
   FastEvacuateFollowersClosure evacuate_followers(gch, _level, this,
@@ -621,18 +625,15 @@
   assert(gch->no_allocs_since_save_marks(0),
          "save marks have not been newly set.");
 
-  int so = SharedHeap::SO_AllClasses | SharedHeap::SO_Strings | SharedHeap::SO_CodeCache;
-
-  gch->gen_process_strong_roots(_level,
-                                true,  // Process younger gens, if any,
-                                       // as strong roots.
-                                true,  // activate StrongRootsScope
-                                true,  // is scavenging
-                                SharedHeap::ScanningOption(so),
-                                &fsc_with_no_gc_barrier,
-                                true,   // walk *all* scavengable nmethods
-                                &fsc_with_gc_barrier,
-                                &klass_scan_closure);
+  gch->gen_process_roots(_level,
+                         true,  // Process younger gens, if any,
+                                // as strong roots.
+                         true,  // activate StrongRootsScope
+                         SharedHeap::SO_ScavengeCodeCache,
+                         GenCollectedHeap::StrongAndWeakRoots,
+                         &fsc_with_no_gc_barrier,
+                         &fsc_with_gc_barrier,
+                         &cld_scan_closure);
 
   // "evacuate followers".
   evacuate_followers.do_void();
@@ -642,7 +643,7 @@
   rp->setup_policy(clear_all_soft_refs);
   const ReferenceProcessorStats& stats =
   rp->process_discovered_references(&is_alive, &keep_alive, &evacuate_followers,
-                                    NULL, _gc_timer);
+                                    NULL, _gc_timer, gc_tracer.gc_id());
   gc_tracer.report_gc_reference_stats(stats);
 
   if (!_promotion_failed) {
@@ -788,7 +789,7 @@
 
   // Try allocating obj in to-space (unless too old)
   if (old->age() < tenuring_threshold()) {
-    obj = (oop) to()->allocate(s);
+    obj = (oop) to()->allocate_aligned(s);
   }
 
   // Otherwise try allocating obj tenured
diff --git a/hotspot/src/share/vm/memory/gcLocker.cpp b/hotspot/src/share/vm/memory/gcLocker.cpp
index 06fc05c..9674263 100644
--- a/hotspot/src/share/vm/memory/gcLocker.cpp
+++ b/hotspot/src/share/vm/memory/gcLocker.cpp
@@ -26,6 +26,7 @@
 #include "memory/gcLocker.inline.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/sharedHeap.hpp"
+#include "runtime/thread.inline.hpp"
 
 volatile jint GC_locker::_jni_lock_count = 0;
 volatile bool GC_locker::_needs_gc       = false;
diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.cpp b/hotspot/src/share/vm/memory/genCollectedHeap.cpp
index d9b6f50..da49aa4 100644
--- a/hotspot/src/share/vm/memory/genCollectedHeap.cpp
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.cpp
@@ -28,6 +28,7 @@
 #include "classfile/vmSymbols.hpp"
 #include "code/icBuffer.hpp"
 #include "gc_implementation/shared/collectorCounters.hpp"
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "gc_implementation/shared/gcTraceTime.hpp"
 #include "gc_implementation/shared/vmGCOperations.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
@@ -60,8 +61,8 @@
 GenCollectedHeap* GenCollectedHeap::_gch;
 NOT_PRODUCT(size_t GenCollectedHeap::_skip_header_HeapWords = 0;)
 
-// The set of potentially parallel tasks in strong root scanning.
-enum GCH_process_strong_roots_tasks {
+// The set of potentially parallel tasks in root scanning.
+enum GCH_strong_roots_tasks {
   // We probably want to parallelize both of these internally, but for now...
   GCH_PS_younger_gens,
   // Leave this one last.
@@ -71,11 +72,11 @@
 GenCollectedHeap::GenCollectedHeap(GenCollectorPolicy *policy) :
   SharedHeap(policy),
   _gen_policy(policy),
-  _gen_process_strong_tasks(new SubTasksDone(GCH_PS_NumElements)),
+  _gen_process_roots_tasks(new SubTasksDone(GCH_PS_NumElements)),
   _full_collections_completed(0)
 {
-  if (_gen_process_strong_tasks == NULL ||
-      !_gen_process_strong_tasks->valid()) {
+  if (_gen_process_roots_tasks == NULL ||
+      !_gen_process_roots_tasks->valid()) {
     vm_exit_during_initialization("Failed necessary allocation.");
   }
   assert(policy != NULL, "Sanity check");
@@ -385,7 +386,9 @@
     const char* gc_cause_prefix = complete ? "Full GC" : "GC";
     gclog_or_tty->date_stamp(PrintGC && PrintGCDateStamps);
     TraceCPUTime tcpu(PrintGCDetails, true, gclog_or_tty);
-    GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL);
+    // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later
+    // so we can assume here that the next GC id is what we want.
+    GCTraceTime t(GCCauseString(gc_cause_prefix, gc_cause()), PrintGCDetails, false, NULL, GCId::peek());
 
     gc_prologue(complete);
     increment_total_collections(complete);
@@ -418,7 +421,9 @@
         }
         // Timer for individual generations. Last argument is false: no CR
         // FIXME: We should try to start the timing earlier to cover more of the GC pause
-        GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL);
+        // The PrintGCDetails logging starts before we have incremented the GC id. We will do that later
+        // so we can assume here that the next GC id is what we want.
+        GCTraceTime t1(_gens[i]->short_name(), PrintGCDetails, false, NULL, GCId::peek());
         TraceCollectorStats tcs(_gens[i]->counters());
         TraceMemoryManagerStats tmms(_gens[i]->kind(),gc_cause());
 
@@ -585,33 +590,29 @@
 
 void GenCollectedHeap::set_par_threads(uint t) {
   SharedHeap::set_par_threads(t);
-  _gen_process_strong_tasks->set_n_threads(t);
+  _gen_process_roots_tasks->set_n_threads(t);
 }
 
 void GenCollectedHeap::
-gen_process_strong_roots(int level,
-                         bool younger_gens_as_roots,
-                         bool activate_scope,
-                         bool is_scavenging,
-                         SharedHeap::ScanningOption so,
-                         OopsInGenClosure* not_older_gens,
-                         bool do_code_roots,
-                         OopsInGenClosure* older_gens,
-                         KlassClosure* klass_closure) {
-  // General strong roots.
+gen_process_roots(int level,
+                  bool younger_gens_as_roots,
+                  bool activate_scope,
+                  SharedHeap::ScanningOption so,
+                  OopsInGenClosure* not_older_gens,
+                  OopsInGenClosure* weak_roots,
+                  OopsInGenClosure* older_gens,
+                  CLDClosure* cld_closure,
+                  CLDClosure* weak_cld_closure,
+                  CodeBlobClosure* code_closure) {
 
-  if (!do_code_roots) {
-    SharedHeap::process_strong_roots(activate_scope, is_scavenging, so,
-                                     not_older_gens, NULL, klass_closure);
-  } else {
-    bool do_code_marking = (activate_scope || nmethod::oops_do_marking_is_active());
-    CodeBlobToOopClosure code_roots(not_older_gens, /*do_marking=*/ do_code_marking);
-    SharedHeap::process_strong_roots(activate_scope, is_scavenging, so,
-                                     not_older_gens, &code_roots, klass_closure);
-  }
+  // General roots.
+  SharedHeap::process_roots(activate_scope, so,
+                            not_older_gens, weak_roots,
+                            cld_closure, weak_cld_closure,
+                            code_closure);
 
   if (younger_gens_as_roots) {
-    if (!_gen_process_strong_tasks->is_task_claimed(GCH_PS_younger_gens)) {
+    if (!_gen_process_roots_tasks->is_task_claimed(GCH_PS_younger_gens)) {
       for (int i = 0; i < level; i++) {
         not_older_gens->set_generation(_gens[i]);
         _gens[i]->oop_iterate(not_older_gens);
@@ -627,12 +628,42 @@
     older_gens->reset_generation();
   }
 
-  _gen_process_strong_tasks->all_tasks_completed();
+  _gen_process_roots_tasks->all_tasks_completed();
 }
 
-void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure,
-                                              CodeBlobClosure* code_roots) {
-  SharedHeap::process_weak_roots(root_closure, code_roots);
+void GenCollectedHeap::
+gen_process_roots(int level,
+                  bool younger_gens_as_roots,
+                  bool activate_scope,
+                  SharedHeap::ScanningOption so,
+                  bool only_strong_roots,
+                  OopsInGenClosure* not_older_gens,
+                  OopsInGenClosure* older_gens,
+                  CLDClosure* cld_closure) {
+
+  const bool is_adjust_phase = !only_strong_roots && !younger_gens_as_roots;
+
+  bool is_moving_collection = false;
+  if (level == 0 || is_adjust_phase) {
+    // young collections are always moving
+    is_moving_collection = true;
+  }
+
+  MarkingCodeBlobClosure mark_code_closure(not_older_gens, is_moving_collection);
+  CodeBlobClosure* code_closure = &mark_code_closure;
+
+  gen_process_roots(level,
+                    younger_gens_as_roots,
+                    activate_scope, so,
+                    not_older_gens, only_strong_roots ? NULL : not_older_gens,
+                    older_gens,
+                    cld_closure, only_strong_roots ? NULL : cld_closure,
+                    code_closure);
+
+}
+
+void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) {
+  SharedHeap::process_weak_roots(root_closure);
   // "Local" "weak" refs
   for (int i = 0; i < _n_gens; i++) {
     _gens[i]->ref_processor()->weak_oops_do(root_closure);
@@ -673,10 +704,6 @@
   return _gens[0]->end_addr();
 }
 
-size_t GenCollectedHeap::unsafe_max_alloc() {
-  return _gens[0]->unsafe_max_alloc_nogc();
-}
-
 // public collection interfaces
 
 void GenCollectedHeap::collect(GCCause::Cause cause) {
@@ -687,15 +714,18 @@
 #else  // INCLUDE_ALL_GCS
     ShouldNotReachHere();
 #endif // INCLUDE_ALL_GCS
+  } else if (cause == GCCause::_wb_young_gc) {
+    // minor collection for WhiteBox API
+    collect(cause, 0);
   } else {
 #ifdef ASSERT
-    if (cause == GCCause::_scavenge_alot) {
-      // minor collection only
-      collect(cause, 0);
-    } else {
-      // Stop-the-world full collection
-      collect(cause, n_gens() - 1);
-    }
+  if (cause == GCCause::_scavenge_alot) {
+    // minor collection only
+    collect(cause, 0);
+  } else {
+    // Stop-the-world full collection
+    collect(cause, n_gens() - 1);
+  }
 #else
     // Stop-the-world full collection
     collect(cause, n_gens() - 1);
@@ -851,12 +881,6 @@
   }
 }
 
-void GenCollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  for (int i = 0; i < _n_gens; i++) {
-    _gens[i]->oop_iterate(mr, cl);
-  }
-}
-
 void GenCollectedHeap::object_iterate(ObjectClosure* cl) {
   for (int i = 0; i < _n_gens; i++) {
     _gens[i]->object_iterate(cl);
@@ -1074,7 +1098,7 @@
   guarantee(_n_gens = 2, "Wrong number of generations");
   Generation* old_gen = _gens[1];
   // Start by compacting into same gen.
-  CompactPoint cp(old_gen, NULL, NULL);
+  CompactPoint cp(old_gen);
   old_gen->prepare_for_compaction(&cp);
   Generation* young_gen = _gens[0];
   young_gen->prepare_for_compaction(&cp);
diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp
index a44e2eb..77ae3ad 100644
--- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp
+++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp
@@ -78,9 +78,9 @@
   unsigned int _full_collections_completed;
 
   // Data structure for claiming the (potentially) parallel tasks in
-  // (gen-specific) strong roots processing.
-  SubTasksDone* _gen_process_strong_tasks;
-  SubTasksDone* gen_process_strong_tasks() { return _gen_process_strong_tasks; }
+  // (gen-specific) roots processing.
+  SubTasksDone* _gen_process_roots_tasks;
+  SubTasksDone* gen_process_roots_tasks() { return _gen_process_roots_tasks; }
 
   // In block contents verification, the number of header words to skip
   NOT_PRODUCT(static size_t _skip_header_HeapWords;)
@@ -166,14 +166,6 @@
   HeapWord** top_addr() const;
   HeapWord** end_addr() const;
 
-  // Return an estimate of the maximum allocation that could be performed
-  // without triggering any collection activity.  In a generational
-  // collector, for example, this is probably the largest allocation that
-  // could be supported in the youngest generation.  It is "unsafe" because
-  // no locks are taken; the result should be treated as an approximation,
-  // not a guarantee.
-  size_t unsafe_max_alloc();
-
   // Does this heap support heap inspection? (+PrintClassHistogram)
   virtual bool supports_heap_inspection() const { return true; }
 
@@ -220,7 +212,6 @@
 
   // Iteration functions.
   void oop_iterate(ExtendedOopClosure* cl);
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   void object_iterate(ObjectClosure* cl);
   void safe_object_iterate(ObjectClosure* cl);
   Space* space_containing(const void* addr) const;
@@ -412,26 +403,35 @@
   // The "so" argument determines which of the roots
   // the closure is applied to:
   // "SO_None" does none;
-  // "SO_AllClasses" applies the closure to all entries in the SystemDictionary;
-  // "SO_SystemClasses" to all the "system" classes and loaders;
-  // "SO_Strings" applies the closure to all entries in the StringTable.
-  void gen_process_strong_roots(int level,
-                                bool younger_gens_as_roots,
-                                // The remaining arguments are in an order
-                                // consistent with SharedHeap::process_strong_roots:
-                                bool activate_scope,
-                                bool is_scavenging,
-                                SharedHeap::ScanningOption so,
-                                OopsInGenClosure* not_older_gens,
-                                bool do_code_roots,
-                                OopsInGenClosure* older_gens,
-                                KlassClosure* klass_closure);
+ private:
+  void gen_process_roots(int level,
+                         bool younger_gens_as_roots,
+                         bool activate_scope,
+                         SharedHeap::ScanningOption so,
+                         OopsInGenClosure* not_older_gens,
+                         OopsInGenClosure* weak_roots,
+                         OopsInGenClosure* older_gens,
+                         CLDClosure* cld_closure,
+                         CLDClosure* weak_cld_closure,
+                         CodeBlobClosure* code_closure);
 
-  // Apply "blk" to all the weak roots of the system.  These include
-  // JNI weak roots, the code cache, system dictionary, symbol table,
-  // string table, and referents of reachable weak refs.
-  void gen_process_weak_roots(OopClosure* root_closure,
-                              CodeBlobClosure* code_roots);
+ public:
+  static const bool StrongAndWeakRoots = false;
+  static const bool StrongRootsOnly    = true;
+
+  void gen_process_roots(int level,
+                         bool younger_gens_as_roots,
+                         bool activate_scope,
+                         SharedHeap::ScanningOption so,
+                         bool only_strong_roots,
+                         OopsInGenClosure* not_older_gens,
+                         OopsInGenClosure* older_gens,
+                         CLDClosure* cld_closure);
+
+  // Apply "root_closure" to all the weak roots of the system.
+  // These include JNI weak roots, string table,
+  // and referents of reachable weak refs.
+  void gen_process_weak_roots(OopClosure* root_closure);
 
   // Set the saved marks of generations, if that makes sense.
   // In particular, if any generation might iterate over the oops
diff --git a/hotspot/src/share/vm/memory/genMarkSweep.cpp b/hotspot/src/share/vm/memory/genMarkSweep.cpp
index fdeba2a..48911b1 100644
--- a/hotspot/src/share/vm/memory/genMarkSweep.cpp
+++ b/hotspot/src/share/vm/memory/genMarkSweep.cpp
@@ -69,7 +69,7 @@
   _ref_processor = rp;
   rp->setup_policy(clear_all_softrefs);
 
-  GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL);
+  GCTraceTime t1(GCCauseString("Full GC", gch->gc_cause()), PrintGC && !PrintGCDetails, true, NULL, _gc_tracer->gc_id());
 
   gch->trace_heap_before_gc(_gc_tracer);
 
@@ -193,7 +193,7 @@
 void GenMarkSweep::mark_sweep_phase1(int level,
                                   bool clear_all_softrefs) {
   // Recursively traverse all live objects and mark them
-  GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 1", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace(" 1");
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
@@ -207,22 +207,21 @@
   // Need new claim bits before marking starts.
   ClassLoaderDataGraph::clear_claimed_marks();
 
-  gch->gen_process_strong_roots(level,
-                                false, // Younger gens are not roots.
-                                true,  // activate StrongRootsScope
-                                false, // not scavenging
-                                SharedHeap::SO_SystemClasses,
-                                &follow_root_closure,
-                                true,   // walk code active on stacks
-                                &follow_root_closure,
-                                &follow_klass_closure);
+  gch->gen_process_roots(level,
+                         false, // Younger gens are not roots.
+                         true,  // activate StrongRootsScope
+                         SharedHeap::SO_None,
+                         GenCollectedHeap::StrongRootsOnly,
+                         &follow_root_closure,
+                         &follow_root_closure,
+                         &follow_cld_closure);
 
   // Process reference objects found during marking
   {
     ref_processor()->setup_policy(clear_all_softrefs);
     const ReferenceProcessorStats& stats =
       ref_processor()->process_discovered_references(
-        &is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer);
+        &is_alive, &keep_alive, &follow_stack_closure, NULL, _gc_timer, _gc_tracer->gc_id());
     gc_tracer()->report_gc_reference_stats(stats);
   }
 
@@ -264,7 +263,7 @@
 
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
-  GCTraceTime tm("phase 2", PrintGC && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 2", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace("2");
 
   gch->prepare_for_compaction();
@@ -281,7 +280,7 @@
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
   // Adjust the pointers to reflect the new locations
-  GCTraceTime tm("phase 3", PrintGC && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 3", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace("3");
 
   // Need new claim bits for the pointer adjustment tracing.
@@ -293,22 +292,16 @@
   // are run.
   adjust_pointer_closure.set_orig_generation(gch->get_gen(level));
 
-  gch->gen_process_strong_roots(level,
-                                false, // Younger gens are not roots.
-                                true,  // activate StrongRootsScope
-                                false, // not scavenging
-                                SharedHeap::SO_AllClasses,
-                                &adjust_pointer_closure,
-                                false, // do not walk code
-                                &adjust_pointer_closure,
-                                &adjust_klass_closure);
+  gch->gen_process_roots(level,
+                         false, // Younger gens are not roots.
+                         true,  // activate StrongRootsScope
+                         SharedHeap::SO_AllCodeCache,
+                         GenCollectedHeap::StrongAndWeakRoots,
+                         &adjust_pointer_closure,
+                         &adjust_pointer_closure,
+                         &adjust_cld_closure);
 
-  // Now adjust pointers in remaining weak roots.  (All of which should
-  // have been cleared if they pointed to non-surviving objects.)
-  CodeBlobToOopClosure adjust_code_pointer_closure(&adjust_pointer_closure,
-                                                   /*do_marking=*/ false);
-  gch->gen_process_weak_roots(&adjust_pointer_closure,
-                              &adjust_code_pointer_closure);
+  gch->gen_process_weak_roots(&adjust_pointer_closure);
 
   adjust_marks();
   GenAdjustPointersClosure blk;
@@ -336,7 +329,7 @@
   // to use a higher index (saved from phase2) when verifying perm_gen.
   GenCollectedHeap* gch = GenCollectedHeap::heap();
 
-  GCTraceTime tm("phase 4", PrintGC && Verbose, true, _gc_timer);
+  GCTraceTime tm("phase 4", PrintGC && Verbose, true, _gc_timer, _gc_tracer->gc_id());
   trace("4");
 
   GenCompactClosure blk;
diff --git a/hotspot/src/share/vm/memory/generation.cpp b/hotspot/src/share/vm/memory/generation.cpp
index ef3bf7e..d52f325 100644
--- a/hotspot/src/share/vm/memory/generation.cpp
+++ b/hotspot/src/share/vm/memory/generation.cpp
@@ -297,22 +297,16 @@
 
 class GenerationOopIterateClosure : public SpaceClosure {
  public:
-  ExtendedOopClosure* cl;
-  MemRegion mr;
+  ExtendedOopClosure* _cl;
   virtual void do_space(Space* s) {
-    s->oop_iterate(mr, cl);
+    s->oop_iterate(_cl);
   }
-  GenerationOopIterateClosure(ExtendedOopClosure* _cl, MemRegion _mr) :
-    cl(_cl), mr(_mr) {}
+  GenerationOopIterateClosure(ExtendedOopClosure* cl) :
+    _cl(cl) {}
 };
 
 void Generation::oop_iterate(ExtendedOopClosure* cl) {
-  GenerationOopIterateClosure blk(cl, _reserved);
-  space_iterate(&blk);
-}
-
-void Generation::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
-  GenerationOopIterateClosure blk(cl, mr);
+  GenerationOopIterateClosure blk(cl);
   space_iterate(&blk);
 }
 
diff --git a/hotspot/src/share/vm/memory/generation.hpp b/hotspot/src/share/vm/memory/generation.hpp
index a0c6d78..bacd502 100644
--- a/hotspot/src/share/vm/memory/generation.hpp
+++ b/hotspot/src/share/vm/memory/generation.hpp
@@ -543,10 +543,6 @@
   // generation, calling "cl.do_oop" on each.
   virtual void oop_iterate(ExtendedOopClosure* cl);
 
-  // Same as above, restricted to the intersection of a memory region and
-  // the generation.
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
-
   // Iterate over all objects in the generation, calling "cl.do_object" on
   // each.
   virtual void object_iterate(ObjectClosure* cl);
diff --git a/hotspot/src/share/vm/memory/guardedMemory.cpp b/hotspot/src/share/vm/memory/guardedMemory.cpp
new file mode 100644
index 0000000..763548f
--- /dev/null
+++ b/hotspot/src/share/vm/memory/guardedMemory.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+#include "precompiled.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+#include "memory/guardedMemory.hpp"
+#include "runtime/os.hpp"
+
+void* GuardedMemory::wrap_copy(const void* ptr, const size_t len, const void* tag) {
+  size_t total_sz = GuardedMemory::get_total_size(len);
+  void* outerp = os::malloc(total_sz, mtInternal);
+  if (outerp != NULL) {
+    GuardedMemory guarded(outerp, len, tag);
+    void* innerp = guarded.get_user_ptr();
+    memcpy(innerp, ptr, len);
+    return innerp;
+  }
+  return NULL; // OOM
+}
+
+bool GuardedMemory::free_copy(void* p) {
+  if (p == NULL) {
+    return true;
+  }
+  GuardedMemory guarded((u_char*)p);
+  bool verify_ok = guarded.verify_guards();
+
+  /* always attempt to free, pass problem on to any nested memchecker */
+  os::free(guarded.release_for_freeing());
+
+  return verify_ok;
+}
+
+void GuardedMemory::print_on(outputStream* st) const {
+  if (_base_addr == NULL) {
+    st->print_cr("GuardedMemory(" PTR_FORMAT ") not associated to any memory", p2i(this));
+    return;
+  }
+  st->print_cr("GuardedMemory(" PTR_FORMAT ") base_addr=" PTR_FORMAT
+      " tag=" PTR_FORMAT " user_size=" SIZE_FORMAT " user_data=" PTR_FORMAT,
+      p2i(this), p2i(_base_addr), p2i(get_tag()), get_user_size(), p2i(get_user_ptr()));
+
+  Guard* guard = get_head_guard();
+  st->print_cr("  Header guard @" PTR_FORMAT " is %s", p2i(guard), (guard->verify() ? "OK" : "BROKEN"));
+  guard = get_tail_guard();
+  st->print_cr("  Trailer guard @" PTR_FORMAT " is %s", p2i(guard), (guard->verify() ? "OK" : "BROKEN"));
+
+  u_char udata = *get_user_ptr();
+  switch (udata) {
+  case uninitBlockPad:
+    st->print_cr("  User data appears unused");
+    break;
+  case freeBlockPad:
+    st->print_cr("  User data appears to have been freed");
+    break;
+  default:
+    st->print_cr("  User data appears to be in use");
+    break;
+  }
+}
+
+// test code...
+
+#ifndef PRODUCT
+
+static void guarded_memory_test_check(void* p, size_t sz, void* tag) {
+  assert(p != NULL, "NULL pointer given to check");
+  u_char* c = (u_char*) p;
+  GuardedMemory guarded(c);
+  assert(guarded.get_tag() == tag, "Tag is not the same as supplied");
+  assert(guarded.get_user_ptr() == c, "User pointer is not the same as supplied");
+  assert(guarded.get_user_size() == sz, "User size is not the same as supplied");
+  assert(guarded.verify_guards(), "Guard broken");
+}
+
+void GuardedMemory::test_guarded_memory() {
+  // Test the basic characteristics...
+  size_t total_sz = GuardedMemory::get_total_size(1);
+  assert(total_sz > 1 && total_sz >= (sizeof(GuardHeader) + 1 + sizeof(Guard)), "Unexpected size");
+  u_char* basep = (u_char*) os::malloc(total_sz, mtInternal);
+
+  GuardedMemory guarded(basep, 1, (void*)0xf000f000);
+
+  assert(*basep == badResourceValue, "Expected guard in the form of badResourceValue");
+  u_char* userp = guarded.get_user_ptr();
+  assert(*userp == uninitBlockPad, "Expected uninitialized data in the form of uninitBlockPad");
+  guarded_memory_test_check(userp, 1, (void*)0xf000f000);
+
+  void* freep = guarded.release_for_freeing();
+  assert((u_char*)freep == basep, "Expected the same pointer guard was ");
+  assert(*userp == freeBlockPad, "Expected user data to be free block padded");
+  assert(!guarded.verify_guards(), "Expected failed");
+  os::free(freep);
+
+  // Test a number of odd sizes...
+  size_t sz = 0;
+  do {
+    void* p = os::malloc(GuardedMemory::get_total_size(sz), mtInternal);
+    void* up = guarded.wrap_with_guards(p, sz, (void*)1);
+    memset(up, 0, sz);
+    guarded_memory_test_check(up, sz, (void*)1);
+    os::free(guarded.release_for_freeing());
+    sz = (sz << 4) + 1;
+  } while (sz < (256 * 1024));
+
+  // Test buffer overrun into head...
+  basep = (u_char*) os::malloc(GuardedMemory::get_total_size(1), mtInternal);
+  guarded.wrap_with_guards(basep, 1);
+  *basep = 0;
+  assert(!guarded.verify_guards(), "Expected failure");
+  os::free(basep);
+
+  // Test buffer overrun into tail with a number of odd sizes...
+  sz = 1;
+  do {
+    void* p = os::malloc(GuardedMemory::get_total_size(sz), mtInternal);
+    void* up = guarded.wrap_with_guards(p, sz, (void*)1);
+    memset(up, 0, sz + 1); // Buffer-overwrite (within guard)
+    assert(!guarded.verify_guards(), "Guard was not broken as expected");
+    os::free(guarded.release_for_freeing());
+    sz = (sz << 4) + 1;
+  } while (sz < (256 * 1024));
+
+  // Test wrap_copy/wrap_free...
+  assert(GuardedMemory::free_copy(NULL), "Expected free NULL to be OK");
+
+  const char* str = "Check my bounds out";
+  size_t str_sz = strlen(str) + 1;
+  char* str_copy = (char*) GuardedMemory::wrap_copy(str, str_sz);
+  guarded_memory_test_check(str_copy, str_sz, NULL);
+  assert(strcmp(str, str_copy) == 0, "Not identical copy");
+  assert(GuardedMemory::free_copy(str_copy), "Free copy failed to verify");
+
+  void* no_data = NULL;
+  void* no_data_copy = GuardedMemory::wrap_copy(no_data, 0);
+  assert(GuardedMemory::free_copy(no_data_copy), "Expected valid guards even for no data copy");
+}
+
+#endif // !PRODUCT
+
diff --git a/hotspot/src/share/vm/memory/guardedMemory.hpp b/hotspot/src/share/vm/memory/guardedMemory.hpp
new file mode 100644
index 0000000..dada10d
--- /dev/null
+++ b/hotspot/src/share/vm/memory/guardedMemory.hpp
@@ -0,0 +1,326 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+#define SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+/**
+ * Guarded memory for detecting buffer overrun.
+ *
+ * Allows allocations to be wrapped with padded bytes of a known byte pattern,
+ * that is a "guard". Guard patterns may be verified to detect buffer overruns.
+ *
+ * Primarily used by "debug malloc" and "checked JNI".
+ *
+ * Memory layout:
+ *
+ * |Offset             | Content              | Description    |
+ * |------------------------------------------------------------
+ * |base_addr          | 0xABABABABABABABAB   | Head guard     |
+ * |+16                | <size_t:user_size>   | User data size |
+ * |+sizeof(uintptr_t) | <tag>                | Tag word       |
+ * |+sizeof(void*)     | 0xF1 <user_data> (   | User data      |
+ * |+user_size         | 0xABABABABABABABAB   | Tail guard     |
+ * -------------------------------------------------------------
+ *
+ * Where:
+ *  - guard padding uses "badResourceValue" (0xAB)
+ *  - tag word is general purpose
+ *  - user data
+ *    -- initially padded with "uninitBlockPad" (0xF1),
+ *    -- to "freeBlockPad" (0xBA), when freed
+ *
+ * Usage:
+ *
+ * * Allocations: one may wrap allocations with guard memory:
+ * <code>
+ *   Thing* alloc_thing() {
+ *     void* mem = user_alloc_fn(GuardedMemory::get_total_size(sizeof(thing)));
+ *     GuardedMemory guarded(mem, sizeof(thing));
+ *     return (Thing*) guarded.get_user_ptr();
+ *   }
+ * </code>
+ * * Verify: memory guards are still in tact
+ * <code>
+ *   bool verify_thing(Thing* thing) {
+ *     GuardedMemory guarded((void*)thing);
+ *     return guarded.verify_guards();
+ *   }
+ * </code>
+ * * Free: one may mark bytes as freed (further debugging support)
+ * <code>
+ *   void free_thing(Thing* thing) {
+ *    GuardedMemory guarded((void*)thing);
+ *    assert(guarded.verify_guards(), "Corrupt thing");
+ *    user_free_fn(guards.release_for_freeing();
+ *   }
+ * </code>
+ */
+class GuardedMemory : StackObj { // Wrapper on stack
+
+  // Private inner classes for memory layout...
+
+protected:
+
+  /**
+   * Guard class for header and trailer known pattern to test for overwrites.
+   */
+  class Guard { // Class for raw memory (no vtbl allowed)
+    friend class GuardedMemory;
+   protected:
+    enum {
+      GUARD_SIZE = 16
+    };
+
+    u_char _guard[GUARD_SIZE];
+
+   public:
+
+    void build() {
+      u_char* c = _guard; // Possibly unaligned if tail guard
+      u_char* end = c + GUARD_SIZE;
+      while (c < end) {
+        *c = badResourceValue;
+        c++;
+      }
+    }
+
+    bool verify() const {
+      u_char* c = (u_char*) _guard;
+      u_char* end = c + GUARD_SIZE;
+      while (c < end) {
+        if (*c != badResourceValue) {
+          return false;
+        }
+        c++;
+      }
+      return true;
+    }
+
+  }; // GuardedMemory::Guard
+
+  /**
+   * Header guard and size
+   */
+  class GuardHeader : Guard {
+    friend class GuardedMemory;
+   protected:
+    // Take care in modifying fields here, will effect alignment
+    // e.g. x86 ABI 16 byte stack alignment
+    union {
+      uintptr_t __unused_full_word1;
+      size_t _user_size;
+    };
+    void* _tag;
+   public:
+    void set_user_size(const size_t usz) { _user_size = usz; }
+    size_t get_user_size() const { return _user_size; }
+
+    void set_tag(const void* tag) { _tag = (void*) tag; }
+    void* get_tag() const { return _tag; }
+
+  }; // GuardedMemory::GuardHeader
+
+  // Guarded Memory...
+
+ protected:
+  u_char* _base_addr;
+
+ public:
+
+  /**
+   * Create new guarded memory.
+   *
+   * Wraps, starting at the given "base_ptr" with guards. Use "get_user_ptr()"
+   * to return a pointer suitable for user data.
+   *
+   * @param base_ptr  allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes.
+   * @param user_size the size of the user data to be wrapped.
+   * @param tag       optional general purpose tag.
+   */
+  GuardedMemory(void* base_ptr, const size_t user_size, const void* tag = NULL) {
+    wrap_with_guards(base_ptr, user_size, tag);
+  }
+
+  /**
+   * Wrap existing guarded memory.
+   *
+   * To use this constructor, one must have created guarded memory with
+   * "GuardedMemory(void*, size_t, void*)" (or indirectly via helper, e.g. "wrap_copy()").
+   *
+   * @param user_p  existing wrapped memory.
+   */
+  GuardedMemory(void* userp) {
+    u_char* user_ptr = (u_char*) userp;
+    assert((uintptr_t)user_ptr > (sizeof(GuardHeader) + 0x1000), "Invalid pointer");
+    _base_addr = (user_ptr - sizeof(GuardHeader));
+  }
+
+  /**
+   * Create new guarded memory.
+   *
+   * Wraps, starting at the given "base_ptr" with guards. Allows reuse of stack allocated helper.
+   *
+   * @param base_ptr  allocation wishing to be wrapped, must be at least "GuardedMemory::get_total_size()" bytes.
+   * @param user_size the size of the user data to be wrapped.
+   * @param tag       optional general purpose tag.
+   *
+   * @return user data pointer (inner pointer to supplied "base_ptr").
+   */
+  void* wrap_with_guards(void* base_ptr, size_t user_size, const void* tag = NULL) {
+    assert(base_ptr != NULL, "Attempt to wrap NULL with memory guard");
+    _base_addr = (u_char*)base_ptr;
+    get_head_guard()->build();
+    get_head_guard()->set_user_size(user_size);
+    get_tail_guard()->build();
+    set_tag(tag);
+    set_user_bytes(uninitBlockPad);
+    assert(verify_guards(), "Expected valid memory guards");
+    return get_user_ptr();
+  }
+
+  /**
+   * Verify head and tail guards.
+   *
+   * @return true if guards are intact, false would indicate a buffer overrun.
+   */
+  bool verify_guards() const {
+    if (_base_addr != NULL) {
+      return (get_head_guard()->verify() && get_tail_guard()->verify());
+    }
+    return false;
+  }
+
+  /**
+   * Set the general purpose tag.
+   *
+   * @param tag general purpose tag.
+   */
+  void set_tag(const void* tag) { get_head_guard()->set_tag(tag); }
+
+  /**
+   * Return the general purpose tag.
+   *
+   * @return the general purpose tag, defaults to NULL.
+   */
+  void* get_tag() const { return get_head_guard()->get_tag(); }
+
+  /**
+   * Return the size of the user data.
+   *
+   * @return the size of the user data.
+   */
+  size_t get_user_size() const {
+    assert(_base_addr, "Not wrapping any memory");
+    return get_head_guard()->get_user_size();
+  }
+
+  /**
+   * Return the user data pointer.
+   *
+   * @return the user data pointer.
+   */
+  u_char* get_user_ptr() const {
+    assert(_base_addr, "Not wrapping any memory");
+    return _base_addr + sizeof(GuardHeader);
+  }
+
+  /**
+   * Release the wrapped pointer for resource freeing.
+   *
+   * Pads the user data with "freeBlockPad", and dis-associates the helper.
+   *
+   * @return the original base pointer used to wrap the data.
+   */
+  void* release_for_freeing() {
+    set_user_bytes(freeBlockPad);
+    return release();
+  }
+
+  /**
+   * Dis-associate the help from the original base address.
+   *
+   * @return the original base pointer used to wrap the data.
+   */
+  void* release() {
+    void* p = (void*) _base_addr;
+    _base_addr = NULL;
+    return p;
+  }
+
+  virtual void print_on(outputStream* st) const;
+
+ protected:
+  GuardHeader*  get_head_guard() const { return (GuardHeader*) _base_addr; }
+  Guard*        get_tail_guard() const { return (Guard*) (get_user_ptr() + get_user_size()); };
+  void set_user_bytes(u_char ch) {
+    memset(get_user_ptr(), ch, get_user_size());
+  }
+
+public:
+  /**
+   * Return the total size required for wrapping the given user size.
+   *
+   * @return the total size required for wrapping the given user size.
+   */
+  static size_t get_total_size(size_t user_size) {
+    size_t total_size = sizeof(GuardHeader) + user_size + sizeof(Guard);
+    assert(total_size > user_size, "Unexpected wrap-around");
+    return total_size;
+  }
+
+  // Helper functions...
+
+  /**
+   * Wrap a copy of size "len" of "ptr".
+   *
+   * @param ptr the memory to be copied
+   * @param len the length of the copy
+   * @param tag optional general purpose tag (see GuardedMemory::get_tag())
+   *
+   * @return guarded wrapped memory pointer to the user area, or NULL if OOM.
+   */
+  static void* wrap_copy(const void* p, const size_t len, const void* tag = NULL);
+
+  /**
+   * Free wrapped copy.
+   *
+   * Frees memory copied with "wrap_copy()".
+   *
+   * @param p memory returned by "wrap_copy()".
+   *
+   * @return true if guards were verified as intact. false indicates a buffer overrun.
+   */
+  static bool free_copy(void* p);
+
+  // Testing...
+#ifndef PRODUCT
+  static void test_guarded_memory(void);
+#endif
+}; // GuardedMemory
+
+#endif // SHARE_VM_MEMORY_GUARDED_MEMORY_HPP
diff --git a/hotspot/src/share/vm/memory/heapInspection.cpp b/hotspot/src/share/vm/memory/heapInspection.cpp
index 7a4c6fc..cc8f4fc 100644
--- a/hotspot/src/share/vm/memory/heapInspection.cpp
+++ b/hotspot/src/share/vm/memory/heapInspection.cpp
@@ -135,7 +135,7 @@
   _ref = (HeapWord*) Universe::boolArrayKlassObj();
   _buckets =
     (KlassInfoBucket*)  AllocateHeap(sizeof(KlassInfoBucket) * _num_buckets,
-                                            mtInternal, 0, AllocFailStrategy::RETURN_NULL);
+       mtInternal, CURRENT_PC, AllocFailStrategy::RETURN_NULL);
   if (_buckets != NULL) {
     _size = _num_buckets;
     for (int index = 0; index < _size; index++) {
diff --git a/hotspot/src/share/vm/memory/iterator.cpp b/hotspot/src/share/vm/memory/iterator.cpp
index f69eb4e..1022ece 100644
--- a/hotspot/src/share/vm/memory/iterator.cpp
+++ b/hotspot/src/share/vm/memory/iterator.cpp
@@ -27,6 +27,7 @@
 #include "oops/oop.inline.hpp"
 
 void KlassToOopClosure::do_klass(Klass* k) {
+  assert(_oop_closure != NULL, "Not initialized?");
   k->oops_do(_oop_closure);
 }
 
@@ -34,6 +35,10 @@
   cld->oops_do(_oop_closure, &_klass_closure, _must_claim_cld);
 }
 
+void CLDToKlassAndOopClosure::do_cld(ClassLoaderData* cld) {
+  cld->oops_do(_oop_closure, _klass_closure, _must_claim_cld);
+}
+
 void ObjectToOopClosure::do_object(oop obj) {
   obj->oop_iterate(_cl);
 }
@@ -42,6 +47,20 @@
   ShouldNotCallThis();
 }
 
+void CodeBlobToOopClosure::do_nmethod(nmethod* nm) {
+  nm->oops_do(_cl);
+  if (_fix_relocations) {
+    nm->fix_oop_relocations();
+  }
+}
+
+void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) {
+  nmethod* nm = cb->as_nmethod_or_null();
+  if (nm != NULL) {
+    do_nmethod(nm);
+  }
+}
+
 MarkingCodeBlobClosure::MarkScope::MarkScope(bool activate)
   : _active(activate)
 {
@@ -54,32 +73,7 @@
 
 void MarkingCodeBlobClosure::do_code_blob(CodeBlob* cb) {
   nmethod* nm = cb->as_nmethod_or_null();
-  if (nm == NULL)  return;
-  if (!nm->test_set_oops_do_mark()) {
-    NOT_PRODUCT(if (TraceScavenge)  nm->print_on(tty, "oops_do, 1st visit\n"));
-    do_newly_marked_nmethod(nm);
-  } else {
-    NOT_PRODUCT(if (TraceScavenge)  nm->print_on(tty, "oops_do, skipped on 2nd visit\n"));
+  if (nm != NULL && !nm->test_set_oops_do_mark()) {
+    do_nmethod(nm);
   }
 }
-
-void CodeBlobToOopClosure::do_newly_marked_nmethod(nmethod* nm) {
-  nm->oops_do(_cl, /*allow_zombie=*/ false);
-}
-
-void CodeBlobToOopClosure::do_code_blob(CodeBlob* cb) {
-  if (!_do_marking) {
-    nmethod* nm = cb->as_nmethod_or_null();
-    NOT_PRODUCT(if (TraceScavenge && Verbose && nm != NULL)  nm->print_on(tty, "oops_do, unmarked visit\n"));
-    // This assert won't work, since there are lots of mini-passes
-    // (mostly in debug mode) that co-exist with marking phases.
-    //assert(!(cb->is_nmethod() && ((nmethod*)cb)->test_oops_do_mark()), "found marked nmethod during mark-free phase");
-    if (nm != NULL) {
-      nm->oops_do(_cl);
-    }
-  } else {
-    MarkingCodeBlobClosure::do_code_blob(cb);
-  }
-}
-
-
diff --git a/hotspot/src/share/vm/memory/iterator.hpp b/hotspot/src/share/vm/memory/iterator.hpp
index dd98234..6622e13 100644
--- a/hotspot/src/share/vm/memory/iterator.hpp
+++ b/hotspot/src/share/vm/memory/iterator.hpp
@@ -84,8 +84,8 @@
   //
   // Providing default implementations of the _nv functions unfortunately
   // removes the compile-time safeness, but reduces the clutter for the
-  // ExtendedOopClosures that don't need to walk the metadata. Currently,
-  // only CMS needs these.
+  // ExtendedOopClosures that don't need to walk the metadata.
+  // Currently, only CMS and G1 need these.
 
   virtual bool do_metadata() { return do_metadata_nv(); }
   bool do_metadata_v()       { return do_metadata(); }
@@ -128,17 +128,33 @@
   virtual void do_klass(Klass* k) = 0;
 };
 
-class KlassToOopClosure : public KlassClosure {
-  OopClosure* _oop_closure;
+class CLDClosure : public Closure {
  public:
-  KlassToOopClosure(OopClosure* oop_closure) : _oop_closure(oop_closure) {}
+  virtual void do_cld(ClassLoaderData* cld) = 0;
+};
+
+class KlassToOopClosure : public KlassClosure {
+  friend class MetadataAwareOopClosure;
+  friend class MetadataAwareOopsInGenClosure;
+
+  OopClosure* _oop_closure;
+
+  // Used when _oop_closure couldn't be set in an initialization list.
+  void initialize(OopClosure* oop_closure) {
+    assert(_oop_closure == NULL, "Should only be called once");
+    _oop_closure = oop_closure;
+  }
+
+ public:
+  KlassToOopClosure(OopClosure* oop_closure = NULL) : _oop_closure(oop_closure) {}
+
   virtual void do_klass(Klass* k);
 };
 
-class CLDToOopClosure {
-  OopClosure* _oop_closure;
+class CLDToOopClosure : public CLDClosure {
+  OopClosure*       _oop_closure;
   KlassToOopClosure _klass_closure;
-  bool _must_claim_cld;
+  bool              _must_claim_cld;
 
  public:
   CLDToOopClosure(OopClosure* oop_closure, bool must_claim_cld = true) :
@@ -149,6 +165,46 @@
   void do_cld(ClassLoaderData* cld);
 };
 
+class CLDToKlassAndOopClosure : public CLDClosure {
+  friend class SharedHeap;
+  friend class G1CollectedHeap;
+ protected:
+  OopClosure*   _oop_closure;
+  KlassClosure* _klass_closure;
+  bool          _must_claim_cld;
+ public:
+  CLDToKlassAndOopClosure(KlassClosure* klass_closure,
+                          OopClosure* oop_closure,
+                          bool must_claim_cld) :
+                              _oop_closure(oop_closure),
+                              _klass_closure(klass_closure),
+                              _must_claim_cld(must_claim_cld) {}
+  void do_cld(ClassLoaderData* cld);
+};
+
+// The base class for all concurrent marking closures,
+// that participates in class unloading.
+// It's used to proxy through the metadata to the oops defined in them.
+class MetadataAwareOopClosure: public ExtendedOopClosure {
+  KlassToOopClosure _klass_closure;
+
+ public:
+  MetadataAwareOopClosure() : ExtendedOopClosure() {
+    _klass_closure.initialize(this);
+  }
+  MetadataAwareOopClosure(ReferenceProcessor* rp) : ExtendedOopClosure(rp) {
+    _klass_closure.initialize(this);
+  }
+
+  virtual bool do_metadata()    { return do_metadata_nv(); }
+  inline  bool do_metadata_nv() { return true; }
+
+  virtual void do_klass(Klass* k);
+  void do_klass_nv(Klass* k);
+
+  virtual void do_class_loader_data(ClassLoaderData* cld);
+};
+
 // ObjectClosure is used for iterating through an object space
 
 class ObjectClosure : public Closure {
@@ -172,19 +228,6 @@
   ObjectToOopClosure(ExtendedOopClosure* cl) : _cl(cl) {}
 };
 
-// A version of ObjectClosure with "memory" (see _previous_address below)
-class UpwardsObjectClosure: public BoolObjectClosure {
-  HeapWord* _previous_address;
- public:
-  UpwardsObjectClosure() : _previous_address(NULL) { }
-  void set_previous(HeapWord* addr) { _previous_address = addr; }
-  HeapWord* previous()              { return _previous_address; }
-  // A return value of "true" can be used by the caller to decide
-  // if this object's end should *NOT* be recorded in
-  // _previous_address above.
-  virtual bool do_object_bm(oop obj, MemRegion mr) = 0;
-};
-
 // A version of ObjectClosure that is expected to be robust
 // in the face of possibly uninitialized objects.
 class ObjectClosureCareful : public ObjectClosure {
@@ -240,14 +283,26 @@
   virtual void do_code_blob(CodeBlob* cb) = 0;
 };
 
-
-class MarkingCodeBlobClosure : public CodeBlobClosure {
+// Applies an oop closure to all ref fields in code blobs
+// iterated over in an object iteration.
+class CodeBlobToOopClosure : public CodeBlobClosure {
+  OopClosure* _cl;
+  bool _fix_relocations;
+ protected:
+  void do_nmethod(nmethod* nm);
  public:
+  CodeBlobToOopClosure(OopClosure* cl, bool fix_relocations) : _cl(cl), _fix_relocations(fix_relocations) {}
+  virtual void do_code_blob(CodeBlob* cb);
+
+  const static bool FixRelocations = true;
+};
+
+class MarkingCodeBlobClosure : public CodeBlobToOopClosure {
+ public:
+  MarkingCodeBlobClosure(OopClosure* cl, bool fix_relocations) : CodeBlobToOopClosure(cl, fix_relocations) {}
   // Called for each code blob, but at most once per unique blob.
-  virtual void do_newly_marked_nmethod(nmethod* nm) = 0;
 
   virtual void do_code_blob(CodeBlob* cb);
-    // = { if (!nmethod(cb)->test_set_oops_do_mark())  do_newly_marked_nmethod(cb); }
 
   class MarkScope : public StackObj {
   protected:
@@ -260,23 +315,6 @@
   };
 };
 
-
-// Applies an oop closure to all ref fields in code blobs
-// iterated over in an object iteration.
-class CodeBlobToOopClosure: public MarkingCodeBlobClosure {
-  OopClosure* _cl;
-  bool _do_marking;
-public:
-  virtual void do_newly_marked_nmethod(nmethod* cb);
-    // = { cb->oops_do(_cl); }
-  virtual void do_code_blob(CodeBlob* cb);
-    // = { if (_do_marking)  super::do_code_blob(cb); else cb->oops_do(_cl); }
-  CodeBlobToOopClosure(OopClosure* cl, bool do_marking)
-    : _cl(cl), _do_marking(do_marking) {}
-};
-
-
-
 // MonitorClosure is used for iterating over monitors in the monitors cache
 
 class ObjectMonitor;
@@ -345,4 +383,16 @@
   }
 };
 
+
+// Helper defines for ExtendOopClosure
+
+#define if_do_metadata_checked(closure, nv_suffix)       \
+  /* Make sure the non-virtual and the virtual versions match. */     \
+  assert(closure->do_metadata##nv_suffix() == closure->do_metadata(), \
+      "Inconsistency in do_metadata");                                \
+  if (closure->do_metadata##nv_suffix())
+
+#define assert_should_ignore_metadata(closure, nv_suffix)                                  \
+  assert(!closure->do_metadata##nv_suffix(), "Code to handle metadata is not implemented")
+
 #endif // SHARE_VM_MEMORY_ITERATOR_HPP
diff --git a/hotspot/src/share/vm/memory/iterator.inline.hpp b/hotspot/src/share/vm/memory/iterator.inline.hpp
new file mode 100644
index 0000000..cef1266
--- /dev/null
+++ b/hotspot/src/share/vm/memory/iterator.inline.hpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_MEMORY_ITERATOR_INLINE_HPP
+#define SHARE_VM_MEMORY_ITERATOR_INLINE_HPP
+
+#include "classfile/classLoaderData.hpp"
+#include "memory/iterator.hpp"
+#include "oops/klass.hpp"
+#include "utilities/debug.hpp"
+
+inline void MetadataAwareOopClosure::do_class_loader_data(ClassLoaderData* cld) {
+  assert(_klass_closure._oop_closure == this, "Must be");
+
+  bool claim = true;  // Must claim the class loader data before processing.
+  cld->oops_do(_klass_closure._oop_closure, &_klass_closure, claim);
+}
+
+inline void MetadataAwareOopClosure::do_klass_nv(Klass* k) {
+  ClassLoaderData* cld = k->class_loader_data();
+  do_class_loader_data(cld);
+}
+
+inline void MetadataAwareOopClosure::do_klass(Klass* k)       { do_klass_nv(k); }
+
+#endif // SHARE_VM_MEMORY_ITERATOR_INLINE_HPP
diff --git a/hotspot/src/share/vm/memory/memRegion.cpp b/hotspot/src/share/vm/memory/memRegion.cpp
index 9eb2be5..8c33ddc 100644
--- a/hotspot/src/share/vm/memory/memRegion.cpp
+++ b/hotspot/src/share/vm/memory/memRegion.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 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
@@ -103,11 +103,13 @@
 }
 
 void* MemRegion::operator new(size_t size) throw() {
-  return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL);
+  return (address)AllocateHeap(size, mtGC, CURRENT_PC,
+    AllocFailStrategy::RETURN_NULL);
 }
 
 void* MemRegion::operator new [](size_t size) throw() {
-  return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL);
+  return (address)AllocateHeap(size, mtGC, CURRENT_PC,
+    AllocFailStrategy::RETURN_NULL);
 }
 void  MemRegion::operator delete(void* p) {
   FreeHeap(p, mtGC);
diff --git a/hotspot/src/share/vm/memory/metadataFactory.hpp b/hotspot/src/share/vm/memory/metadataFactory.hpp
index 9f7a22e..dbb936f 100644
--- a/hotspot/src/share/vm/memory/metadataFactory.hpp
+++ b/hotspot/src/share/vm/memory/metadataFactory.hpp
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_MEMORY_METADATAFACTORY_HPP
 #define SHARE_VM_MEMORY_METADATAFACTORY_HPP
 
+#include "classfile/classLoaderData.hpp"
 #include "utilities/array.hpp"
 #include "utilities/exceptions.hpp"
 #include "utilities/globalDefinitions.hpp"
diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp
index 8fb833b..359faa0 100644
--- a/hotspot/src/share/vm/memory/metaspace.cpp
+++ b/hotspot/src/share/vm/memory/metaspace.cpp
@@ -42,7 +42,7 @@
 #include "runtime/init.hpp"
 #include "runtime/java.hpp"
 #include "runtime/mutex.hpp"
-#include "runtime/orderAccess.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "services/memTracker.hpp"
 #include "services/memoryService.hpp"
 #include "utilities/copy.hpp"
diff --git a/hotspot/src/share/vm/memory/referenceProcessor.cpp b/hotspot/src/share/vm/memory/referenceProcessor.cpp
index 3eca2ba..7eaa316 100644
--- a/hotspot/src/share/vm/memory/referenceProcessor.cpp
+++ b/hotspot/src/share/vm/memory/referenceProcessor.cpp
@@ -190,7 +190,8 @@
   OopClosure*                  keep_alive,
   VoidClosure*                 complete_gc,
   AbstractRefProcTaskExecutor* task_executor,
-  GCTimer*                     gc_timer) {
+  GCTimer*                     gc_timer,
+  GCId                         gc_id) {
   NOT_PRODUCT(verify_ok_to_handle_reflists());
 
   assert(!enqueuing_is_done(), "If here enqueuing should not be complete");
@@ -212,7 +213,7 @@
   // Soft references
   size_t soft_count = 0;
   {
-    GCTraceTime tt("SoftReference", trace_time, false, gc_timer);
+    GCTraceTime tt("SoftReference", trace_time, false, gc_timer, gc_id);
     soft_count =
       process_discovered_reflist(_discoveredSoftRefs, _current_soft_ref_policy, true,
                                  is_alive, keep_alive, complete_gc, task_executor);
@@ -223,7 +224,7 @@
   // Weak references
   size_t weak_count = 0;
   {
-    GCTraceTime tt("WeakReference", trace_time, false, gc_timer);
+    GCTraceTime tt("WeakReference", trace_time, false, gc_timer, gc_id);
     weak_count =
       process_discovered_reflist(_discoveredWeakRefs, NULL, true,
                                  is_alive, keep_alive, complete_gc, task_executor);
@@ -232,7 +233,7 @@
   // Final references
   size_t final_count = 0;
   {
-    GCTraceTime tt("FinalReference", trace_time, false, gc_timer);
+    GCTraceTime tt("FinalReference", trace_time, false, gc_timer, gc_id);
     final_count =
       process_discovered_reflist(_discoveredFinalRefs, NULL, false,
                                  is_alive, keep_alive, complete_gc, task_executor);
@@ -241,7 +242,7 @@
   // Phantom references
   size_t phantom_count = 0;
   {
-    GCTraceTime tt("PhantomReference", trace_time, false, gc_timer);
+    GCTraceTime tt("PhantomReference", trace_time, false, gc_timer, gc_id);
     phantom_count =
       process_discovered_reflist(_discoveredPhantomRefs, NULL, false,
                                  is_alive, keep_alive, complete_gc, task_executor);
@@ -253,7 +254,7 @@
   // thus use JNI weak references to circumvent the phantom references and
   // resurrect a "post-mortem" object.
   {
-    GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer);
+    GCTraceTime tt("JNI Weak Reference", trace_time, false, gc_timer, gc_id);
     if (task_executor != NULL) {
       task_executor->set_single_threaded_mode();
     }
@@ -1251,14 +1252,15 @@
   OopClosure* keep_alive,
   VoidClosure* complete_gc,
   YieldClosure* yield,
-  GCTimer* gc_timer) {
+  GCTimer* gc_timer,
+  GCId     gc_id) {
 
   NOT_PRODUCT(verify_ok_to_handle_reflists());
 
   // Soft references
   {
     GCTraceTime tt("Preclean SoftReferences", PrintGCDetails && PrintReferenceGC,
-              false, gc_timer);
+              false, gc_timer, gc_id);
     for (uint i = 0; i < _max_num_q; i++) {
       if (yield->should_return()) {
         return;
@@ -1271,7 +1273,7 @@
   // Weak references
   {
     GCTraceTime tt("Preclean WeakReferences", PrintGCDetails && PrintReferenceGC,
-              false, gc_timer);
+              false, gc_timer, gc_id);
     for (uint i = 0; i < _max_num_q; i++) {
       if (yield->should_return()) {
         return;
@@ -1284,7 +1286,7 @@
   // Final references
   {
     GCTraceTime tt("Preclean FinalReferences", PrintGCDetails && PrintReferenceGC,
-              false, gc_timer);
+              false, gc_timer, gc_id);
     for (uint i = 0; i < _max_num_q; i++) {
       if (yield->should_return()) {
         return;
@@ -1297,7 +1299,7 @@
   // Phantom references
   {
     GCTraceTime tt("Preclean PhantomReferences", PrintGCDetails && PrintReferenceGC,
-              false, gc_timer);
+              false, gc_timer, gc_id);
     for (uint i = 0; i < _max_num_q; i++) {
       if (yield->should_return()) {
         return;
diff --git a/hotspot/src/share/vm/memory/referenceProcessor.hpp b/hotspot/src/share/vm/memory/referenceProcessor.hpp
index e1dd2c7..0fba558 100644
--- a/hotspot/src/share/vm/memory/referenceProcessor.hpp
+++ b/hotspot/src/share/vm/memory/referenceProcessor.hpp
@@ -25,6 +25,7 @@
 #ifndef SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP
 #define SHARE_VM_MEMORY_REFERENCEPROCESSOR_HPP
 
+#include "gc_implementation/shared/gcTrace.hpp"
 #include "memory/referencePolicy.hpp"
 #include "memory/referenceProcessorStats.hpp"
 #include "memory/referenceType.hpp"
@@ -349,7 +350,8 @@
                                       OopClosure*        keep_alive,
                                       VoidClosure*       complete_gc,
                                       YieldClosure*      yield,
-                                      GCTimer*           gc_timer);
+                                      GCTimer*           gc_timer,
+                                      GCId               gc_id);
 
   // Delete entries in the discovered lists that have
   // either a null referent or are not active. Such
@@ -480,7 +482,8 @@
                                 OopClosure*                  keep_alive,
                                 VoidClosure*                 complete_gc,
                                 AbstractRefProcTaskExecutor* task_executor,
-                                GCTimer *gc_timer);
+                                GCTimer *gc_timer,
+                                GCId    gc_id);
 
   // Enqueue references at end of GC (called by the garbage collector)
   bool enqueue_discovered_references(AbstractRefProcTaskExecutor* task_executor = NULL);
diff --git a/hotspot/src/share/vm/memory/resourceArea.hpp b/hotspot/src/share/vm/memory/resourceArea.hpp
index 1357081..567b5fc 100644
--- a/hotspot/src/share/vm/memory/resourceArea.hpp
+++ b/hotspot/src/share/vm/memory/resourceArea.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -49,11 +49,11 @@
   debug_only(static int _warned;)       // to suppress multiple warnings
 
 public:
-  ResourceArea() {
+  ResourceArea() : Arena(mtThread) {
     debug_only(_nesting = 0;)
   }
 
-  ResourceArea(size_t init_size) : Arena(init_size) {
+  ResourceArea(size_t init_size) : Arena(mtThread, init_size) {
     debug_only(_nesting = 0;);
   }
 
@@ -64,7 +64,7 @@
     if (UseMallocOnly) {
       // use malloc, but save pointer in res. area for later freeing
       char** save = (char**)internal_malloc_4(sizeof(char*));
-      return (*save = (char*)os::malloc(size, mtThread));
+      return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC));
     }
 #endif
     return (char*)Amalloc(size, alloc_failmode);
diff --git a/hotspot/src/share/vm/memory/sharedHeap.cpp b/hotspot/src/share/vm/memory/sharedHeap.cpp
index 56683fe..bf7a4bb 100644
--- a/hotspot/src/share/vm/memory/sharedHeap.cpp
+++ b/hotspot/src/share/vm/memory/sharedHeap.cpp
@@ -29,6 +29,7 @@
 #include "gc_interface/collectedHeap.inline.hpp"
 #include "memory/sharedHeap.hpp"
 #include "oops/oop.inline.hpp"
+#include "runtime/atomic.inline.hpp"
 #include "runtime/fprofiler.hpp"
 #include "runtime/java.hpp"
 #include "services/management.hpp"
@@ -39,8 +40,8 @@
 
 SharedHeap* SharedHeap::_sh;
 
-// The set of potentially parallel tasks in strong root scanning.
-enum SH_process_strong_roots_tasks {
+// The set of potentially parallel tasks in root scanning.
+enum SH_process_roots_tasks {
   SH_PS_Universe_oops_do,
   SH_PS_JNIHandles_oops_do,
   SH_PS_ObjectSynchronizer_oops_do,
@@ -58,6 +59,7 @@
   CollectedHeap(),
   _collector_policy(policy_),
   _rem_set(NULL),
+  _strong_roots_scope(NULL),
   _strong_roots_parity(0),
   _process_strong_tasks(new SubTasksDone(SH_PS_NumElements)),
   _workers(NULL)
@@ -114,6 +116,19 @@
 static AssertNonScavengableClosure assert_is_non_scavengable_closure;
 #endif
 
+SharedHeap::StrongRootsScope* SharedHeap::active_strong_roots_scope() const {
+  return _strong_roots_scope;
+}
+void SharedHeap::register_strong_roots_scope(SharedHeap::StrongRootsScope* scope) {
+  assert(_strong_roots_scope == NULL, "Should only have one StrongRootsScope active");
+  assert(scope != NULL, "Illegal argument");
+  _strong_roots_scope = scope;
+}
+void SharedHeap::unregister_strong_roots_scope(SharedHeap::StrongRootsScope* scope) {
+  assert(_strong_roots_scope == scope, "Wrong scope unregistered");
+  _strong_roots_scope = NULL;
+}
+
 void SharedHeap::change_strong_roots_parity() {
   // Also set the new collection parity.
   assert(_strong_roots_parity >= 0 && _strong_roots_parity <= 2,
@@ -124,122 +139,173 @@
          "Not in range.");
 }
 
-SharedHeap::StrongRootsScope::StrongRootsScope(SharedHeap* outer, bool activate)
-  : MarkScope(activate)
+SharedHeap::StrongRootsScope::StrongRootsScope(SharedHeap* heap, bool activate)
+  : MarkScope(activate), _sh(heap), _n_workers_done_with_threads(0)
 {
   if (_active) {
-    outer->change_strong_roots_parity();
+    _sh->register_strong_roots_scope(this);
+    _sh->change_strong_roots_parity();
     // Zero the claimed high water mark in the StringTable
     StringTable::clear_parallel_claimed_index();
   }
 }
 
 SharedHeap::StrongRootsScope::~StrongRootsScope() {
-  // nothing particular
+  if (_active) {
+    _sh->unregister_strong_roots_scope(this);
+  }
 }
 
-void SharedHeap::process_strong_roots(bool activate_scope,
-                                      bool is_scavenging,
-                                      ScanningOption so,
-                                      OopClosure* roots,
-                                      CodeBlobClosure* code_roots,
-                                      KlassClosure* klass_closure) {
+Monitor* SharedHeap::StrongRootsScope::_lock = new Monitor(Mutex::leaf, "StrongRootsScope lock", false);
+
+void SharedHeap::StrongRootsScope::mark_worker_done_with_threads(uint n_workers) {
+  // The Thread work barrier is only needed by G1 Class Unloading.
+  // No need to use the barrier if this is single-threaded code.
+  if (UseG1GC && ClassUnloadingWithConcurrentMark && n_workers > 0) {
+    uint new_value = (uint)Atomic::add(1, &_n_workers_done_with_threads);
+    if (new_value == n_workers) {
+      // This thread is last. Notify the others.
+      MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+      _lock->notify_all();
+    }
+  }
+}
+
+void SharedHeap::StrongRootsScope::wait_until_all_workers_done_with_threads(uint n_workers) {
+  assert(UseG1GC,                          "Currently only used by G1");
+  assert(ClassUnloadingWithConcurrentMark, "Currently only needed when doing G1 Class Unloading");
+
+  // No need to use the barrier if this is single-threaded code.
+  if (n_workers > 0 && (uint)_n_workers_done_with_threads != n_workers) {
+    MonitorLockerEx ml(_lock, Mutex::_no_safepoint_check_flag);
+    while ((uint)_n_workers_done_with_threads != n_workers) {
+      _lock->wait(Mutex::_no_safepoint_check_flag, 0, false);
+    }
+  }
+}
+
+void SharedHeap::process_roots(bool activate_scope,
+                               ScanningOption so,
+                               OopClosure* strong_roots,
+                               OopClosure* weak_roots,
+                               CLDClosure* strong_cld_closure,
+                               CLDClosure* weak_cld_closure,
+                               CodeBlobClosure* code_roots) {
   StrongRootsScope srs(this, activate_scope);
 
-  // General strong roots.
+  // General roots.
   assert(_strong_roots_parity != 0, "must have called prologue code");
+  assert(code_roots != NULL, "code root closure should always be set");
   // _n_termination for _process_strong_tasks should be set up stream
   // in a method not running in a GC worker.  Otherwise the GC worker
   // could be trying to change the termination condition while the task
   // is executing in another GC worker.
+
+  // Iterating over the CLDG and the Threads are done early to allow G1 to
+  // first process the strong CLDs and nmethods and then, after a barrier,
+  // let the thread process the weak CLDs and nmethods.
+
+  if (!_process_strong_tasks->is_task_claimed(SH_PS_ClassLoaderDataGraph_oops_do)) {
+    ClassLoaderDataGraph::roots_cld_do(strong_cld_closure, weak_cld_closure);
+  }
+
+  // Some CLDs contained in the thread frames should be considered strong.
+  // Don't process them if they will be processed during the ClassLoaderDataGraph phase.
+  CLDClosure* roots_from_clds_p = (strong_cld_closure != weak_cld_closure) ? strong_cld_closure : NULL;
+  // Only process code roots from thread stacks if we aren't visiting the entire CodeCache anyway
+  CodeBlobClosure* roots_from_code_p = (so & SO_AllCodeCache) ? NULL : code_roots;
+
+  Threads::possibly_parallel_oops_do(strong_roots, roots_from_clds_p, roots_from_code_p);
+
+  // This is the point where this worker thread will not find more strong CLDs/nmethods.
+  // Report this so G1 can synchronize the strong and weak CLDs/nmethods processing.
+  active_strong_roots_scope()->mark_worker_done_with_threads(n_par_threads());
+
   if (!_process_strong_tasks->is_task_claimed(SH_PS_Universe_oops_do)) {
-    Universe::oops_do(roots);
+    Universe::oops_do(strong_roots);
   }
   // Global (strong) JNI handles
   if (!_process_strong_tasks->is_task_claimed(SH_PS_JNIHandles_oops_do))
-    JNIHandles::oops_do(roots);
-
-  // All threads execute this; the individual threads are task groups.
-  CLDToOopClosure roots_from_clds(roots);
-  CLDToOopClosure* roots_from_clds_p = (is_scavenging ? NULL : &roots_from_clds);
-  if (CollectedHeap::use_parallel_gc_threads()) {
-    Threads::possibly_parallel_oops_do(roots, roots_from_clds_p, code_roots);
-  } else {
-    Threads::oops_do(roots, roots_from_clds_p, code_roots);
-  }
+    JNIHandles::oops_do(strong_roots);
 
   if (!_process_strong_tasks-> is_task_claimed(SH_PS_ObjectSynchronizer_oops_do))
-    ObjectSynchronizer::oops_do(roots);
+    ObjectSynchronizer::oops_do(strong_roots);
   if (!_process_strong_tasks->is_task_claimed(SH_PS_FlatProfiler_oops_do))
-    FlatProfiler::oops_do(roots);
+    FlatProfiler::oops_do(strong_roots);
   if (!_process_strong_tasks->is_task_claimed(SH_PS_Management_oops_do))
-    Management::oops_do(roots);
+    Management::oops_do(strong_roots);
   if (!_process_strong_tasks->is_task_claimed(SH_PS_jvmti_oops_do))
-    JvmtiExport::oops_do(roots);
+    JvmtiExport::oops_do(strong_roots);
 
   if (!_process_strong_tasks->is_task_claimed(SH_PS_SystemDictionary_oops_do)) {
-    if (so & SO_AllClasses) {
-      SystemDictionary::oops_do(roots);
-    } else if (so & SO_SystemClasses) {
-      SystemDictionary::always_strong_oops_do(roots);
-    } else {
-      fatal("We should always have selected either SO_AllClasses or SO_SystemClasses");
-    }
-  }
-
-  if (!_process_strong_tasks->is_task_claimed(SH_PS_ClassLoaderDataGraph_oops_do)) {
-    if (so & SO_AllClasses) {
-      ClassLoaderDataGraph::oops_do(roots, klass_closure, !is_scavenging);
-    } else if (so & SO_SystemClasses) {
-      ClassLoaderDataGraph::always_strong_oops_do(roots, klass_closure, !is_scavenging);
-    }
+    SystemDictionary::roots_oops_do(strong_roots, weak_roots);
   }
 
   // All threads execute the following. A specific chunk of buckets
   // from the StringTable are the individual tasks.
-  if (so & SO_Strings) {
+  if (weak_roots != NULL) {
     if (CollectedHeap::use_parallel_gc_threads()) {
-      StringTable::possibly_parallel_oops_do(roots);
+      StringTable::possibly_parallel_oops_do(weak_roots);
     } else {
-      StringTable::oops_do(roots);
+      StringTable::oops_do(weak_roots);
     }
   }
 
   if (!_process_strong_tasks->is_task_claimed(SH_PS_CodeCache_oops_do)) {
-    if (so & SO_CodeCache) {
+    if (so & SO_ScavengeCodeCache) {
       assert(code_roots != NULL, "must supply closure for code cache");
 
-      if (is_scavenging) {
-        // We only visit parts of the CodeCache when scavenging.
-        CodeCache::scavenge_root_nmethods_do(code_roots);
-      } else {
-        // CMSCollector uses this to do intermediate-strength collections.
-        // We scan the entire code cache, since CodeCache::do_unloading is not called.
-        CodeCache::blobs_do(code_roots);
-      }
+      // We only visit parts of the CodeCache when scavenging.
+      CodeCache::scavenge_root_nmethods_do(code_roots);
+    }
+    if (so & SO_AllCodeCache) {
+      assert(code_roots != NULL, "must supply closure for code cache");
+
+      // CMSCollector uses this to do intermediate-strength collections.
+      // We scan the entire code cache, since CodeCache::do_unloading is not called.
+      CodeCache::blobs_do(code_roots);
     }
     // Verify that the code cache contents are not subject to
     // movement by a scavenging collection.
-    DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, /*do_marking=*/ false));
+    DEBUG_ONLY(CodeBlobToOopClosure assert_code_is_non_scavengable(&assert_is_non_scavengable_closure, !CodeBlobToOopClosure::FixRelocations));
     DEBUG_ONLY(CodeCache::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable));
   }
 
   _process_strong_tasks->all_tasks_completed();
 }
 
+void SharedHeap::process_all_roots(bool activate_scope,
+                                   ScanningOption so,
+                                   OopClosure* roots,
+                                   CLDClosure* cld_closure,
+                                   CodeBlobClosure* code_closure) {
+  process_roots(activate_scope, so,
+                roots, roots,
+                cld_closure, cld_closure,
+                code_closure);
+}
+
+void SharedHeap::process_strong_roots(bool activate_scope,
+                                      ScanningOption so,
+                                      OopClosure* roots,
+                                      CLDClosure* cld_closure,
+                                      CodeBlobClosure* code_closure) {
+  process_roots(activate_scope, so,
+                roots, NULL,
+                cld_closure, NULL,
+                code_closure);
+}
+
+
 class AlwaysTrueClosure: public BoolObjectClosure {
 public:
   bool do_object_b(oop p) { return true; }
 };
 static AlwaysTrueClosure always_true;
 
-void SharedHeap::process_weak_roots(OopClosure* root_closure,
-                                    CodeBlobClosure* code_roots) {
+void SharedHeap::process_weak_roots(OopClosure* root_closure) {
   // Global (weak) JNI handles
   JNIHandles::weak_oops_do(&always_true, root_closure);
-
-  CodeCache::blobs_do(code_roots);
-  StringTable::oops_do(root_closure);
 }
 
 void SharedHeap::set_barrier_set(BarrierSet* bs) {
diff --git a/hotspot/src/share/vm/memory/sharedHeap.hpp b/hotspot/src/share/vm/memory/sharedHeap.hpp
index f5d9e05..9827817 100644
--- a/hotspot/src/share/vm/memory/sharedHeap.hpp
+++ b/hotspot/src/share/vm/memory/sharedHeap.hpp
@@ -69,14 +69,10 @@
 //    number of active GC workers.  CompactibleFreeListSpace and Space
 //    have SequentialSubTasksDone's.
 // Example of using SubTasksDone and SequentialSubTasksDone
-// G1CollectedHeap::g1_process_strong_roots() calls
-//  process_strong_roots(false, // no scoping; this is parallel code
-//                       is_scavenging, so,
-//                       &buf_scan_non_heap_roots,
-//                       &eager_scan_code_roots);
-//  which delegates to SharedHeap::process_strong_roots() and uses
+// G1CollectedHeap::g1_process_roots()
+//  to SharedHeap::process_roots() and uses
 //  SubTasksDone* _process_strong_tasks to claim tasks.
-//  process_strong_roots() calls
+//  process_roots() calls
 //      rem_set()->younger_refs_iterate()
 //  to scan the card table and which eventually calls down into
 //  CardTableModRefBS::par_non_clean_card_iterate_work().  This method
@@ -163,9 +159,6 @@
   // Iteration functions.
   void oop_iterate(ExtendedOopClosure* cl) = 0;
 
-  // Same as above, restricted to a memory region.
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0;
-
   // Iterate over all spaces in use in the heap, in an undefined order.
   virtual void space_iterate(SpaceClosure* cl) = 0;
 
@@ -185,12 +178,12 @@
   // task.  (This also means that a parallel thread may only call
   // process_strong_roots once.)
   //
-  // For calls to process_strong_roots by sequential code, the parity is
+  // For calls to process_roots by sequential code, the parity is
   // updated automatically.
   //
   // The idea is that objects representing fine-grained tasks, such as
   // threads, will contain a "parity" field.  A task will is claimed in the
-  // current "process_strong_roots" call only if its parity field is the
+  // current "process_roots" call only if its parity field is the
   // same as the "strong_roots_parity"; task claiming is accomplished by
   // updating the parity field to the strong_roots_parity with a CAS.
   //
@@ -201,27 +194,45 @@
   //   c) to never return a distinguished value (zero) with which such
   //      task-claiming variables may be initialized, to indicate "never
   //      claimed".
- private:
-  void change_strong_roots_parity();
  public:
   int strong_roots_parity() { return _strong_roots_parity; }
 
-  // Call these in sequential code around process_strong_roots.
+  // Call these in sequential code around process_roots.
   // strong_roots_prologue calls change_strong_roots_parity, if
   // parallel tasks are enabled.
   class StrongRootsScope : public MarkingCodeBlobClosure::MarkScope {
-  public:
-    StrongRootsScope(SharedHeap* outer, bool activate = true);
+    // Used to implement the Thread work barrier.
+    static Monitor* _lock;
+
+    SharedHeap*   _sh;
+    volatile jint _n_workers_done_with_threads;
+
+   public:
+    StrongRootsScope(SharedHeap* heap, bool activate = true);
     ~StrongRootsScope();
+
+    // Mark that this thread is done with the Threads work.
+    void mark_worker_done_with_threads(uint n_workers);
+    // Wait until all n_workers are done with the Threads work.
+    void wait_until_all_workers_done_with_threads(uint n_workers);
   };
   friend class StrongRootsScope;
 
+  // The current active StrongRootScope
+  StrongRootsScope* _strong_roots_scope;
+
+  StrongRootsScope* active_strong_roots_scope() const;
+
+ private:
+  void register_strong_roots_scope(StrongRootsScope* scope);
+  void unregister_strong_roots_scope(StrongRootsScope* scope);
+  void change_strong_roots_parity();
+
+ public:
   enum ScanningOption {
-    SO_None                = 0x0,
-    SO_AllClasses          = 0x1,
-    SO_SystemClasses       = 0x2,
-    SO_Strings             = 0x4,
-    SO_CodeCache           = 0x8
+    SO_None                =  0x0,
+    SO_AllCodeCache        =  0x8,
+    SO_ScavengeCodeCache   = 0x10
   };
 
   FlexibleWorkGang* workers() const { return _workers; }
@@ -229,22 +240,29 @@
   // Invoke the "do_oop" method the closure "roots" on all root locations.
   // The "so" argument determines which roots the closure is applied to:
   // "SO_None" does none;
-  // "SO_AllClasses" applies the closure to all entries in the SystemDictionary;
-  // "SO_SystemClasses" to all the "system" classes and loaders;
-  // "SO_Strings" applies the closure to all entries in StringTable;
-  // "SO_CodeCache" applies the closure to all elements of the CodeCache.
+  // "SO_AllCodeCache" applies the closure to all elements of the CodeCache.
+  // "SO_ScavengeCodeCache" applies the closure to elements on the scavenge root list in the CodeCache.
+  void process_roots(bool activate_scope,
+                     ScanningOption so,
+                     OopClosure* strong_roots,
+                     OopClosure* weak_roots,
+                     CLDClosure* strong_cld_closure,
+                     CLDClosure* weak_cld_closure,
+                     CodeBlobClosure* code_roots);
+  void process_all_roots(bool activate_scope,
+                         ScanningOption so,
+                         OopClosure* roots,
+                         CLDClosure* cld_closure,
+                         CodeBlobClosure* code_roots);
   void process_strong_roots(bool activate_scope,
-                            bool is_scavenging,
                             ScanningOption so,
                             OopClosure* roots,
-                            CodeBlobClosure* code_roots,
-                            KlassClosure* klass_closure);
+                            CLDClosure* cld_closure,
+                            CodeBlobClosure* code_roots);
 
-  // Apply "blk" to all the weak roots of the system.  These include
-  // JNI weak roots, the code cache, system dictionary, symbol table,
-  // string table.
-  void process_weak_roots(OopClosure* root_closure,
-                          CodeBlobClosure* code_roots);
+
+  // Apply "root_closure" to the JNI weak roots..
+  void process_weak_roots(OopClosure* root_closure);
 
   // The functions below are helper functions that a subclass of
   // "SharedHeap" can use in the implementation of its virtual
@@ -257,7 +275,7 @@
   virtual void gc_epilogue(bool full) = 0;
 
   // Sets the number of parallel threads that will be doing tasks
-  // (such as process strong roots) subsequently.
+  // (such as process roots) subsequently.
   virtual void set_par_threads(uint t);
 
   int n_termination();
@@ -274,4 +292,8 @@
                              size_t capacity);
 };
 
+inline SharedHeap::ScanningOption operator|(SharedHeap::ScanningOption so0, SharedHeap::ScanningOption so1) {
+  return static_cast<SharedHeap::ScanningOption>(static_cast<int>(so0) | static_cast<int>(so1));
+}
+
 #endif // SHARE_VM_MEMORY_SHAREDHEAP_HPP
diff --git a/hotspot/src/share/vm/memory/space.cpp b/hotspot/src/share/vm/memory/space.cpp
index 0c3b46c..317384f 100644
--- a/hotspot/src/share/vm/memory/space.cpp
+++ b/hotspot/src/share/vm/memory/space.cpp
@@ -28,6 +28,7 @@
 #include "gc_implementation/shared/liveRange.hpp"
 #include "gc_implementation/shared/markSweep.hpp"
 #include "gc_implementation/shared/spaceDecorator.hpp"
+#include "gc_interface/collectedHeap.inline.hpp"
 #include "memory/blockOffsetTable.inline.hpp"
 #include "memory/defNewGeneration.hpp"
 #include "memory/genCollectedHeap.hpp"
@@ -37,14 +38,13 @@
 #include "oops/oop.inline.hpp"
 #include "oops/oop.inline2.hpp"
 #include "runtime/java.hpp"
+#include "runtime/prefetch.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/safepoint.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/globalDefinitions.hpp"
 #include "utilities/macros.hpp"
 
-void SpaceMemRegionOopsIterClosure::do_oop(oop* p)       { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
-void SpaceMemRegionOopsIterClosure::do_oop(narrowOop* p) { SpaceMemRegionOopsIterClosure::do_oop_work(p); }
-
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
 HeapWord* DirtyCardToOopClosure::get_actual_top(HeapWord* top,
@@ -307,10 +307,6 @@
   CompactibleSpace::clear(mangle_space);
 }
 
-bool ContiguousSpace::is_in(const void* p) const {
-  return _bottom <= p && p < _top;
-}
-
 bool ContiguousSpace::is_free_block(const HeapWord* p) const {
   return p >= _top;
 }
@@ -552,115 +548,11 @@
   object_iterate(&blk2);
 }
 
-HeapWord* Space::object_iterate_careful(ObjectClosureCareful* cl) {
-  guarantee(false, "NYI");
-  return bottom();
-}
-
-HeapWord* Space::object_iterate_careful_m(MemRegion mr,
-                                          ObjectClosureCareful* cl) {
-  guarantee(false, "NYI");
-  return bottom();
-}
-
-
-void Space::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) {
-  assert(!mr.is_empty(), "Should be non-empty");
-  // We use MemRegion(bottom(), end()) rather than used_region() below
-  // because the two are not necessarily equal for some kinds of
-  // spaces, in particular, certain kinds of free list spaces.
-  // We could use the more complicated but more precise:
-  // MemRegion(used_region().start(), round_to(used_region().end(), CardSize))
-  // but the slight imprecision seems acceptable in the assertion check.
-  assert(MemRegion(bottom(), end()).contains(mr),
-         "Should be within used space");
-  HeapWord* prev = cl->previous();   // max address from last time
-  if (prev >= mr.end()) { // nothing to do
-    return;
-  }
-  // This assert will not work when we go from cms space to perm
-  // space, and use same closure. Easy fix deferred for later. XXX YSR
-  // assert(prev == NULL || contains(prev), "Should be within space");
-
-  bool last_was_obj_array = false;
-  HeapWord *blk_start_addr, *region_start_addr;
-  if (prev > mr.start()) {
-    region_start_addr = prev;
-    blk_start_addr    = prev;
-    // The previous invocation may have pushed "prev" beyond the
-    // last allocated block yet there may be still be blocks
-    // in this region due to a particular coalescing policy.
-    // Relax the assertion so that the case where the unallocated
-    // block is maintained and "prev" is beyond the unallocated
-    // block does not cause the assertion to fire.
-    assert((BlockOffsetArrayUseUnallocatedBlock &&
-            (!is_in(prev))) ||
-           (blk_start_addr == block_start(region_start_addr)), "invariant");
-  } else {
-    region_start_addr = mr.start();
-    blk_start_addr    = block_start(region_start_addr);
-  }
-  HeapWord* region_end_addr = mr.end();
-  MemRegion derived_mr(region_start_addr, region_end_addr);
-  while (blk_start_addr < region_end_addr) {
-    const size_t size = block_size(blk_start_addr);
-    if (block_is_obj(blk_start_addr)) {
-      last_was_obj_array = cl->do_object_bm(oop(blk_start_addr), derived_mr);
-    } else {
-      last_was_obj_array = false;
-    }
-    blk_start_addr += size;
-  }
-  if (!last_was_obj_array) {
-    assert((bottom() <= blk_start_addr) && (blk_start_addr <= end()),
-           "Should be within (closed) used space");
-    assert(blk_start_addr > prev, "Invariant");
-    cl->set_previous(blk_start_addr); // min address for next time
-  }
-}
-
 bool Space::obj_is_alive(const HeapWord* p) const {
   assert (block_is_obj(p), "The address should point to an object");
   return true;
 }
 
-void ContiguousSpace::object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl) {
-  assert(!mr.is_empty(), "Should be non-empty");
-  assert(used_region().contains(mr), "Should be within used space");
-  HeapWord* prev = cl->previous();   // max address from last time
-  if (prev >= mr.end()) { // nothing to do
-    return;
-  }
-  // See comment above (in more general method above) in case you
-  // happen to use this method.
-  assert(prev == NULL || is_in_reserved(prev), "Should be within space");
-
-  bool last_was_obj_array = false;
-  HeapWord *obj_start_addr, *region_start_addr;
-  if (prev > mr.start()) {
-    region_start_addr = prev;
-    obj_start_addr    = prev;
-    assert(obj_start_addr == block_start(region_start_addr), "invariant");
-  } else {
-    region_start_addr = mr.start();
-    obj_start_addr    = block_start(region_start_addr);
-  }
-  HeapWord* region_end_addr = mr.end();
-  MemRegion derived_mr(region_start_addr, region_end_addr);
-  while (obj_start_addr < region_end_addr) {
-    oop obj = oop(obj_start_addr);
-    const size_t size = obj->size();
-    last_was_obj_array = cl->do_object_bm(obj, derived_mr);
-    obj_start_addr += size;
-  }
-  if (!last_was_obj_array) {
-    assert((bottom() <= obj_start_addr)  && (obj_start_addr <= end()),
-           "Should be within (closed) used space");
-    assert(obj_start_addr > prev, "Invariant");
-    cl->set_previous(obj_start_addr); // min address for next time
-  }
-}
-
 #if INCLUDE_ALL_GCS
 #define ContigSpace_PAR_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)         \
                                                                             \
@@ -688,43 +580,6 @@
   }
 }
 
-void ContiguousSpace::oop_iterate(MemRegion mr, ExtendedOopClosure* blk) {
-  if (is_empty()) {
-    return;
-  }
-  MemRegion cur = MemRegion(bottom(), top());
-  mr = mr.intersection(cur);
-  if (mr.is_empty()) {
-    return;
-  }
-  if (mr.equals(cur)) {
-    oop_iterate(blk);
-    return;
-  }
-  assert(mr.end() <= top(), "just took an intersection above");
-  HeapWord* obj_addr = block_start(mr.start());
-  HeapWord* t = mr.end();
-
-  // Handle first object specially.
-  oop obj = oop(obj_addr);
-  SpaceMemRegionOopsIterClosure smr_blk(blk, mr);
-  obj_addr += obj->oop_iterate(&smr_blk);
-  while (obj_addr < t) {
-    oop obj = oop(obj_addr);
-    assert(obj->is_oop(), "expected an oop");
-    obj_addr += obj->size();
-    // If "obj_addr" is not greater than top, then the
-    // entire object "obj" is within the region.
-    if (obj_addr <= t) {
-      obj->oop_iterate(blk);
-    } else {
-      // "obj" extends beyond end of region
-      obj->oop_iterate(&smr_blk);
-      break;
-    }
-  };
-}
-
 void ContiguousSpace::object_iterate(ObjectClosure* blk) {
   if (is_empty()) return;
   WaterMark bm = bottom_mark();
@@ -830,14 +685,8 @@
 // This version requires locking.
 inline HeapWord* ContiguousSpace::allocate_impl(size_t size,
                                                 HeapWord* const end_value) {
-  // In G1 there are places where a GC worker can allocates into a
-  // region using this serial allocation code without being prone to a
-  // race with other GC workers (we ensure that no other GC worker can
-  // access the same region at the same time). So the assert below is
-  // too strong in the case of G1.
   assert(Heap_lock->owned_by_self() ||
-         (SafepointSynchronize::is_at_safepoint() &&
-                               (Thread::current()->is_VM_thread() || UseG1GC)),
+         (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()),
          "not locked");
   HeapWord* obj = top();
   if (pointer_delta(end_value, obj) >= size) {
@@ -871,6 +720,27 @@
   } while (true);
 }
 
+HeapWord* ContiguousSpace::allocate_aligned(size_t size) {
+  assert(Heap_lock->owned_by_self() || (SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread()), "not locked");
+  HeapWord* end_value = end();
+
+  HeapWord* obj = CollectedHeap::align_allocation_or_fail(top(), end_value, SurvivorAlignmentInBytes);
+  if (obj == NULL) {
+    return NULL;
+  }
+
+  if (pointer_delta(end_value, obj) >= size) {
+    HeapWord* new_top = obj + size;
+    set_top(new_top);
+    assert(is_ptr_aligned(obj, SurvivorAlignmentInBytes) && is_aligned(new_top),
+      "checking alignment");
+    return obj;
+  } else {
+    set_top(obj);
+    return NULL;
+  }
+}
+
 // Requires locking.
 HeapWord* ContiguousSpace::allocate(size_t size) {
   return allocate_impl(size, end());
diff --git a/hotspot/src/share/vm/memory/space.hpp b/hotspot/src/share/vm/memory/space.hpp
index 2d11322..7ee6541 100644
--- a/hotspot/src/share/vm/memory/space.hpp
+++ b/hotspot/src/share/vm/memory/space.hpp
@@ -33,24 +33,8 @@
 #include "memory/watermark.hpp"
 #include "oops/markOop.hpp"
 #include "runtime/mutexLocker.hpp"
-#include "runtime/prefetch.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/workgroup.hpp"
-#ifdef TARGET_OS_FAMILY_linux
-# include "os_linux.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_solaris
-# include "os_solaris.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_windows
-# include "os_windows.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_aix
-# include "os_aix.inline.hpp"
-#endif
-#ifdef TARGET_OS_FAMILY_bsd
-# include "os_bsd.inline.hpp"
-#endif
 
 // A space is an abstraction for the "storage units" backing
 // up the generation abstraction. It includes specific
@@ -81,31 +65,6 @@
 class CardTableRS;
 class DirtyCardToOopClosure;
 
-// An oop closure that is circumscribed by a filtering memory region.
-class SpaceMemRegionOopsIterClosure: public ExtendedOopClosure {
- private:
-  ExtendedOopClosure* _cl;
-  MemRegion   _mr;
- protected:
-  template <class T> void do_oop_work(T* p) {
-    if (_mr.contains(p)) {
-      _cl->do_oop(p);
-    }
-  }
- public:
-  SpaceMemRegionOopsIterClosure(ExtendedOopClosure* cl, MemRegion mr):
-    _cl(cl), _mr(mr) {}
-  virtual void do_oop(oop* p);
-  virtual void do_oop(narrowOop* p);
-  virtual bool do_metadata() {
-    // _cl is of type ExtendedOopClosure instead of OopClosure, so that we can check this.
-    assert(!_cl->do_metadata(), "I've checked all call paths, this shouldn't happen.");
-    return false;
-  }
-  virtual void do_klass(Klass* k)                         { ShouldNotReachHere(); }
-  virtual void do_class_loader_data(ClassLoaderData* cld) { ShouldNotReachHere(); }
-};
-
 // A Space describes a heap area. Class Space is an abstract
 // base class.
 //
@@ -145,6 +104,12 @@
 
   void set_saved_mark_word(HeapWord* p) { _saved_mark_word = p; }
 
+  // Returns true if this object has been allocated since a
+  // generation's "save_marks" call.
+  virtual bool obj_allocated_since_save_marks(const oop obj) const {
+    return (HeapWord*)obj >= saved_mark_word();
+  }
+
   MemRegionClosure* preconsumptionDirtyCardClosure() const {
     return _preconsumptionDirtyCardClosure;
   }
@@ -152,9 +117,9 @@
     _preconsumptionDirtyCardClosure = cl;
   }
 
-  // Returns a subregion of the space containing all the objects in
+  // Returns a subregion of the space containing only the allocated objects in
   // the space.
-  virtual MemRegion used_region() const { return MemRegion(bottom(), end()); }
+  virtual MemRegion used_region() const = 0;
 
   // Returns a region that is guaranteed to contain (at least) all objects
   // allocated at the time of the last call to "save_marks".  If the space
@@ -164,7 +129,7 @@
   // saved mark.  Otherwise, the "obj_allocated_since_save_marks" method of
   // the space must distiguish between objects in the region allocated before
   // and after the call to save marks.
-  virtual MemRegion used_region_at_save_marks() const {
+  MemRegion used_region_at_save_marks() const {
     return MemRegion(bottom(), saved_mark_word());
   }
 
@@ -197,7 +162,9 @@
   // expensive operation. To prevent performance problems
   // on account of its inadvertent use in product jvm's,
   // we restrict its use to assertion checks only.
-  virtual bool is_in(const void* p) const = 0;
+  bool is_in(const void* p) const {
+    return used_region().contains(p);
+  }
 
   // Returns true iff the given reserved memory of the space contains the
   // given address.
@@ -221,11 +188,6 @@
   // applications of the closure are not included in the iteration.
   virtual void oop_iterate(ExtendedOopClosure* cl);
 
-  // Same as above, restricted to the intersection of a memory region and
-  // the space.  Fields in objects allocated by applications of the closure
-  // are not included in the iteration.
-  virtual void oop_iterate(MemRegion mr, ExtendedOopClosure* cl) = 0;
-
   // Iterate over all objects in the space, calling "cl.do_object" on
   // each.  Objects allocated by applications of the closure are not
   // included in the iteration.
@@ -234,24 +196,6 @@
   // objects whose internal references point to objects in the space.
   virtual void safe_object_iterate(ObjectClosure* blk) = 0;
 
-  // Iterate over all objects that intersect with mr, calling "cl->do_object"
-  // on each.  There is an exception to this: if this closure has already
-  // been invoked on an object, it may skip such objects in some cases.  This is
-  // Most likely to happen in an "upwards" (ascending address) iteration of
-  // MemRegions.
-  virtual void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
-
-  // Iterate over as many initialized objects in the space as possible,
-  // calling "cl.do_object_careful" on each. Return NULL if all objects
-  // in the space (at the start of the iteration) were iterated over.
-  // Return an address indicating the extent of the iteration in the
-  // event that the iteration had to return because of finding an
-  // uninitialized object in the space, or if the closure "cl"
-  // signalled early termination.
-  virtual HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
-  virtual HeapWord* object_iterate_careful_m(MemRegion mr,
-                                             ObjectClosureCareful* cl);
-
   // Create and return a new dirty card to oop closure. Can be
   // overriden to return the appropriate type of closure
   // depending on the type of space in which the closure will
@@ -292,10 +236,6 @@
   // Allocation (return NULL if full).  Enforces mutual exclusion internally.
   virtual HeapWord* par_allocate(size_t word_size) = 0;
 
-  // Returns true if this object has been allocated since a
-  // generation's "save_marks" call.
-  virtual bool obj_allocated_since_save_marks(const oop obj) const = 0;
-
   // Mark-sweep-compact support: all spaces can update pointers to objects
   // moving as a part of compaction.
   virtual void adjust_pointers();
@@ -390,9 +330,9 @@
   Generation* gen;
   CompactibleSpace* space;
   HeapWord* threshold;
-  CompactPoint(Generation* _gen, CompactibleSpace* _space,
-               HeapWord* _threshold) :
-    gen(_gen), space(_space), threshold(_threshold) {}
+
+  CompactPoint(Generation* _gen) :
+    gen(_gen), space(NULL), threshold(0) {}
 };
 
 
@@ -427,7 +367,7 @@
 
   // Perform operations on the space needed after a compaction
   // has been performed.
-  virtual void reset_after_compaction() {}
+  virtual void reset_after_compaction() = 0;
 
   // Returns the next space (in the current generation) to be compacted in
   // the global compaction order.  Also is used to select the next
@@ -492,7 +432,7 @@
   HeapWord* _end_of_live;
 
   // Minimum size of a free block.
-  virtual size_t minimum_free_block_size() const = 0;
+  virtual size_t minimum_free_block_size() const { return 0; }
 
   // This the function is invoked when an allocation of an object covering
   // "start" to "end occurs crosses the threshold; returns the next
@@ -512,272 +452,6 @@
                         size_t word_len);
 };
 
-#define SCAN_AND_FORWARD(cp,scan_limit,block_is_obj,block_size) {            \
-  /* Compute the new addresses for the live objects and store it in the mark \
-   * Used by universe::mark_sweep_phase2()                                   \
-   */                                                                        \
-  HeapWord* compact_top; /* This is where we are currently compacting to. */ \
-                                                                             \
-  /* We're sure to be here before any objects are compacted into this        \
-   * space, so this is a good time to initialize this:                       \
-   */                                                                        \
-  set_compaction_top(bottom());                                              \
-                                                                             \
-  if (cp->space == NULL) {                                                   \
-    assert(cp->gen != NULL, "need a generation");                            \
-    assert(cp->threshold == NULL, "just checking");                          \
-    assert(cp->gen->first_compaction_space() == this, "just checking");      \
-    cp->space = cp->gen->first_compaction_space();                           \
-    compact_top = cp->space->bottom();                                       \
-    cp->space->set_compaction_top(compact_top);                              \
-    cp->threshold = cp->space->initialize_threshold();                       \
-  } else {                                                                   \
-    compact_top = cp->space->compaction_top();                               \
-  }                                                                          \
-                                                                             \
-  /* We allow some amount of garbage towards the bottom of the space, so     \
-   * we don't start compacting before there is a significant gain to be made.\
-   * Occasionally, we want to ensure a full compaction, which is determined  \
-   * by the MarkSweepAlwaysCompactCount parameter.                           \
-   */                                                                        \
-  uint invocations = MarkSweep::total_invocations();                         \
-  bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0);       \
-                                                                             \
-  size_t allowed_deadspace = 0;                                              \
-  if (skip_dead) {                                                           \
-    const size_t ratio = allowed_dead_ratio();                               \
-    allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize;           \
-  }                                                                          \
-                                                                             \
-  HeapWord* q = bottom();                                                    \
-  HeapWord* t = scan_limit();                                                \
-                                                                             \
-  HeapWord*  end_of_live= q;    /* One byte beyond the last byte of the last \
-                                   live object. */                           \
-  HeapWord*  first_dead = end();/* The first dead object. */                 \
-  LiveRange* liveRange  = NULL; /* The current live range, recorded in the   \
-                                   first header of preceding free area. */   \
-  _first_dead = first_dead;                                                  \
-                                                                             \
-  const intx interval = PrefetchScanIntervalInBytes;                         \
-                                                                             \
-  while (q < t) {                                                            \
-    assert(!block_is_obj(q) ||                                               \
-           oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() ||   \
-           oop(q)->mark()->has_bias_pattern(),                               \
-           "these are the only valid states during a mark sweep");           \
-    if (block_is_obj(q) && oop(q)->is_gc_marked()) {                         \
-      /* prefetch beyond q */                                                \
-      Prefetch::write(q, interval);                                          \
-      size_t size = block_size(q);                                           \
-      compact_top = cp->space->forward(oop(q), size, cp, compact_top);       \
-      q += size;                                                             \
-      end_of_live = q;                                                       \
-    } else {                                                                 \
-      /* run over all the contiguous dead objects */                         \
-      HeapWord* end = q;                                                     \
-      do {                                                                   \
-        /* prefetch beyond end */                                            \
-        Prefetch::write(end, interval);                                      \
-        end += block_size(end);                                              \
-      } while (end < t && (!block_is_obj(end) || !oop(end)->is_gc_marked()));\
-                                                                             \
-      /* see if we might want to pretend this object is alive so that        \
-       * we don't have to compact quite as often.                            \
-       */                                                                    \
-      if (allowed_deadspace > 0 && q == compact_top) {                       \
-        size_t sz = pointer_delta(end, q);                                   \
-        if (insert_deadspace(allowed_deadspace, q, sz)) {                    \
-          compact_top = cp->space->forward(oop(q), sz, cp, compact_top);     \
-          q = end;                                                           \
-          end_of_live = end;                                                 \
-          continue;                                                          \
-        }                                                                    \
-      }                                                                      \
-                                                                             \
-      /* otherwise, it really is a free region. */                           \
-                                                                             \
-      /* for the previous LiveRange, record the end of the live objects. */  \
-      if (liveRange) {                                                       \
-        liveRange->set_end(q);                                               \
-      }                                                                      \
-                                                                             \
-      /* record the current LiveRange object.                                \
-       * liveRange->start() is overlaid on the mark word.                    \
-       */                                                                    \
-      liveRange = (LiveRange*)q;                                             \
-      liveRange->set_start(end);                                             \
-      liveRange->set_end(end);                                               \
-                                                                             \
-      /* see if this is the first dead region. */                            \
-      if (q < first_dead) {                                                  \
-        first_dead = q;                                                      \
-      }                                                                      \
-                                                                             \
-      /* move on to the next object */                                       \
-      q = end;                                                               \
-    }                                                                        \
-  }                                                                          \
-                                                                             \
-  assert(q == t, "just checking");                                           \
-  if (liveRange != NULL) {                                                   \
-    liveRange->set_end(q);                                                   \
-  }                                                                          \
-  _end_of_live = end_of_live;                                                \
-  if (end_of_live < first_dead) {                                            \
-    first_dead = end_of_live;                                                \
-  }                                                                          \
-  _first_dead = first_dead;                                                  \
-                                                                             \
-  /* save the compaction_top of the compaction space. */                     \
-  cp->space->set_compaction_top(compact_top);                                \
-}
-
-#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) {                             \
-  /* adjust all the interior pointers to point at the new locations of objects  \
-   * Used by MarkSweep::mark_sweep_phase3() */                                  \
-                                                                                \
-  HeapWord* q = bottom();                                                       \
-  HeapWord* t = _end_of_live;  /* Established by "prepare_for_compaction". */   \
-                                                                                \
-  assert(_first_dead <= _end_of_live, "Stands to reason, no?");                 \
-                                                                                \
-  if (q < t && _first_dead > q &&                                               \
-      !oop(q)->is_gc_marked()) {                                                \
-    /* we have a chunk of the space which hasn't moved and we've                \
-     * reinitialized the mark word during the previous pass, so we can't        \
-     * use is_gc_marked for the traversal. */                                   \
-    HeapWord* end = _first_dead;                                                \
-                                                                                \
-    while (q < end) {                                                           \
-      /* I originally tried to conjoin "block_start(q) == q" to the             \
-       * assertion below, but that doesn't work, because you can't              \
-       * accurately traverse previous objects to get to the current one         \
-       * after their pointers have been                                         \
-       * updated, until the actual compaction is done.  dld, 4/00 */            \
-      assert(block_is_obj(q),                                                   \
-             "should be at block boundaries, and should be looking at objs");   \
-                                                                                \
-      /* point all the oops to the new location */                              \
-      size_t size = oop(q)->adjust_pointers();                                  \
-      size = adjust_obj_size(size);                                             \
-                                                                                \
-      q += size;                                                                \
-    }                                                                           \
-                                                                                \
-    if (_first_dead == t) {                                                     \
-      q = t;                                                                    \
-    } else {                                                                    \
-      /* $$$ This is funky.  Using this to read the previously written          \
-       * LiveRange.  See also use below. */                                     \
-      q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer();                \
-    }                                                                           \
-  }                                                                             \
-                                                                                \
-  const intx interval = PrefetchScanIntervalInBytes;                            \
-                                                                                \
-  debug_only(HeapWord* prev_q = NULL);                                          \
-  while (q < t) {                                                               \
-    /* prefetch beyond q */                                                     \
-    Prefetch::write(q, interval);                                               \
-    if (oop(q)->is_gc_marked()) {                                               \
-      /* q is alive */                                                          \
-      /* point all the oops to the new location */                              \
-      size_t size = oop(q)->adjust_pointers();                                  \
-      size = adjust_obj_size(size);                                             \
-      debug_only(prev_q = q);                                                   \
-      q += size;                                                                \
-    } else {                                                                    \
-      /* q is not a live object, so its mark should point at the next           \
-       * live object */                                                         \
-      debug_only(prev_q = q);                                                   \
-      q = (HeapWord*) oop(q)->mark()->decode_pointer();                         \
-      assert(q > prev_q, "we should be moving forward through memory");         \
-    }                                                                           \
-  }                                                                             \
-                                                                                \
-  assert(q == t, "just checking");                                              \
-}
-
-#define SCAN_AND_COMPACT(obj_size) {                                            \
-  /* Copy all live objects to their new location                                \
-   * Used by MarkSweep::mark_sweep_phase4() */                                  \
-                                                                                \
-  HeapWord*       q = bottom();                                                 \
-  HeapWord* const t = _end_of_live;                                             \
-  debug_only(HeapWord* prev_q = NULL);                                          \
-                                                                                \
-  if (q < t && _first_dead > q &&                                               \
-      !oop(q)->is_gc_marked()) {                                                \
-    debug_only(                                                                 \
-    /* we have a chunk of the space which hasn't moved and we've reinitialized  \
-     * the mark word during the previous pass, so we can't use is_gc_marked for \
-     * the traversal. */                                                        \
-    HeapWord* const end = _first_dead;                                          \
-                                                                                \
-    while (q < end) {                                                           \
-      size_t size = obj_size(q);                                                \
-      assert(!oop(q)->is_gc_marked(),                                           \
-             "should be unmarked (special dense prefix handling)");             \
-      debug_only(prev_q = q);                                                   \
-      q += size;                                                                \
-    }                                                                           \
-    )  /* debug_only */                                                         \
-                                                                                \
-    if (_first_dead == t) {                                                     \
-      q = t;                                                                    \
-    } else {                                                                    \
-      /* $$$ Funky */                                                           \
-      q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer();               \
-    }                                                                           \
-  }                                                                             \
-                                                                                \
-  const intx scan_interval = PrefetchScanIntervalInBytes;                       \
-  const intx copy_interval = PrefetchCopyIntervalInBytes;                       \
-  while (q < t) {                                                               \
-    if (!oop(q)->is_gc_marked()) {                                              \
-      /* mark is pointer to next marked oop */                                  \
-      debug_only(prev_q = q);                                                   \
-      q = (HeapWord*) oop(q)->mark()->decode_pointer();                         \
-      assert(q > prev_q, "we should be moving forward through memory");         \
-    } else {                                                                    \
-      /* prefetch beyond q */                                                   \
-      Prefetch::read(q, scan_interval);                                         \
-                                                                                \
-      /* size and destination */                                                \
-      size_t size = obj_size(q);                                                \
-      HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee();                \
-                                                                                \
-      /* prefetch beyond compaction_top */                                      \
-      Prefetch::write(compaction_top, copy_interval);                           \
-                                                                                \
-      /* copy object and reinit its mark */                                     \
-      assert(q != compaction_top, "everything in this pass should be moving");  \
-      Copy::aligned_conjoint_words(q, compaction_top, size);                    \
-      oop(compaction_top)->init_mark();                                         \
-      assert(oop(compaction_top)->klass() != NULL, "should have a class");      \
-                                                                                \
-      debug_only(prev_q = q);                                                   \
-      q += size;                                                                \
-    }                                                                           \
-  }                                                                             \
-                                                                                \
-  /* Let's remember if we were empty before we did the compaction. */           \
-  bool was_empty = used_region().is_empty();                                    \
-  /* Reset space after compaction is complete */                                \
-  reset_after_compaction();                                                     \
-  /* We do this clear, below, since it has overloaded meanings for some */      \
-  /* space subtypes.  For example, OffsetTableContigSpace's that were   */      \
-  /* compacted into will have had their offset table thresholds updated */      \
-  /* continuously, but those that weren't need to have their thresholds */      \
-  /* re-initialized.  Also mangles unused area for debugging.           */      \
-  if (used_region().is_empty()) {                                               \
-    if (!was_empty) clear(SpaceDecorator::Mangle);                              \
-  } else {                                                                      \
-    if (ZapUnusedHeapArea) mangle_unused_area();                                \
-  }                                                                             \
-}
-
 class GenSpaceMangler;
 
 // A space in which the free area is contiguous.  It therefore supports
@@ -808,7 +482,7 @@
   HeapWord* top() const            { return _top;    }
   void set_top(HeapWord* value)    { _top = value; }
 
-  virtual void set_saved_mark()    { _saved_mark_word = top();    }
+  void set_saved_mark()            { _saved_mark_word = top();    }
   void reset_saved_mark()          { _saved_mark_word = bottom(); }
 
   WaterMark bottom_mark()     { return WaterMark(this, bottom()); }
@@ -843,36 +517,31 @@
   size_t used() const            { return byte_size(bottom(), top()); }
   size_t free() const            { return byte_size(top(),    end()); }
 
-  // Override from space.
-  bool is_in(const void* p) const;
-
   virtual bool is_free_block(const HeapWord* p) const;
 
   // In a contiguous space we have a more obvious bound on what parts
   // contain objects.
   MemRegion used_region() const { return MemRegion(bottom(), top()); }
 
-  MemRegion used_region_at_save_marks() const {
-    return MemRegion(bottom(), saved_mark_word());
-  }
-
   // Allocation (return NULL if full)
   virtual HeapWord* allocate(size_t word_size);
   virtual HeapWord* par_allocate(size_t word_size);
-
-  virtual bool obj_allocated_since_save_marks(const oop obj) const {
-    return (HeapWord*)obj >= saved_mark_word();
-  }
+  HeapWord* allocate_aligned(size_t word_size);
 
   // Iteration
   void oop_iterate(ExtendedOopClosure* cl);
-  void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
   void object_iterate(ObjectClosure* blk);
   // For contiguous spaces this method will iterate safely over objects
   // in the space (i.e., between bottom and top) when at a safepoint.
   void safe_object_iterate(ObjectClosure* blk);
-  void object_iterate_mem(MemRegion mr, UpwardsObjectClosure* cl);
-  // iterates on objects up to the safe limit
+
+  // Iterate over as many initialized objects in the space as possible,
+  // calling "cl.do_object_careful" on each. Return NULL if all objects
+  // in the space (at the start of the iteration) were iterated over.
+  // Return an address indicating the extent of the iteration in the
+  // event that the iteration had to return because of finding an
+  // uninitialized object in the space, or if the closure "cl"
+  // signaled early termination.
   HeapWord* object_iterate_careful(ObjectClosureCareful* cl);
   HeapWord* concurrent_iteration_safe_limit() {
     assert(_concurrent_iteration_safe_limit <= top(),
@@ -903,7 +572,6 @@
     // set new iteration safe limit
     set_concurrent_iteration_safe_limit(compaction_top());
   }
-  virtual size_t minimum_free_block_size() const { return 0; }
 
   // Override.
   DirtyCardToOopClosure* new_dcto_cl(ExtendedOopClosure* cl,
diff --git a/hotspot/src/share/vm/memory/space.inline.hpp b/hotspot/src/share/vm/memory/space.inline.hpp
index 1d600e2..007cebd 100644
--- a/hotspot/src/share/vm/memory/space.inline.hpp
+++ b/hotspot/src/share/vm/memory/space.inline.hpp
@@ -28,12 +28,279 @@
 #include "gc_interface/collectedHeap.hpp"
 #include "memory/space.hpp"
 #include "memory/universe.hpp"
+#include "runtime/prefetch.inline.hpp"
 #include "runtime/safepoint.hpp"
 
 inline HeapWord* Space::block_start(const void* p) {
   return block_start_const(p);
 }
 
+#define SCAN_AND_FORWARD(cp,scan_limit,block_is_obj,block_size) {            \
+  /* Compute the new addresses for the live objects and store it in the mark \
+   * Used by universe::mark_sweep_phase2()                                   \
+   */                                                                        \
+  HeapWord* compact_top; /* This is where we are currently compacting to. */ \
+                                                                             \
+  /* We're sure to be here before any objects are compacted into this        \
+   * space, so this is a good time to initialize this:                       \
+   */                                                                        \
+  set_compaction_top(bottom());                                              \
+                                                                             \
+  if (cp->space == NULL) {                                                   \
+    assert(cp->gen != NULL, "need a generation");                            \
+    assert(cp->threshold == NULL, "just checking");                          \
+    assert(cp->gen->first_compaction_space() == this, "just checking");      \
+    cp->space = cp->gen->first_compaction_space();                           \
+    compact_top = cp->space->bottom();                                       \
+    cp->space->set_compaction_top(compact_top);                              \
+    cp->threshold = cp->space->initialize_threshold();                       \
+  } else {                                                                   \
+    compact_top = cp->space->compaction_top();                               \
+  }                                                                          \
+                                                                             \
+  /* We allow some amount of garbage towards the bottom of the space, so     \
+   * we don't start compacting before there is a significant gain to be made.\
+   * Occasionally, we want to ensure a full compaction, which is determined  \
+   * by the MarkSweepAlwaysCompactCount parameter.                           \
+   */                                                                        \
+  uint invocations = MarkSweep::total_invocations();                         \
+  bool skip_dead = ((invocations % MarkSweepAlwaysCompactCount) != 0);       \
+                                                                             \
+  size_t allowed_deadspace = 0;                                              \
+  if (skip_dead) {                                                           \
+    const size_t ratio = allowed_dead_ratio();                               \
+    allowed_deadspace = (capacity() * ratio / 100) / HeapWordSize;           \
+  }                                                                          \
+                                                                             \
+  HeapWord* q = bottom();                                                    \
+  HeapWord* t = scan_limit();                                                \
+                                                                             \
+  HeapWord*  end_of_live= q;    /* One byte beyond the last byte of the last \
+                                   live object. */                           \
+  HeapWord*  first_dead = end();/* The first dead object. */                 \
+  LiveRange* liveRange  = NULL; /* The current live range, recorded in the   \
+                                   first header of preceding free area. */   \
+  _first_dead = first_dead;                                                  \
+                                                                             \
+  const intx interval = PrefetchScanIntervalInBytes;                         \
+                                                                             \
+  while (q < t) {                                                            \
+    assert(!block_is_obj(q) ||                                               \
+           oop(q)->mark()->is_marked() || oop(q)->mark()->is_unlocked() ||   \
+           oop(q)->mark()->has_bias_pattern(),                               \
+           "these are the only valid states during a mark sweep");           \
+    if (block_is_obj(q) && oop(q)->is_gc_marked()) {                         \
+      /* prefetch beyond q */                                                \
+      Prefetch::write(q, interval);                                          \
+      size_t size = block_size(q);                                           \
+      compact_top = cp->space->forward(oop(q), size, cp, compact_top);       \
+      q += size;                                                             \
+      end_of_live = q;                                                       \
+    } else {                                                                 \
+      /* run over all the contiguous dead objects */                         \
+      HeapWord* end = q;                                                     \
+      do {                                                                   \
+        /* prefetch beyond end */                                            \
+        Prefetch::write(end, interval);                                      \
+        end += block_size(end);                                              \
+      } while (end < t && (!block_is_obj(end) || !oop(end)->is_gc_marked()));\
+                                                                             \
+      /* see if we might want to pretend this object is alive so that        \
+       * we don't have to compact quite as often.                            \
+       */                                                                    \
+      if (allowed_deadspace > 0 && q == compact_top) {                       \
+        size_t sz = pointer_delta(end, q);                                   \
+        if (insert_deadspace(allowed_deadspace, q, sz)) {                    \
+          compact_top = cp->space->forward(oop(q), sz, cp, compact_top);     \
+          q = end;                                                           \
+          end_of_live = end;                                                 \
+          continue;                                                          \
+        }                                                                    \
+      }                                                                      \
+                                                                             \
+      /* otherwise, it really is a free region. */                           \
+                                                                             \
+      /* for the previous LiveRange, record the end of the live objects. */  \
+      if (liveRange) {                                                       \
+        liveRange->set_end(q);                                               \
+      }                                                                      \
+                                                                             \
+      /* record the current LiveRange object.                                \
+       * liveRange->start() is overlaid on the mark word.                    \
+       */                                                                    \
+      liveRange = (LiveRange*)q;                                             \
+      liveRange->set_start(end);                                             \
+      liveRange->set_end(end);                                               \
+                                                                             \
+      /* see if this is the first dead region. */                            \
+      if (q < first_dead) {                                                  \
+        first_dead = q;                                                      \
+      }                                                                      \
+                                                                             \
+      /* move on to the next object */                                       \
+      q = end;                                                               \
+    }                                                                        \
+  }                                                                          \
+                                                                             \
+  assert(q == t, "just checking");                                           \
+  if (liveRange != NULL) {                                                   \
+    liveRange->set_end(q);                                                   \
+  }                                                                          \
+  _end_of_live = end_of_live;                                                \
+  if (end_of_live < first_dead) {                                            \
+    first_dead = end_of_live;                                                \
+  }                                                                          \
+  _first_dead = first_dead;                                                  \
+                                                                             \
+  /* save the compaction_top of the compaction space. */                     \
+  cp->space->set_compaction_top(compact_top);                                \
+}
+
+#define SCAN_AND_ADJUST_POINTERS(adjust_obj_size) {                             \
+  /* adjust all the interior pointers to point at the new locations of objects  \
+   * Used by MarkSweep::mark_sweep_phase3() */                                  \
+                                                                                \
+  HeapWord* q = bottom();                                                       \
+  HeapWord* t = _end_of_live;  /* Established by "prepare_for_compaction". */   \
+                                                                                \
+  assert(_first_dead <= _end_of_live, "Stands to reason, no?");                 \
+                                                                                \
+  if (q < t && _first_dead > q &&                                               \
+      !oop(q)->is_gc_marked()) {                                                \
+    /* we have a chunk of the space which hasn't moved and we've                \
+     * reinitialized the mark word during the previous pass, so we can't        \
+     * use is_gc_marked for the traversal. */                                   \
+    HeapWord* end = _first_dead;                                                \
+                                                                                \
+    while (q < end) {                                                           \
+      /* I originally tried to conjoin "block_start(q) == q" to the             \
+       * assertion below, but that doesn't work, because you can't              \
+       * accurately traverse previous objects to get to the current one         \
+       * after their pointers have been                                         \
+       * updated, until the actual compaction is done.  dld, 4/00 */            \
+      assert(block_is_obj(q),                                                   \
+             "should be at block boundaries, and should be looking at objs");   \
+                                                                                \
+      /* point all the oops to the new location */                              \
+      size_t size = oop(q)->adjust_pointers();                                  \
+      size = adjust_obj_size(size);                                             \
+                                                                                \
+      q += size;                                                                \
+    }                                                                           \
+                                                                                \
+    if (_first_dead == t) {                                                     \
+      q = t;                                                                    \
+    } else {                                                                    \
+      /* $$$ This is funky.  Using this to read the previously written          \
+       * LiveRange.  See also use below. */                                     \
+      q = (HeapWord*)oop(_first_dead)->mark()->decode_pointer();                \
+    }                                                                           \
+  }                                                                             \
+                                                                                \
+  const intx interval = PrefetchScanIntervalInBytes;                            \
+                                                                                \
+  debug_only(HeapWord* prev_q = NULL);                                          \
+  while (q < t) {                                                               \
+    /* prefetch beyond q */                                                     \
+    Prefetch::write(q, interval);                                               \
+    if (oop(q)->is_gc_marked()) {                                               \
+      /* q is alive */                                                          \
+      /* point all the oops to the new location */                              \
+      size_t size = oop(q)->adjust_pointers();                                  \
+      size = adjust_obj_size(size);                                             \
+      debug_only(prev_q = q);                                                   \
+      q += size;                                                                \
+    } else {                                                                    \
+      /* q is not a live object, so its mark should point at the next           \
+       * live object */                                                         \
+      debug_only(prev_q = q);                                                   \
+      q = (HeapWord*) oop(q)->mark()->decode_pointer();                         \
+      assert(q > prev_q, "we should be moving forward through memory");         \
+    }                                                                           \
+  }                                                                             \
+                                                                                \
+  assert(q == t, "just checking");                                              \
+}
+
+#define SCAN_AND_COMPACT(obj_size) {                                            \
+  /* Copy all live objects to their new location                                \
+   * Used by MarkSweep::mark_sweep_phase4() */                                  \
+                                                                                \
+  HeapWord*       q = bottom();                                                 \
+  HeapWord* const t = _end_of_live;                                             \
+  debug_only(HeapWord* prev_q = NULL);                                          \
+                                                                                \
+  if (q < t && _first_dead > q &&                                               \
+      !oop(q)->is_gc_marked()) {                                                \
+    debug_only(                                                                 \
+    /* we have a chunk of the space which hasn't moved and we've reinitialized  \
+     * the mark word during the previous pass, so we can't use is_gc_marked for \
+     * the traversal. */                                                        \
+    HeapWord* const end = _first_dead;                                          \
+                                                                                \
+    while (q < end) {                                                           \
+      size_t size = obj_size(q);                                                \
+      assert(!oop(q)->is_gc_marked(),                                           \
+             "should be unmarked (special dense prefix handling)");             \
+      debug_only(prev_q = q);                                                   \
+      q += size;                                                                \
+    }                                                                           \
+    )  /* debug_only */                                                         \
+                                                                                \
+    if (_first_dead == t) {                                                     \
+      q = t;                                                                    \
+    } else {                                                                    \
+      /* $$$ Funky */                                                           \
+      q = (HeapWord*) oop(_first_dead)->mark()->decode_pointer();               \
+    }                                                                           \
+  }                                                                             \
+                                                                                \
+  const intx scan_interval = PrefetchScanIntervalInBytes;                       \
+  const intx copy_interval = PrefetchCopyIntervalInBytes;                       \
+  while (q < t) {                                                               \
+    if (!oop(q)->is_gc_marked()) {                                              \
+      /* mark is pointer to next marked oop */                                  \
+      debug_only(prev_q = q);                                                   \
+      q = (HeapWord*) oop(q)->mark()->decode_pointer();                         \
+      assert(q > prev_q, "we should be moving forward through memory");         \
+    } else {                                                                    \
+      /* prefetch beyond q */                                                   \
+      Prefetch::read(q, scan_interval);                                         \
+                                                                                \
+      /* size and destination */                                                \
+      size_t size = obj_size(q);                                                \
+      HeapWord* compaction_top = (HeapWord*)oop(q)->forwardee();                \
+                                                                                \
+      /* prefetch beyond compaction_top */                                      \
+      Prefetch::write(compaction_top, copy_interval);                           \
+                                                                                \
+      /* copy object and reinit its mark */                                     \
+      assert(q != compaction_top, "everything in this pass should be moving");  \
+      Copy::aligned_conjoint_words(q, compaction_top, size);                    \
+      oop(compaction_top)->init_mark();                                         \
+      assert(oop(compaction_top)->klass() != NULL, "should have a class");      \
+                                                                                \
+      debug_only(prev_q = q);                                                   \
+      q += size;                                                                \
+    }                                                                           \
+  }                                                                             \
+                                                                                \
+  /* Let's remember if we were empty before we did the compaction. */           \
+  bool was_empty = used_region().is_empty();                                    \
+  /* Reset space after compaction is complete */                                \
+  reset_after_compaction();                                                     \
+  /* We do this clear, below, since it has overloaded meanings for some */      \
+  /* space subtypes.  For example, OffsetTableContigSpace's that were   */      \
+  /* compacted into will have had their offset table thresholds updated */      \
+  /* continuously, but those that weren't need to have their thresholds */      \
+  /* re-initialized.  Also mangles unused area for debugging.           */      \
+  if (used_region().is_empty()) {                                               \
+    if (!was_empty) clear(SpaceDecorator::Mangle);                              \
+  } else {                                                                      \
+    if (ZapUnusedHeapArea) mangle_unused_area();                                \
+  }                                                                             \
+}
+
 inline HeapWord* OffsetTableContigSpace::allocate(size_t size) {
   HeapWord* res = ContiguousSpace::allocate(size);
   if (res != NULL) {
diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp
index 482c3ff..761caec 100644
--- a/hotspot/src/share/vm/oops/cpCache.cpp
+++ b/hotspot/src/share/vm/oops/cpCache.cpp
@@ -33,6 +33,7 @@
 #include "prims/jvmtiRedefineClassesTrace.hpp"
 #include "prims/methodHandles.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
 # include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp
index dda5e89..a597b28 100644
--- a/hotspot/src/share/vm/oops/cpCache.hpp
+++ b/hotspot/src/share/vm/oops/cpCache.hpp
@@ -27,6 +27,7 @@
 
 #include "interpreter/bytecodes.hpp"
 #include "memory/allocation.hpp"
+#include "runtime/orderAccess.hpp"
 #include "utilities/array.hpp"
 
 class PSPromotionManager;
diff --git a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
index a92167a..131ecbf 100644
--- a/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceClassLoaderKlass.cpp
@@ -28,6 +28,7 @@
 #include "gc_implementation/shared/markSweep.inline.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
 #include "memory/genOopClosures.inline.hpp"
+#include "memory/iterator.inline.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceClassLoaderKlass.hpp"
@@ -44,12 +45,6 @@
 #include "oops/oop.pcgc.inline.hpp"
 #endif // INCLUDE_ALL_GCS
 
-#define if_do_metadata_checked(closure, nv_suffix)                    \
-  /* Make sure the non-virtual and the virtual versions match. */     \
-  assert(closure->do_metadata##nv_suffix() == closure->do_metadata(), \
-      "Inconsistency in do_metadata");                                \
-  if (closure->do_metadata##nv_suffix())
-
 // Macro to define InstanceClassLoaderKlass::oop_oop_iterate for virtual/nonvirtual for
 // all closures.  Macros calling macros above for each oop size.
 // Since ClassLoader objects have only a pointer to the loader_data, they are not
diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp
index db0e0a5..18bc4c6 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp
@@ -35,6 +35,7 @@
 #include "jvmtifiles/jvmti.h"
 #include "memory/genOopClosures.inline.hpp"
 #include "memory/heapInspection.hpp"
+#include "memory/iterator.inline.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/fieldStreams.hpp"
@@ -54,6 +55,7 @@
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/thread.inline.hpp"
 #include "services/classLoadingService.hpp"
 #include "services/threadService.hpp"
@@ -287,6 +289,7 @@
   set_static_oop_field_count(0);
   set_nonstatic_field_size(0);
   set_is_marked_dependent(false);
+  set_has_unloaded_dependent(false);
   set_init_state(InstanceKlass::allocated);
   set_init_thread(NULL);
   set_reference_type(rt);
@@ -1817,6 +1820,9 @@
   return id;
 }
 
+int nmethodBucket::decrement() {
+  return Atomic::add(-1, (volatile int *)&_count);
+}
 
 //
 // Walk the list of dependent nmethods searching for nmethods which
@@ -1831,7 +1837,7 @@
     nmethod* nm = b->get_nmethod();
     // since dependencies aren't removed until an nmethod becomes a zombie,
     // the dependency list may contain nmethods which aren't alive.
-    if (nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) {
+    if (b->count() > 0 && nm->is_alive() && !nm->is_marked_for_deoptimization() && nm->check_dependency_on(changes)) {
       if (TraceDependencies) {
         ResourceMark rm;
         tty->print_cr("Marked for deoptimization");
@@ -1848,6 +1854,43 @@
   return found;
 }
 
+void InstanceKlass::clean_dependent_nmethods() {
+  assert_locked_or_safepoint(CodeCache_lock);
+
+  if (has_unloaded_dependent()) {
+    nmethodBucket* b = _dependencies;
+    nmethodBucket* last = NULL;
+    while (b != NULL) {
+      assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
+
+      nmethodBucket* next = b->next();
+
+      if (b->count() == 0) {
+        if (last == NULL) {
+          _dependencies = next;
+        } else {
+          last->set_next(next);
+        }
+        delete b;
+        // last stays the same.
+      } else {
+        last = b;
+      }
+
+      b = next;
+    }
+    set_has_unloaded_dependent(false);
+  }
+#ifdef ASSERT
+  else {
+    // Verification
+    for (nmethodBucket* b = _dependencies; b != NULL; b = b->next()) {
+      assert(b->count() >= 0, err_msg("bucket count: %d", b->count()));
+      assert(b->count() != 0, "empty buckets need to be cleaned");
+    }
+  }
+#endif
+}
 
 //
 // Add an nmethodBucket to the list of dependencies for this nmethod.
@@ -1882,13 +1925,10 @@
   nmethodBucket* last = NULL;
   while (b != NULL) {
     if (nm == b->get_nmethod()) {
-      if (b->decrement() == 0) {
-        if (last == NULL) {
-          _dependencies = b->next();
-        } else {
-          last->set_next(b->next());
-        }
-        delete b;
+      int val = b->decrement();
+      guarantee(val >= 0, err_msg("Underflow: %d", val));
+      if (val == 0) {
+        set_has_unloaded_dependent(true);
       }
       return;
     }
@@ -1927,6 +1967,10 @@
   nmethodBucket* b = _dependencies;
   while (b != NULL) {
     if (nm == b->get_nmethod()) {
+#ifdef ASSERT
+      int count = b->count();
+      assert(count >= 0, err_msg("count shouldn't be negative: %d", count));
+#endif
       return true;
     }
     b = b->next();
@@ -2131,12 +2175,6 @@
 // closure's do_metadata() method dictates whether the given closure should be
 // applied to the klass ptr in the object header.
 
-#define if_do_metadata_checked(closure, nv_suffix)                    \
-  /* Make sure the non-virtual and the virtual versions match. */     \
-  assert(closure->do_metadata##nv_suffix() == closure->do_metadata(), \
-      "Inconsistency in do_metadata");                                \
-  if (closure->do_metadata##nv_suffix())
-
 #define InstanceKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)        \
                                                                              \
 int InstanceKlass::oop_oop_iterate##nv_suffix(oop obj, OopClosureType* closure) { \
@@ -2160,10 +2198,9 @@
 int InstanceKlass::oop_oop_iterate_backwards##nv_suffix(oop obj,                \
                                               OopClosureType* closure) {        \
   SpecializationStats::record_iterate_call##nv_suffix(SpecializationStats::ik); \
-  /* header */                                                                  \
-  if_do_metadata_checked(closure, nv_suffix) {                                  \
-    closure->do_klass##nv_suffix(obj->klass());                                 \
-  }                                                                             \
+                                                                                \
+  assert_should_ignore_metadata(closure, nv_suffix);                            \
+                                                                                \
   /* instance variables */                                                      \
   InstanceKlass_OOP_MAP_REVERSE_ITERATE(                                        \
     obj,                                                                        \
@@ -2232,7 +2269,7 @@
 #endif // INCLUDE_ALL_GCS
 
 void InstanceKlass::clean_implementors_list(BoolObjectClosure* is_alive) {
-  assert(is_loader_alive(is_alive), "this klass should be live");
+  assert(class_loader_data()->is_alive(is_alive), "this klass should be live");
   if (is_interface()) {
     if (ClassUnloading) {
       Klass* impl = implementor();
@@ -3041,8 +3078,7 @@
         offset          <= (juint) value->length() &&
         offset + length <= (juint) value->length()) {
       st->print(BULLET"string: ");
-      Handle h_obj(obj);
-      java_lang_String::print(h_obj, st);
+      java_lang_String::print(obj, st);
       st->cr();
       if (!WizardMode)  return;  // that is enough
     }
diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp
index 31e5acc..894bff2 100644
--- a/hotspot/src/share/vm/oops/instanceKlass.hpp
+++ b/hotspot/src/share/vm/oops/instanceKlass.hpp
@@ -226,6 +226,7 @@
   // _is_marked_dependent can be set concurrently, thus cannot be part of the
   // _misc_flags.
   bool            _is_marked_dependent;  // used for marking during flushing and deoptimization
+  bool            _has_unloaded_dependent;
 
   enum {
     _misc_rewritten            = 1 << 0, // methods rewritten.
@@ -473,6 +474,9 @@
   bool is_marked_dependent() const         { return _is_marked_dependent; }
   void set_is_marked_dependent(bool value) { _is_marked_dependent = value; }
 
+  bool has_unloaded_dependent() const         { return _has_unloaded_dependent; }
+  void set_has_unloaded_dependent(bool value) { _has_unloaded_dependent = value; }
+
   // initialization (virtuals from Klass)
   bool should_be_initialized() const;  // means that initialize should be called
   void initialize(TRAPS);
@@ -946,6 +950,7 @@
 
   void clean_implementors_list(BoolObjectClosure* is_alive);
   void clean_method_data(BoolObjectClosure* is_alive);
+  void clean_dependent_nmethods();
 
   // Explicit metaspace deallocation of fields
   // For RedefineClasses and class file parsing errors, we need to deallocate
@@ -1234,7 +1239,7 @@
   }
   int count()                             { return _count; }
   int increment()                         { _count += 1; return _count; }
-  int decrement()                         { _count -= 1; assert(_count >= 0, "don't underflow"); return _count; }
+  int decrement();
   nmethodBucket* next()                   { return _next; }
   void set_next(nmethodBucket* b)         { _next = b; }
   nmethod* get_nmethod()                  { return _nmethod; }
diff --git a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
index fd05124..2fd8e48 100644
--- a/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
+++ b/hotspot/src/share/vm/oops/instanceMirrorKlass.cpp
@@ -28,6 +28,7 @@
 #include "gc_implementation/shared/markSweep.inline.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
 #include "memory/genOopClosures.inline.hpp"
+#include "memory/iterator.inline.hpp"
 #include "memory/oopFactory.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/instanceMirrorKlass.hpp"
@@ -241,12 +242,6 @@
   return oop_size(obj);                                                               \
 
 
-#define if_do_metadata_checked(closure, nv_suffix)                    \
-  /* Make sure the non-virtual and the virtual versions match. */     \
-  assert(closure->do_metadata##nv_suffix() == closure->do_metadata(), \
-      "Inconsistency in do_metadata");                                \
-  if (closure->do_metadata##nv_suffix())
-
 // Macro to define InstanceMirrorKlass::oop_oop_iterate for virtual/nonvirtual for
 // all closures.  Macros calling macros above for each oop size.
 
diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp
index 27dc20c..e68f310 100644
--- a/hotspot/src/share/vm/oops/klass.cpp
+++ b/hotspot/src/share/vm/oops/klass.cpp
@@ -36,11 +36,13 @@
 #include "oops/instanceKlass.hpp"
 #include "oops/klass.inline.hpp"
 #include "oops/oop.inline2.hpp"
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/stack.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
+#include "gc_implementation/g1/g1SATBCardTableModRefBS.hpp"
 #include "gc_implementation/parallelScavenge/psParallelCompact.hpp"
 #include "gc_implementation/parallelScavenge/psPromotionManager.hpp"
 #include "gc_implementation/parallelScavenge/psScavenge.hpp"
@@ -158,7 +160,12 @@
   _primary_supers[0] = k;
   set_super_check_offset(in_bytes(primary_supers_offset()));
 
-  set_java_mirror(NULL);
+  // The constructor is used from init_self_patching_vtbl_list,
+  // which doesn't zero out the memory before calling the constructor.
+  // Need to set the field explicitly to not hit an assert that the field
+  // should be NULL before setting it.
+  _java_mirror = NULL;
+
   set_modifier_flags(0);
   set_layout_helper(Klass::_lh_neutral_value);
   set_name(NULL);
@@ -390,7 +397,7 @@
   return mirror_alive;
 }
 
-void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive) {
+void Klass::clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses) {
   if (!ClassUnloading) {
     return;
   }
@@ -435,7 +442,7 @@
     }
 
     // Clean the implementors list and method data.
-    if (current->oop_is_instance()) {
+    if (clean_alive_klasses && current->oop_is_instance()) {
       InstanceKlass* ik = InstanceKlass::cast(current);
       ik->clean_implementors_list(is_alive);
       ik->clean_method_data(is_alive);
@@ -447,12 +454,18 @@
   record_modified_oops();
 }
 
-void Klass::klass_update_barrier_set_pre(void* p, oop v) {
-  // This barrier used by G1, where it's used remember the old oop values,
-  // so that we don't forget any objects that were live at the snapshot at
-  // the beginning. This function is only used when we write oops into
-  // Klasses. Since the Klasses are used as roots in G1, we don't have to
-  // do anything here.
+// This barrier is used by G1 to remember the old oop values, so
+// that we don't forget any objects that were live at the snapshot at
+// the beginning. This function is only used when we write oops into Klasses.
+void Klass::klass_update_barrier_set_pre(oop* p, oop v) {
+#if INCLUDE_ALL_GCS
+  if (UseG1GC) {
+    oop obj = *p;
+    if (obj != NULL) {
+      G1SATBCardTableModRefBS::enqueue(obj);
+    }
+  }
+#endif
 }
 
 void Klass::klass_oop_store(oop* p, oop v) {
@@ -463,7 +476,7 @@
   if (always_do_update_barrier) {
     klass_oop_store((volatile oop*)p, v);
   } else {
-    klass_update_barrier_set_pre((void*)p, v);
+    klass_update_barrier_set_pre(p, v);
     *p = v;
     klass_update_barrier_set(v);
   }
@@ -473,7 +486,7 @@
   assert(!Universe::heap()->is_in_reserved((void*)p), "Should store pointer into metadata");
   assert(v == NULL || Universe::heap()->is_in_reserved((void*)v), "Should store pointer to an object");
 
-  klass_update_barrier_set_pre((void*)p, v);
+  klass_update_barrier_set_pre((oop*)p, v); // Cast away volatile.
   OrderAccess::release_store_ptr(p, v);
   klass_update_barrier_set(v);
 }
@@ -698,3 +711,21 @@
 }
 
 #endif
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+class TestKlass {
+ public:
+  static void test_oop_is_instanceClassLoader() {
+    assert(SystemDictionary::ClassLoader_klass()->oop_is_instanceClassLoader(), "assert");
+    assert(!SystemDictionary::String_klass()->oop_is_instanceClassLoader(), "assert");
+  }
+};
+
+void TestKlass_test() {
+  TestKlass::test_oop_is_instanceClassLoader();
+}
+
+#endif
diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp
index 0d9dbce..96cc3e5 100644
--- a/hotspot/src/share/vm/oops/klass.hpp
+++ b/hotspot/src/share/vm/oops/klass.hpp
@@ -32,7 +32,6 @@
 #include "oops/klassPS.hpp"
 #include "oops/metadata.hpp"
 #include "oops/oop.hpp"
-#include "runtime/orderAccess.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/accessFlags.hpp"
 #include "utilities/macros.hpp"
@@ -500,6 +499,7 @@
   virtual bool oop_is_objArray_slow()       const { return false; }
   virtual bool oop_is_typeArray_slow()      const { return false; }
  public:
+  virtual bool oop_is_instanceClassLoader() const { return false; }
   virtual bool oop_is_instanceMirror()      const { return false; }
   virtual bool oop_is_instanceRef()         const { return false; }
 
@@ -583,36 +583,9 @@
   // The is_alive closure passed in depends on the Garbage Collector used.
   bool is_loader_alive(BoolObjectClosure* is_alive);
 
-  static void clean_weak_klass_links(BoolObjectClosure* is_alive);
-
-  // Prefetch within oop iterators.  This is a macro because we
-  // can't guarantee that the compiler will inline it.  In 64-bit
-  // it generally doesn't.  Signature is
-  //
-  // static void prefetch_beyond(oop* const start,
-  //                             oop* const end,
-  //                             const intx foffset,
-  //                             const Prefetch::style pstyle);
-#define prefetch_beyond(start, end, foffset, pstyle) {   \
-    const intx foffset_ = (foffset);                     \
-    const Prefetch::style pstyle_ = (pstyle);            \
-    assert(foffset_ > 0, "prefetch beyond, not behind"); \
-    if (pstyle_ != Prefetch::do_none) {                  \
-      oop* ref = (start);                                \
-      if (ref < (end)) {                                 \
-        switch (pstyle_) {                               \
-        case Prefetch::do_read:                          \
-          Prefetch::read(*ref, foffset_);                \
-          break;                                         \
-        case Prefetch::do_write:                         \
-          Prefetch::write(*ref, foffset_);               \
-          break;                                         \
-        default:                                         \
-          ShouldNotReachHere();                          \
-          break;                                         \
-        }                                                \
-      }                                                  \
-    }                                                    \
+  static void clean_weak_klass_links(BoolObjectClosure* is_alive, bool clean_alive_klasses = true);
+  static void clean_subklass_tree(BoolObjectClosure* is_alive) {
+    clean_weak_klass_links(is_alive, false /* clean_alive_klasses */);
   }
 
   // iterators
@@ -720,7 +693,7 @@
  private:
   // barriers used by klass_oop_store
   void klass_update_barrier_set(oop v);
-  void klass_update_barrier_set_pre(void* p, oop v);
+  void klass_update_barrier_set_pre(oop* p, oop v);
 };
 
 #endif // SHARE_VM_OOPS_KLASS_HPP
diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp
index 15aeae7..0ccf432 100644
--- a/hotspot/src/share/vm/oops/method.cpp
+++ b/hotspot/src/share/vm/oops/method.cpp
@@ -49,6 +49,7 @@
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/frame.inline.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/relocator.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp
index 1138b35..1d7d73a 100644
--- a/hotspot/src/share/vm/oops/methodData.cpp
+++ b/hotspot/src/share/vm/oops/methodData.cpp
@@ -34,6 +34,7 @@
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 
 PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
 
diff --git a/hotspot/src/share/vm/oops/objArrayKlass.cpp b/hotspot/src/share/vm/oops/objArrayKlass.cpp
index 514fdfb..0d17ce6 100644
--- a/hotspot/src/share/vm/oops/objArrayKlass.cpp
+++ b/hotspot/src/share/vm/oops/objArrayKlass.cpp
@@ -29,6 +29,7 @@
 #include "gc_implementation/shared/markSweep.inline.hpp"
 #include "gc_interface/collectedHeap.inline.hpp"
 #include "memory/genOopClosures.inline.hpp"
+#include "memory/iterator.inline.hpp"
 #include "memory/metadataFactory.hpp"
 #include "memory/resourceArea.hpp"
 #include "memory/universe.inline.hpp"
@@ -42,6 +43,7 @@
 #include "oops/symbol.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/copy.hpp"
 #include "utilities/macros.hpp"
 #if INCLUDE_ALL_GCS
@@ -475,12 +477,6 @@
 }
 #endif // INCLUDE_ALL_GCS
 
-#define if_do_metadata_checked(closure, nv_suffix)                    \
-  /* Make sure the non-virtual and the virtual versions match. */     \
-  assert(closure->do_metadata##nv_suffix() == closure->do_metadata(), \
-      "Inconsistency in do_metadata");                                \
-  if (closure->do_metadata##nv_suffix())
-
 #define ObjArrayKlass_OOP_OOP_ITERATE_DEFN(OopClosureType, nv_suffix)           \
                                                                                 \
 int ObjArrayKlass::oop_oop_iterate##nv_suffix(oop obj,                          \
diff --git a/hotspot/src/share/vm/oops/oop.hpp b/hotspot/src/share/vm/oops/oop.hpp
index 2013c3e..2ea801d 100644
--- a/hotspot/src/share/vm/oops/oop.hpp
+++ b/hotspot/src/share/vm/oops/oop.hpp
@@ -109,12 +109,13 @@
   int size_given_klass(Klass* klass);
 
   // type test operations (inlined in oop.inline.h)
-  bool is_instance()           const;
-  bool is_instanceMirror()     const;
-  bool is_instanceRef()        const;
-  bool is_array()              const;
-  bool is_objArray()           const;
-  bool is_typeArray()          const;
+  bool is_instance()            const;
+  bool is_instanceMirror()      const;
+  bool is_instanceClassLoader() const;
+  bool is_instanceRef()         const;
+  bool is_array()               const;
+  bool is_objArray()            const;
+  bool is_typeArray()           const;
 
  private:
   // field addresses in oop
diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp
index 0a08143..0dc0db8 100644
--- a/hotspot/src/share/vm/oops/oop.inline.hpp
+++ b/hotspot/src/share/vm/oops/oop.inline.hpp
@@ -38,7 +38,8 @@
 #include "oops/klass.inline.hpp"
 #include "oops/markOop.inline.hpp"
 #include "oops/oop.hpp"
-#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 #include "utilities/macros.hpp"
 #ifdef TARGET_ARCH_x86
@@ -147,12 +148,13 @@
 
 inline bool oopDesc::is_a(Klass* k)        const { return klass()->is_subtype_of(k); }
 
-inline bool oopDesc::is_instance()           const { return klass()->oop_is_instance(); }
-inline bool oopDesc::is_instanceMirror()     const { return klass()->oop_is_instanceMirror(); }
-inline bool oopDesc::is_instanceRef()        const { return klass()->oop_is_instanceRef(); }
-inline bool oopDesc::is_array()              const { return klass()->oop_is_array(); }
-inline bool oopDesc::is_objArray()           const { return klass()->oop_is_objArray(); }
-inline bool oopDesc::is_typeArray()          const { return klass()->oop_is_typeArray(); }
+inline bool oopDesc::is_instance()            const { return klass()->oop_is_instance(); }
+inline bool oopDesc::is_instanceClassLoader() const { return klass()->oop_is_instanceClassLoader(); }
+inline bool oopDesc::is_instanceMirror()      const { return klass()->oop_is_instanceMirror(); }
+inline bool oopDesc::is_instanceRef()         const { return klass()->oop_is_instanceRef(); }
+inline bool oopDesc::is_array()               const { return klass()->oop_is_array(); }
+inline bool oopDesc::is_objArray()            const { return klass()->oop_is_objArray(); }
+inline bool oopDesc::is_typeArray()           const { return klass()->oop_is_typeArray(); }
 
 inline void*     oopDesc::field_base(int offset)        const { return (void*)&((char*)this)[offset]; }
 
diff --git a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp
index 596bbc6..8a46039 100644
--- a/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp
+++ b/hotspot/src/share/vm/oops/oop.pcgc.inline.hpp
@@ -54,8 +54,6 @@
   klass()->oop_follow_contents(cm, this);
 }
 
-// Used by parallel old GC.
-
 inline oop oopDesc::forward_to_atomic(oop p) {
   assert(ParNewGeneration::is_legal_forward_ptr(p),
          "illegal forwarding pointer value.");
diff --git a/hotspot/src/share/vm/oops/typeArrayKlass.cpp b/hotspot/src/share/vm/oops/typeArrayKlass.cpp
index 8d9c672..7cc9475 100644
--- a/hotspot/src/share/vm/oops/typeArrayKlass.cpp
+++ b/hotspot/src/share/vm/oops/typeArrayKlass.cpp
@@ -39,6 +39,7 @@
 #include "oops/typeArrayKlass.hpp"
 #include "oops/typeArrayOop.hpp"
 #include "runtime/handles.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/macros.hpp"
 
 bool TypeArrayKlass::compute_is_subtype_of(Klass* k) {
diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp
index 29ad6cd..20f30dc 100644
--- a/hotspot/src/share/vm/oops/typeArrayOop.hpp
+++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp
@@ -27,39 +27,7 @@
 
 #include "oops/arrayOop.hpp"
 #include "oops/typeArrayKlass.hpp"
-#ifdef TARGET_OS_ARCH_linux_x86
-# include "orderAccess_linux_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_sparc
-# include "orderAccess_linux_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_zero
-# include "orderAccess_linux_zero.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_x86
-# include "orderAccess_solaris_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_sparc
-# include "orderAccess_solaris_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_windows_x86
-# include "orderAccess_windows_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_arm
-# include "orderAccess_linux_arm.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_ppc
-# include "orderAccess_linux_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_aix_ppc
-# include "orderAccess_aix_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_x86
-# include "orderAccess_bsd_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_zero
-# include "orderAccess_bsd_zero.inline.hpp"
-#endif
+#include "runtime/orderAccess.inline.hpp"
 
 // A typeArrayOop is an array containing basic types (non oop elements).
 // It is used for arrays of {characters, singles, doubles, bytes, shorts, integers, longs}
diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp
index 0e039dc..06155aa 100644
--- a/hotspot/src/share/vm/opto/c2_globals.hpp
+++ b/hotspot/src/share/vm/opto/c2_globals.hpp
@@ -653,9 +653,6 @@
   product(bool, UseMathExactIntrinsics, true,                               \
           "Enables intrinsification of various java.lang.Math functions")   \
                                                                             \
-  experimental(bool, ReplaceInParentMaps, false,                            \
-          "Propagate type improvements in callers of inlinee if possible")  \
-                                                                            \
   product(bool, UseTypeSpeculation, true,                                   \
           "Speculatively propagate types from profiles")                    \
                                                                             \
diff --git a/hotspot/src/share/vm/opto/callGenerator.cpp b/hotspot/src/share/vm/opto/callGenerator.cpp
index 42ed3bc..4e7d836 100644
--- a/hotspot/src/share/vm/opto/callGenerator.cpp
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp
@@ -63,12 +63,12 @@
   }
 
   virtual bool      is_parse() const           { return true; }
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
   int is_osr() { return _is_osr; }
 
 };
 
-JVMState* ParseGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* ParseGenerator::generate(JVMState* jvms) {
   Compile* C = Compile::current();
 
   if (is_osr()) {
@@ -80,7 +80,7 @@
     return NULL;  // bailing out of the compile; do not try to parse
   }
 
-  Parse parser(jvms, method(), _expected_uses, parent_parser);
+  Parse parser(jvms, method(), _expected_uses);
   // Grab signature for matching/allocation
 #ifdef ASSERT
   if (parser.tf() != (parser.depth() == 1 ? C->tf() : tf())) {
@@ -119,12 +119,12 @@
       _separate_io_proj(separate_io_proj)
   {
   }
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
 
   CallStaticJavaNode* call_node() const { return _call_node; }
 };
 
-JVMState* DirectCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* DirectCallGenerator::generate(JVMState* jvms) {
   GraphKit kit(jvms);
   bool is_static = method()->is_static();
   address target = is_static ? SharedRuntime::get_resolve_static_call_stub()
@@ -171,10 +171,10 @@
            vtable_index >= 0, "either invalid or usable");
   }
   virtual bool      is_virtual() const          { return true; }
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
 };
 
-JVMState* VirtualCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
   GraphKit kit(jvms);
   Node* receiver = kit.argument(0);
 
@@ -276,7 +276,7 @@
   // Convert the CallStaticJava into an inline
   virtual void do_late_inline();
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
+  virtual JVMState* generate(JVMState* jvms) {
     Compile *C = Compile::current();
     C->print_inlining_skip(this);
 
@@ -290,7 +290,7 @@
     // that the late inlining logic can distinguish between fall
     // through and exceptional uses of the memory and io projections
     // as is done for allocations and macro expansion.
-    return DirectCallGenerator::generate(jvms, parent_parser);
+    return DirectCallGenerator::generate(jvms);
   }
 
   virtual void print_inlining_late(const char* msg) {
@@ -389,7 +389,7 @@
   }
 
   // Now perform the inling using the synthesized JVMState
-  JVMState* new_jvms = _inline_cg->generate(jvms, NULL);
+  JVMState* new_jvms = _inline_cg->generate(jvms);
   if (new_jvms == NULL)  return;  // no change
   if (C->failing())      return;
 
@@ -407,7 +407,7 @@
   C->env()->notice_inlined_method(_inline_cg->method());
   C->set_inlining_progress(true);
 
-  kit.replace_call(call, result);
+  kit.replace_call(call, result, true);
 }
 
 
@@ -429,8 +429,8 @@
 
   virtual bool is_mh_late_inline() const { return true; }
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
-    JVMState* new_jvms = LateInlineCallGenerator::generate(jvms, parent_parser);
+  virtual JVMState* generate(JVMState* jvms) {
+    JVMState* new_jvms = LateInlineCallGenerator::generate(jvms);
     if (_input_not_const) {
       // inlining won't be possible so no need to enqueue right now.
       call_node()->set_generator(this);
@@ -477,13 +477,13 @@
   LateInlineStringCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
     LateInlineCallGenerator(method, inline_cg) {}
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
+  virtual JVMState* generate(JVMState* jvms) {
     Compile *C = Compile::current();
     C->print_inlining_skip(this);
 
     C->add_string_late_inline(this);
 
-    JVMState* new_jvms =  DirectCallGenerator::generate(jvms, parent_parser);
+    JVMState* new_jvms =  DirectCallGenerator::generate(jvms);
     return new_jvms;
   }
 
@@ -500,13 +500,13 @@
   LateInlineBoxingCallGenerator(ciMethod* method, CallGenerator* inline_cg) :
     LateInlineCallGenerator(method, inline_cg) {}
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) {
+  virtual JVMState* generate(JVMState* jvms) {
     Compile *C = Compile::current();
     C->print_inlining_skip(this);
 
     C->add_boxing_late_inline(this);
 
-    JVMState* new_jvms =  DirectCallGenerator::generate(jvms, parent_parser);
+    JVMState* new_jvms =  DirectCallGenerator::generate(jvms);
     return new_jvms;
   }
 };
@@ -542,7 +542,7 @@
   virtual bool      is_virtual() const          { return _is_virtual; }
   virtual bool      is_deferred() const         { return true; }
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
 };
 
 
@@ -552,12 +552,12 @@
   return new WarmCallGenerator(ci, if_cold, if_hot);
 }
 
-JVMState* WarmCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* WarmCallGenerator::generate(JVMState* jvms) {
   Compile* C = Compile::current();
   if (C->log() != NULL) {
     C->log()->elem("warm_call bci='%d'", jvms->bci());
   }
-  jvms = _if_cold->generate(jvms, parent_parser);
+  jvms = _if_cold->generate(jvms);
   if (jvms != NULL) {
     Node* m = jvms->map()->control();
     if (m->is_CatchProj()) m = m->in(0);  else m = C->top();
@@ -618,7 +618,7 @@
   virtual bool      is_inline()    const    { return _if_hit->is_inline(); }
   virtual bool      is_deferred()  const    { return _if_hit->is_deferred(); }
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
 };
 
 
@@ -630,7 +630,7 @@
 }
 
 
-JVMState* PredictedCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* PredictedCallGenerator::generate(JVMState* jvms) {
   GraphKit kit(jvms);
   PhaseGVN& gvn = kit.gvn();
   // We need an explicit receiver null_check before checking its type.
@@ -648,6 +648,10 @@
     return kit.transfer_exceptions_into_jvms();
   }
 
+  // Make a copy of the replaced nodes in case we need to restore them
+  ReplacedNodes replaced_nodes = kit.map()->replaced_nodes();
+  replaced_nodes.clone();
+
   Node* exact_receiver = receiver;  // will get updated in place...
   Node* slow_ctl = kit.type_check_receiver(receiver,
                                            _predicted_receiver, _hit_prob,
@@ -658,7 +662,7 @@
   { PreserveJVMState pjvms(&kit);
     kit.set_control(slow_ctl);
     if (!kit.stopped()) {
-      slow_jvms = _if_missed->generate(kit.sync_jvms(), parent_parser);
+      slow_jvms = _if_missed->generate(kit.sync_jvms());
       if (kit.failing())
         return NULL;  // might happen because of NodeCountInliningCutoff
       assert(slow_jvms != NULL, "must be");
@@ -679,12 +683,12 @@
   kit.replace_in_map(receiver, exact_receiver);
 
   // Make the hot call:
-  JVMState* new_jvms = _if_hit->generate(kit.sync_jvms(), parent_parser);
+  JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
   if (new_jvms == NULL) {
     // Inline failed, so make a direct call.
     assert(_if_hit->is_inline(), "must have been a failed inline");
     CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
-    new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
+    new_jvms = cg->generate(kit.sync_jvms());
   }
   kit.add_exception_states_from(new_jvms);
   kit.set_jvms(new_jvms);
@@ -701,6 +705,11 @@
     return kit.transfer_exceptions_into_jvms();
   }
 
+  // There are 2 branches and the replaced nodes are only valid on
+  // one: restore the replaced nodes to what they were before the
+  // branch.
+  kit.map()->set_replaced_nodes(replaced_nodes);
+
   // Finish the diamond.
   kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
   RegionNode* region = new (kit.C) RegionNode(3);
@@ -710,7 +719,15 @@
   Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
   iophi->set_req(2, slow_map->i_o());
   kit.set_i_o(gvn.transform(iophi));
+  // Merge memory
   kit.merge_memory(slow_map->merged_memory(), region, 2);
+  // Transform new memory Phis.
+  for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
+    Node* phi = mms.memory();
+    if (phi->is_Phi() && phi->in(0) == region) {
+      mms.set_memory(gvn.transform(phi));
+    }
+  }
   uint tos = kit.jvms()->stkoff() + kit.sp();
   uint limit = slow_map->req();
   for (uint i = TypeFunc::Parms; i < limit; i++) {
@@ -864,15 +881,15 @@
 }
 
 
-//------------------------PredictedIntrinsicGenerator------------------------------
-// Internal class which handles all predicted Intrinsic calls.
-class PredictedIntrinsicGenerator : public CallGenerator {
+//------------------------PredicatedIntrinsicGenerator------------------------------
+// Internal class which handles all predicated Intrinsic calls.
+class PredicatedIntrinsicGenerator : public CallGenerator {
   CallGenerator* _intrinsic;
   CallGenerator* _cg;
 
 public:
-  PredictedIntrinsicGenerator(CallGenerator* intrinsic,
-                              CallGenerator* cg)
+  PredicatedIntrinsicGenerator(CallGenerator* intrinsic,
+                               CallGenerator* cg)
     : CallGenerator(cg->method())
   {
     _intrinsic = intrinsic;
@@ -883,107 +900,186 @@
   virtual bool      is_inlined()   const    { return true; }
   virtual bool      is_intrinsic() const    { return true; }
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
 };
 
 
-CallGenerator* CallGenerator::for_predicted_intrinsic(CallGenerator* intrinsic,
-                                                      CallGenerator* cg) {
-  return new PredictedIntrinsicGenerator(intrinsic, cg);
+CallGenerator* CallGenerator::for_predicated_intrinsic(CallGenerator* intrinsic,
+                                                       CallGenerator* cg) {
+  return new PredicatedIntrinsicGenerator(intrinsic, cg);
 }
 
 
-JVMState* PredictedIntrinsicGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* PredicatedIntrinsicGenerator::generate(JVMState* jvms) {
+  // The code we want to generate here is:
+  //    if (receiver == NULL)
+  //        uncommon_Trap
+  //    if (predicate(0))
+  //        do_intrinsic(0)
+  //    else
+  //    if (predicate(1))
+  //        do_intrinsic(1)
+  //    ...
+  //    else
+  //        do_java_comp
+
   GraphKit kit(jvms);
   PhaseGVN& gvn = kit.gvn();
 
   CompileLog* log = kit.C->log();
   if (log != NULL) {
-    log->elem("predicted_intrinsic bci='%d' method='%d'",
+    log->elem("predicated_intrinsic bci='%d' method='%d'",
               jvms->bci(), log->identify(method()));
   }
 
-  Node* slow_ctl = _intrinsic->generate_predicate(kit.sync_jvms());
-  if (kit.failing())
-    return NULL;  // might happen because of NodeCountInliningCutoff
-
-  SafePointNode* slow_map = NULL;
-  JVMState* slow_jvms;
-  if (slow_ctl != NULL) {
-    PreserveJVMState pjvms(&kit);
-    kit.set_control(slow_ctl);
-    if (!kit.stopped()) {
-      slow_jvms = _cg->generate(kit.sync_jvms(), parent_parser);
-      if (kit.failing())
-        return NULL;  // might happen because of NodeCountInliningCutoff
-      assert(slow_jvms != NULL, "must be");
-      kit.add_exception_states_from(slow_jvms);
-      kit.set_map(slow_jvms->map());
-      if (!kit.stopped())
-        slow_map = kit.stop();
-    }
-  }
-
-  if (kit.stopped()) {
-    // Predicate is always false.
-    kit.set_jvms(slow_jvms);
-    return kit.transfer_exceptions_into_jvms();
-  }
-
-  // Generate intrinsic code:
-  JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms(), parent_parser);
-  if (new_jvms == NULL) {
-    // Intrinsic failed, so use slow code or make a direct call.
-    if (slow_map == NULL) {
-      CallGenerator* cg = CallGenerator::for_direct_call(method());
-      new_jvms = cg->generate(kit.sync_jvms(), parent_parser);
-    } else {
-      kit.set_jvms(slow_jvms);
+  if (!method()->is_static()) {
+    // We need an explicit receiver null_check before checking its type in predicate.
+    // We share a map with the caller, so his JVMS gets adjusted.
+    Node* receiver = kit.null_check_receiver_before_call(method());
+    if (kit.stopped()) {
       return kit.transfer_exceptions_into_jvms();
     }
   }
-  kit.add_exception_states_from(new_jvms);
-  kit.set_jvms(new_jvms);
 
-  // Need to merge slow and fast?
-  if (slow_map == NULL) {
-    // The fast path is the only path remaining.
+  int n_predicates = _intrinsic->predicates_count();
+  assert(n_predicates > 0, "sanity");
+
+  JVMState** result_jvms = NEW_RESOURCE_ARRAY(JVMState*, (n_predicates+1));
+
+  // Region for normal compilation code if intrinsic failed.
+  Node* slow_region = new (kit.C) RegionNode(1);
+
+  int results = 0;
+  for (int predicate = 0; (predicate < n_predicates) && !kit.stopped(); predicate++) {
+#ifdef ASSERT
+    JVMState* old_jvms = kit.jvms();
+    SafePointNode* old_map = kit.map();
+    Node* old_io  = old_map->i_o();
+    Node* old_mem = old_map->memory();
+    Node* old_exc = old_map->next_exception();
+#endif
+    Node* else_ctrl = _intrinsic->generate_predicate(kit.sync_jvms(), predicate);
+#ifdef ASSERT
+    // Assert(no_new_memory && no_new_io && no_new_exceptions) after generate_predicate.
+    assert(old_jvms == kit.jvms(), "generate_predicate should not change jvm state");
+    SafePointNode* new_map = kit.map();
+    assert(old_io  == new_map->i_o(), "generate_predicate should not change i_o");
+    assert(old_mem == new_map->memory(), "generate_predicate should not change memory");
+    assert(old_exc == new_map->next_exception(), "generate_predicate should not add exceptions");
+#endif
+    if (!kit.stopped()) {
+      PreserveJVMState pjvms(&kit);
+      // Generate intrinsic code:
+      JVMState* new_jvms = _intrinsic->generate(kit.sync_jvms());
+      if (new_jvms == NULL) {
+        // Intrinsic failed, use normal compilation path for this predicate.
+        slow_region->add_req(kit.control());
+      } else {
+        kit.add_exception_states_from(new_jvms);
+        kit.set_jvms(new_jvms);
+        if (!kit.stopped()) {
+          result_jvms[results++] = kit.jvms();
+        }
+      }
+    }
+    if (else_ctrl == NULL) {
+      else_ctrl = kit.C->top();
+    }
+    kit.set_control(else_ctrl);
+  }
+  if (!kit.stopped()) {
+    // Final 'else' after predicates.
+    slow_region->add_req(kit.control());
+  }
+  if (slow_region->req() > 1) {
+    PreserveJVMState pjvms(&kit);
+    // Generate normal compilation code:
+    kit.set_control(gvn.transform(slow_region));
+    JVMState* new_jvms = _cg->generate(kit.sync_jvms());
+    if (kit.failing())
+      return NULL;  // might happen because of NodeCountInliningCutoff
+    assert(new_jvms != NULL, "must be");
+    kit.add_exception_states_from(new_jvms);
+    kit.set_jvms(new_jvms);
+    if (!kit.stopped()) {
+      result_jvms[results++] = kit.jvms();
+    }
+  }
+
+  if (results == 0) {
+    // All paths ended in uncommon traps.
+    (void) kit.stop();
     return kit.transfer_exceptions_into_jvms();
   }
 
-  if (kit.stopped()) {
-    // Intrinsic method threw an exception, so it's just the slow path after all.
-    kit.set_jvms(slow_jvms);
+  if (results == 1) { // Only one path
+    kit.set_jvms(result_jvms[0]);
     return kit.transfer_exceptions_into_jvms();
   }
 
-  // Finish the diamond.
+  // Merge all paths.
   kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
-  RegionNode* region = new (kit.C) RegionNode(3);
-  region->init_req(1, kit.control());
-  region->init_req(2, slow_map->control());
-  kit.set_control(gvn.transform(region));
+  RegionNode* region = new (kit.C) RegionNode(results + 1);
   Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
-  iophi->set_req(2, slow_map->i_o());
+  for (int i = 0; i < results; i++) {
+    JVMState* jvms = result_jvms[i];
+    int path = i + 1;
+    SafePointNode* map = jvms->map();
+    region->init_req(path, map->control());
+    iophi->set_req(path, map->i_o());
+    if (i == 0) {
+      kit.set_jvms(jvms);
+    } else {
+      kit.merge_memory(map->merged_memory(), region, path);
+    }
+  }
+  kit.set_control(gvn.transform(region));
   kit.set_i_o(gvn.transform(iophi));
-  kit.merge_memory(slow_map->merged_memory(), region, 2);
+  // Transform new memory Phis.
+  for (MergeMemStream mms(kit.merged_memory()); mms.next_non_empty();) {
+    Node* phi = mms.memory();
+    if (phi->is_Phi() && phi->in(0) == region) {
+      mms.set_memory(gvn.transform(phi));
+    }
+  }
+
+  // Merge debug info.
+  Node** ins = NEW_RESOURCE_ARRAY(Node*, results);
   uint tos = kit.jvms()->stkoff() + kit.sp();
-  uint limit = slow_map->req();
+  Node* map = kit.map();
+  uint limit = map->req();
   for (uint i = TypeFunc::Parms; i < limit; i++) {
     // Skip unused stack slots; fast forward to monoff();
     if (i == tos) {
       i = kit.jvms()->monoff();
       if( i >= limit ) break;
     }
-    Node* m = kit.map()->in(i);
-    Node* n = slow_map->in(i);
-    if (m != n) {
-      const Type* t = gvn.type(m)->meet_speculative(gvn.type(n));
-      Node* phi = PhiNode::make(region, m, t);
-      phi->set_req(2, n);
-      kit.map()->set_req(i, gvn.transform(phi));
+    Node* n = map->in(i);
+    ins[0] = n;
+    const Type* t = gvn.type(n);
+    bool needs_phi = false;
+    for (int j = 1; j < results; j++) {
+      JVMState* jvms = result_jvms[j];
+      Node* jmap = jvms->map();
+      Node* m = NULL;
+      if (jmap->req() > i) {
+        m = jmap->in(i);
+        if (m != n) {
+          needs_phi = true;
+          t = t->meet_speculative(gvn.type(m));
+        }
+      }
+      ins[j] = m;
+    }
+    if (needs_phi) {
+      Node* phi = PhiNode::make(region, n, t);
+      for (int j = 1; j < results; j++) {
+        phi->set_req(j + 1, ins[j]);
+      }
+      map->set_req(i, gvn.transform(phi));
     }
   }
+
   return kit.transfer_exceptions_into_jvms();
 }
 
@@ -1006,7 +1102,7 @@
   virtual bool      is_virtual() const          { ShouldNotReachHere(); return false; }
   virtual bool      is_trap() const             { return true; }
 
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
+  virtual JVMState* generate(JVMState* jvms);
 };
 
 
@@ -1018,7 +1114,7 @@
 }
 
 
-JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* UncommonTrapCallGenerator::generate(JVMState* jvms) {
   GraphKit kit(jvms);
   // Take the trap with arguments pushed on the stack.  (Cf. null_check_receiver).
   int nargs = method()->arg_size();
diff --git a/hotspot/src/share/vm/opto/callGenerator.hpp b/hotspot/src/share/vm/opto/callGenerator.hpp
index d03555f..1f08742 100644
--- a/hotspot/src/share/vm/opto/callGenerator.hpp
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp
@@ -31,8 +31,6 @@
 #include "opto/type.hpp"
 #include "runtime/deoptimization.hpp"
 
-class Parse;
-
 //---------------------------CallGenerator-------------------------------------
 // The subclasses of this class handle generation of ideal nodes for
 // call sites and method entry points.
@@ -63,8 +61,9 @@
   virtual bool      is_virtual() const          { return false; }
   // is_deferred: The decision whether to inline or not is deferred.
   virtual bool      is_deferred() const         { return false; }
-  // is_predicted: Uses an explicit check against a predicted type.
-  virtual bool      is_predicted() const        { return false; }
+  // is_predicated: Uses an explicit check (predicate).
+  virtual bool      is_predicated() const       { return false; }
+  virtual int       predicates_count() const    { return 0; }
   // is_trap: Does not return to the caller.  (E.g., uncommon trap.)
   virtual bool      is_trap() const             { return false; }
   // does_virtual_dispatch: Should try inlining as normal method first.
@@ -111,7 +110,7 @@
   //
   // If the result is NULL, it means that this CallGenerator was unable
   // to handle the given call, and another CallGenerator should be consulted.
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser) = 0;
+  virtual JVMState* generate(JVMState* jvms) = 0;
 
   // How to generate a call site that is inlined:
   static CallGenerator* for_inline(ciMethod* m, float expected_uses = -1);
@@ -157,9 +156,9 @@
   // Registry for intrinsics:
   static CallGenerator* for_intrinsic(ciMethod* m);
   static void register_intrinsic(ciMethod* m, CallGenerator* cg);
-  static CallGenerator* for_predicted_intrinsic(CallGenerator* intrinsic,
-                                                CallGenerator* cg);
-  virtual Node* generate_predicate(JVMState* jvms) { return NULL; };
+  static CallGenerator* for_predicated_intrinsic(CallGenerator* intrinsic,
+                                                 CallGenerator* cg);
+  virtual Node* generate_predicate(JVMState* jvms, int predicate) { return NULL; };
 
   virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); }
 
diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp
index 6a1b08c..67e5494 100644
--- a/hotspot/src/share/vm/opto/callnode.cpp
+++ b/hotspot/src/share/vm/opto/callnode.cpp
@@ -1089,6 +1089,7 @@
 #ifndef PRODUCT
 void SafePointNode::dump_spec(outputStream *st) const {
   st->print(" SafePoint ");
+  _replaced_nodes.dump(st);
 }
 #endif
 
diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp
index 398cbfe..6eb78b0 100644
--- a/hotspot/src/share/vm/opto/callnode.hpp
+++ b/hotspot/src/share/vm/opto/callnode.hpp
@@ -30,6 +30,7 @@
 #include "opto/multnode.hpp"
 #include "opto/opcodes.hpp"
 #include "opto/phaseX.hpp"
+#include "opto/replacednodes.hpp"
 #include "opto/type.hpp"
 
 // Portions of code courtesy of Clifford Click
@@ -335,6 +336,7 @@
   OopMap*         _oop_map;   // Array of OopMap info (8-bit char) for GC
   JVMState* const _jvms;      // Pointer to list of JVM State objects
   const TypePtr*  _adr_type;  // What type of memory does this node produce?
+  ReplacedNodes   _replaced_nodes; // During parsing: list of pair of nodes from calls to GraphKit::replace_in_map()
 
   // Many calls take *all* of memory as input,
   // but some produce a limited subset of that memory as output.
@@ -426,6 +428,37 @@
   void               set_next_exception(SafePointNode* n);
   bool                   has_exceptions() const { return next_exception() != NULL; }
 
+  // Helper methods to operate on replaced nodes
+  ReplacedNodes replaced_nodes() const {
+    return _replaced_nodes;
+  }
+
+  void set_replaced_nodes(ReplacedNodes replaced_nodes) {
+    _replaced_nodes = replaced_nodes;
+  }
+
+  void clone_replaced_nodes() {
+    _replaced_nodes.clone();
+  }
+  void record_replaced_node(Node* initial, Node* improved) {
+    _replaced_nodes.record(initial, improved);
+  }
+  void transfer_replaced_nodes_from(SafePointNode* sfpt, uint idx = 0) {
+    _replaced_nodes.transfer_from(sfpt->_replaced_nodes, idx);
+  }
+  void delete_replaced_nodes() {
+    _replaced_nodes.reset();
+  }
+  void apply_replaced_nodes() {
+    _replaced_nodes.apply(this);
+  }
+  void merge_replaced_nodes_with(SafePointNode* sfpt) {
+    _replaced_nodes.merge_with(sfpt->_replaced_nodes);
+  }
+  bool has_replaced_nodes() const {
+    return !_replaced_nodes.is_empty();
+  }
+
   // Standard Node stuff
   virtual int            Opcode() const;
   virtual bool           pinned() const { return true; }
diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp
index 53ddf7b..53515c1 100644
--- a/hotspot/src/share/vm/opto/compile.cpp
+++ b/hotspot/src/share/vm/opto/compile.cpp
@@ -391,6 +391,11 @@
   uint next = 0;
   while (next < useful.size()) {
     Node *n = useful.at(next++);
+    if (n->is_SafePoint()) {
+      // We're done with a parsing phase. Replaced nodes are not valid
+      // beyond that point.
+      n->as_SafePoint()->delete_replaced_nodes();
+    }
     // Use raw traversal of out edges since this code removes out edges
     int max = n->outcnt();
     for (int j = 0; j < max; ++j) {
@@ -660,6 +665,10 @@
                   _printer(IdealGraphPrinter::printer()),
 #endif
                   _congraph(NULL),
+                  _comp_arena(mtCompiler),
+                  _node_arena(mtCompiler),
+                  _old_arena(mtCompiler),
+                  _Compile_types(mtCompiler),
                   _replay_inline_data(NULL),
                   _late_inlines(comp_arena(), 2, 0, NULL),
                   _string_late_inlines(comp_arena(), 2, 0, NULL),
@@ -670,7 +679,6 @@
                   _inlining_incrementally(false),
                   _print_inlining_list(NULL),
                   _print_inlining_idx(0),
-                  _preserve_jvm_state(0),
                   _interpreter_frame_size(0) {
   C = this;
 
@@ -782,7 +790,7 @@
       return;
     }
     JVMState* jvms = build_start_state(start(), tf());
-    if ((jvms = cg->generate(jvms, NULL)) == NULL) {
+    if ((jvms = cg->generate(jvms)) == NULL) {
       record_method_not_compilable("method parse failed");
       return;
     }
@@ -968,6 +976,10 @@
     _in_dump_cnt(0),
     _printer(NULL),
 #endif
+    _comp_arena(mtCompiler),
+    _node_arena(mtCompiler),
+    _old_arena(mtCompiler),
+    _Compile_types(mtCompiler),
     _dead_node_list(comp_arena()),
     _dead_node_count(0),
     _congraph(NULL),
@@ -977,7 +989,6 @@
     _inlining_incrementally(false),
     _print_inlining_list(NULL),
     _print_inlining_idx(0),
-    _preserve_jvm_state(0),
     _allowed_reasons(0),
     _interpreter_frame_size(0) {
   C = this;
@@ -1910,6 +1921,8 @@
     for_igvn()->clear();
     gvn->replace_with(&igvn);
 
+    _late_inlines_pos = _late_inlines.length();
+
     while (_boxing_late_inlines.length() > 0) {
       CallGenerator* cg = _boxing_late_inlines.pop();
       cg->do_late_inline();
@@ -1973,8 +1986,8 @@
     if (live_nodes() > (uint)LiveNodeCountInliningCutoff) {
       if (low_live_nodes < (uint)LiveNodeCountInliningCutoff * 8 / 10) {
         // PhaseIdealLoop is expensive so we only try it once we are
-        // out of loop and we only try it again if the previous helped
-        // got the number of nodes down significantly
+        // out of live nodes and we only try it again if the previous
+        // helped got the number of nodes down significantly
         PhaseIdealLoop ideal_loop( igvn, false, true );
         if (failing())  return;
         low_live_nodes = live_nodes();
@@ -2066,6 +2079,10 @@
     // Inline valueOf() methods now.
     inline_boxing_calls(igvn);
 
+    if (AlwaysIncrementalInline) {
+      inline_incrementally(igvn);
+    }
+
     print_method(PHASE_INCREMENTAL_BOXING_INLINE, 2);
 
     if (failing())  return;
diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp
index acfae52..b006512 100644
--- a/hotspot/src/share/vm/opto/compile.hpp
+++ b/hotspot/src/share/vm/opto/compile.hpp
@@ -429,9 +429,6 @@
   // Remove the speculative part of types and clean up the graph
   void remove_speculative_types(PhaseIterGVN &igvn);
 
-  // Are we within a PreserveJVMState block?
-  int _preserve_jvm_state;
-
   void* _replay_inline_data; // Pointer to data loaded from file
 
  public:
@@ -1196,21 +1193,6 @@
 
   // Auxiliary method for randomized fuzzing/stressing
   static bool randomized_select(int count);
-
-  // enter a PreserveJVMState block
-  void inc_preserve_jvm_state() {
-    _preserve_jvm_state++;
-  }
-
-  // exit a PreserveJVMState block
-  void dec_preserve_jvm_state() {
-    _preserve_jvm_state--;
-    assert(_preserve_jvm_state >= 0, "_preserve_jvm_state shouldn't be negative");
-  }
-
-  bool has_preserve_jvm_state() const {
-    return _preserve_jvm_state > 0;
-  }
 };
 
 #endif // SHARE_VM_OPTO_COMPILE_HPP
diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp
index 7e8ff1c..6044690 100644
--- a/hotspot/src/share/vm/opto/doCall.cpp
+++ b/hotspot/src/share/vm/opto/doCall.cpp
@@ -115,12 +115,12 @@
   if (allow_inline && allow_intrinsics) {
     CallGenerator* cg = find_intrinsic(callee, call_does_dispatch);
     if (cg != NULL) {
-      if (cg->is_predicted()) {
+      if (cg->is_predicated()) {
         // Code without intrinsic but, hopefully, inlined.
         CallGenerator* inline_cg = this->call_generator(callee,
               vtable_index, call_does_dispatch, jvms, allow_inline, prof_factor, speculative_receiver_type, false);
         if (inline_cg != NULL) {
-          cg = CallGenerator::for_predicted_intrinsic(cg, inline_cg);
+          cg = CallGenerator::for_predicated_intrinsic(cg, inline_cg);
         }
       }
 
@@ -523,7 +523,7 @@
   // because exceptions don't return to the call site.)
   profile_call(receiver);
 
-  JVMState* new_jvms = cg->generate(jvms, this);
+  JVMState* new_jvms = cg->generate(jvms);
   if (new_jvms == NULL) {
     // When inlining attempt fails (e.g., too many arguments),
     // it may contaminate the current compile state, making it
@@ -537,7 +537,7 @@
     // intrinsic was expecting to optimize. Should always be possible to
     // get a normal java call that may inline in that case
     cg = C->call_generator(cg->method(), vtable_index, call_does_dispatch, jvms, try_inline, prof_factor(), speculative_receiver_type, /* allow_intrinsics= */ false);
-    if ((new_jvms = cg->generate(jvms, this)) == NULL) {
+    if ((new_jvms = cg->generate(jvms)) == NULL) {
       guarantee(failing(), "call failed to generate:  calls should work");
       return;
     }
diff --git a/hotspot/src/share/vm/opto/escape.cpp b/hotspot/src/share/vm/opto/escape.cpp
index 042ca41..00d9e34 100644
--- a/hotspot/src/share/vm/opto/escape.cpp
+++ b/hotspot/src/share/vm/opto/escape.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -938,7 +938,13 @@
                   strcmp(call->as_CallLeaf()->_name, "aescrypt_encryptBlock") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "aescrypt_decryptBlock") == 0 ||
                   strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_encryptAESCrypt") == 0 ||
-                  strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0)
+                  strcmp(call->as_CallLeaf()->_name, "cipherBlockChaining_decryptAESCrypt") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "sha1_implCompress") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "sha1_implCompressMB") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "sha256_implCompress") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "sha256_implCompressMB") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "sha512_implCompress") == 0 ||
+                  strcmp(call->as_CallLeaf()->_name, "sha512_implCompressMB") == 0)
                   ))) {
             call->dump();
             fatal(err_msg_res("EA unexpected CallLeaf %s", call->as_CallLeaf()->_name));
diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp
index 6ec9856..925bbae 100644
--- a/hotspot/src/share/vm/opto/graphKit.cpp
+++ b/hotspot/src/share/vm/opto/graphKit.cpp
@@ -428,6 +428,7 @@
       }
     }
   }
+  phi_map->merge_replaced_nodes_with(ex_map);
 }
 
 //--------------------------use_exception_state--------------------------------
@@ -641,7 +642,6 @@
   _map    = kit->map();   // preserve the map
   _sp     = kit->sp();
   kit->set_map(clone_map ? kit->clone_map() : NULL);
-  Compile::current()->inc_preserve_jvm_state();
 #ifdef ASSERT
   _bci    = kit->bci();
   Parse* parser = kit->is_Parse();
@@ -659,7 +659,6 @@
 #endif
   kit->set_map(_map);
   kit->set_sp(_sp);
-  Compile::current()->dec_preserve_jvm_state();
 }
 
 
@@ -1398,60 +1397,17 @@
   // on the map.  This includes locals, stack, and monitors
   // of the current (innermost) JVM state.
 
-  if (!ReplaceInParentMaps) {
+  // don't let inconsistent types from profiling escape this
+  // method
+
+  const Type* told = _gvn.type(old);
+  const Type* tnew = _gvn.type(neww);
+
+  if (!tnew->higher_equal(told)) {
     return;
   }
 
-  // PreserveJVMState doesn't do a deep copy so we can't modify
-  // parents
-  if (Compile::current()->has_preserve_jvm_state()) {
-    return;
-  }
-
-  Parse* parser = is_Parse();
-  bool progress = true;
-  Node* ctrl = map()->in(0);
-  // Follow the chain of parsers and see whether the update can be
-  // done in the map of callers. We can do the replace for a caller if
-  // the current control post dominates the control of a caller.
-  while (parser != NULL && parser->caller() != NULL && progress) {
-    progress = false;
-    Node* parent_map = parser->caller()->map();
-    assert(parser->exits().map()->jvms()->depth() == parser->caller()->depth(), "map mismatch");
-
-    Node* parent_ctrl = parent_map->in(0);
-
-    while (parent_ctrl->is_Region()) {
-      Node* n = parent_ctrl->as_Region()->is_copy();
-      if (n == NULL) {
-        break;
-      }
-      parent_ctrl = n;
-    }
-
-    for (;;) {
-      if (ctrl == parent_ctrl) {
-        // update the map of the exits which is the one that will be
-        // used when compilation resume after inlining
-        parser->exits().map()->replace_edge(old, neww);
-        progress = true;
-        break;
-      }
-      if (ctrl->is_Proj() && ctrl->as_Proj()->is_uncommon_trap_if_pattern(Deoptimization::Reason_none)) {
-        ctrl = ctrl->in(0)->in(0);
-      } else if (ctrl->is_Region()) {
-        Node* n = ctrl->as_Region()->is_copy();
-        if (n == NULL) {
-          break;
-        }
-        ctrl = n;
-      } else {
-        break;
-      }
-    }
-
-    parser = parser->parent_parser();
-  }
+  map()->record_replaced_node(old, neww);
 }
 
 
@@ -1855,12 +1811,16 @@
 
 
 // Replace the call with the current state of the kit.
-void GraphKit::replace_call(CallNode* call, Node* result) {
+void GraphKit::replace_call(CallNode* call, Node* result, bool do_replaced_nodes) {
   JVMState* ejvms = NULL;
   if (has_exceptions()) {
     ejvms = transfer_exceptions_into_jvms();
   }
 
+  ReplacedNodes replaced_nodes = map()->replaced_nodes();
+  ReplacedNodes replaced_nodes_exception;
+  Node* ex_ctl = top();
+
   SafePointNode* final_state = stop();
 
   // Find all the needed outputs of this call
@@ -1877,6 +1837,10 @@
     C->gvn_replace_by(callprojs.fallthrough_catchproj, final_ctl);
   }
   if (callprojs.fallthrough_memproj != NULL) {
+    if (final_mem->is_MergeMem()) {
+      // Parser's exits MergeMem was not transformed but may be optimized
+      final_mem = _gvn.transform(final_mem);
+    }
     C->gvn_replace_by(callprojs.fallthrough_memproj,   final_mem);
   }
   if (callprojs.fallthrough_ioproj != NULL) {
@@ -1908,10 +1872,13 @@
 
     // Load my combined exception state into the kit, with all phis transformed:
     SafePointNode* ex_map = ekit.combine_and_pop_all_exception_states();
+    replaced_nodes_exception = ex_map->replaced_nodes();
 
     Node* ex_oop = ekit.use_exception_state(ex_map);
+
     if (callprojs.catchall_catchproj != NULL) {
       C->gvn_replace_by(callprojs.catchall_catchproj, ekit.control());
+      ex_ctl = ekit.control();
     }
     if (callprojs.catchall_memproj != NULL) {
       C->gvn_replace_by(callprojs.catchall_memproj,   ekit.reset_memory());
@@ -1944,6 +1911,13 @@
       _gvn.transform(wl.pop());
     }
   }
+
+  if (callprojs.fallthrough_catchproj != NULL && !final_ctl->is_top() && do_replaced_nodes) {
+    replaced_nodes.apply(C, final_ctl);
+  }
+  if (!ex_ctl->is_top() && do_replaced_nodes) {
+    replaced_nodes_exception.apply(C, ex_ctl);
+  }
 }
 
 
@@ -2435,23 +2409,24 @@
     Node* new_slice = mms.memory2();
     if (old_slice != new_slice) {
       PhiNode* phi;
-      if (new_slice->is_Phi() && new_slice->as_Phi()->region() == region) {
-        phi = new_slice->as_Phi();
-        #ifdef ASSERT
-        if (old_slice->is_Phi() && old_slice->as_Phi()->region() == region)
-          old_slice = old_slice->in(new_path);
-        // Caller is responsible for ensuring that any pre-existing
-        // phis are already aware of old memory.
-        int old_path = (new_path > 1) ? 1 : 2;  // choose old_path != new_path
-        assert(phi->in(old_path) == old_slice, "pre-existing phis OK");
-        #endif
-        mms.set_memory(phi);
+      if (old_slice->is_Phi() && old_slice->as_Phi()->region() == region) {
+        if (mms.is_empty()) {
+          // clone base memory Phi's inputs for this memory slice
+          assert(old_slice == mms.base_memory(), "sanity");
+          phi = PhiNode::make(region, NULL, Type::MEMORY, mms.adr_type(C));
+          _gvn.set_type(phi, Type::MEMORY);
+          for (uint i = 1; i < phi->req(); i++) {
+            phi->init_req(i, old_slice->in(i));
+          }
+        } else {
+          phi = old_slice->as_Phi(); // Phi was generated already
+        }
       } else {
         phi = PhiNode::make(region, old_slice, Type::MEMORY, mms.adr_type(C));
         _gvn.set_type(phi, Type::MEMORY);
-        phi->set_req(new_path, new_slice);
-        mms.set_memory(_gvn.transform(phi));  // assume it is complete
       }
+      phi->set_req(new_path, new_slice);
+      mms.set_memory(phi);
     }
   }
 }
diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp
index d482dfc..2fcd0d2 100644
--- a/hotspot/src/share/vm/opto/graphKit.hpp
+++ b/hotspot/src/share/vm/opto/graphKit.hpp
@@ -685,7 +685,7 @@
   // Replace the call with the current state of the kit.  Requires
   // that the call was generated with separate io_projs so that
   // exceptional control flow can be handled properly.
-  void replace_call(CallNode* call, Node* result);
+  void replace_call(CallNode* call, Node* result, bool do_replaced_nodes = false);
 
   // helper functions for statistics
   void increment_counter(address counter_addr);   // increment a debug counter
diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp
index 587c3b8..f792c37 100644
--- a/hotspot/src/share/vm/opto/ifnode.cpp
+++ b/hotspot/src/share/vm/opto/ifnode.cpp
@@ -503,7 +503,7 @@
   jint  off = 0;
   if (l->is_top()) {
     return 0;
-  } else if (l->is_Add()) {
+  } else if (l->Opcode() == Op_AddI) {
     if ((off = l->in(1)->find_int_con(0)) != 0) {
       ind = l->in(2);
     } else if ((off = l->in(2)->find_int_con(0)) != 0) {
diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp
index 8398bb3..a5072d9 100644
--- a/hotspot/src/share/vm/opto/lcm.cpp
+++ b/hotspot/src/share/vm/opto/lcm.cpp
@@ -484,7 +484,9 @@
         iop == Op_CreateEx ||   // Create-exception must start block
         iop == Op_CheckCastPP
         ) {
-      worklist.map(i,worklist.pop());
+      // select the node n
+      // remove n from worklist and retain the order of remaining nodes
+      worklist.remove((uint)i);
       return n;
     }
 
@@ -570,7 +572,9 @@
   assert(idx >= 0, "index should be set");
   Node *n = worklist[(uint)idx];      // Get the winner
 
-  worklist.map((uint)idx, worklist.pop());     // Compress worklist
+  // select the node n
+  // remove n from worklist and retain the order of remaining nodes
+  worklist.remove((uint)idx);
   return n;
 }
 
diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp
index e3d5658..a713e5f 100644
--- a/hotspot/src/share/vm/opto/library_call.cpp
+++ b/hotspot/src/share/vm/opto/library_call.cpp
@@ -46,25 +46,28 @@
  public:
  private:
   bool             _is_virtual;
-  bool             _is_predicted;
   bool             _does_virtual_dispatch;
+  int8_t           _predicates_count;  // Intrinsic is predicated by several conditions
+  int8_t           _last_predicate; // Last generated predicate
   vmIntrinsics::ID _intrinsic_id;
 
  public:
-  LibraryIntrinsic(ciMethod* m, bool is_virtual, bool is_predicted, bool does_virtual_dispatch, vmIntrinsics::ID id)
+  LibraryIntrinsic(ciMethod* m, bool is_virtual, int predicates_count, bool does_virtual_dispatch, vmIntrinsics::ID id)
     : InlineCallGenerator(m),
       _is_virtual(is_virtual),
-      _is_predicted(is_predicted),
       _does_virtual_dispatch(does_virtual_dispatch),
+      _predicates_count((int8_t)predicates_count),
+      _last_predicate((int8_t)-1),
       _intrinsic_id(id)
   {
   }
   virtual bool is_intrinsic() const { return true; }
   virtual bool is_virtual()   const { return _is_virtual; }
-  virtual bool is_predicted()   const { return _is_predicted; }
+  virtual bool is_predicated() const { return _predicates_count > 0; }
+  virtual int  predicates_count() const { return _predicates_count; }
   virtual bool does_virtual_dispatch()   const { return _does_virtual_dispatch; }
-  virtual JVMState* generate(JVMState* jvms, Parse* parent_parser);
-  virtual Node* generate_predicate(JVMState* jvms);
+  virtual JVMState* generate(JVMState* jvms);
+  virtual Node* generate_predicate(JVMState* jvms, int predicate);
   vmIntrinsics::ID intrinsic_id() const { return _intrinsic_id; }
 };
 
@@ -107,8 +110,8 @@
   vmIntrinsics::ID  intrinsic_id() const { return _intrinsic->intrinsic_id(); }
   ciMethod*         callee()    const    { return _intrinsic->method(); }
 
-  bool try_to_inline();
-  Node* try_to_predicate();
+  bool  try_to_inline(int predicate);
+  Node* try_to_predicate(int predicate);
 
   void push_result() {
     // Push the result onto the stack.
@@ -307,6 +310,14 @@
   Node* inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting);
   Node* get_key_start_from_aescrypt_object(Node* aescrypt_object);
   Node* get_original_key_start_from_aescrypt_object(Node* aescrypt_object);
+  bool inline_sha_implCompress(vmIntrinsics::ID id);
+  bool inline_digestBase_implCompressMB(int predicate);
+  bool inline_sha_implCompressMB(Node* digestBaseObj, ciInstanceKlass* instklass_SHA,
+                                 bool long_state, address stubAddr, const char *stubName,
+                                 Node* src_start, Node* ofs, Node* limit);
+  Node* get_state_from_sha_object(Node *sha_object);
+  Node* get_state_from_sha5_object(Node *sha_object);
+  Node* inline_digestBase_implCompressMB_predicate(int predicate);
   bool inline_encodeISOArray();
   bool inline_updateCRC32();
   bool inline_updateBytesCRC32();
@@ -367,7 +378,7 @@
     }
   }
 
-  bool is_predicted = false;
+  int predicates = 0;
   bool does_virtual_dispatch = false;
 
   switch (id) {
@@ -508,7 +519,24 @@
   case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
     if (!UseAESIntrinsics) return NULL;
     // these two require the predicated logic
-    is_predicted = true;
+    predicates = 1;
+    break;
+
+  case vmIntrinsics::_sha_implCompress:
+    if (!UseSHA1Intrinsics) return NULL;
+    break;
+
+  case vmIntrinsics::_sha2_implCompress:
+    if (!UseSHA256Intrinsics) return NULL;
+    break;
+
+  case vmIntrinsics::_sha5_implCompress:
+    if (!UseSHA512Intrinsics) return NULL;
+    break;
+
+  case vmIntrinsics::_digestBase_implCompressMB:
+    if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) return NULL;
+    predicates = 3;
     break;
 
   case vmIntrinsics::_updateCRC32:
@@ -577,7 +605,7 @@
     if (!InlineUnsafeOps)  return NULL;
   }
 
-  return new LibraryIntrinsic(m, is_virtual, is_predicted, does_virtual_dispatch, (vmIntrinsics::ID) id);
+  return new LibraryIntrinsic(m, is_virtual, predicates, does_virtual_dispatch, (vmIntrinsics::ID) id);
 }
 
 //----------------------register_library_intrinsics-----------------------
@@ -586,7 +614,7 @@
   // Nothing to do here.
 }
 
-JVMState* LibraryIntrinsic::generate(JVMState* jvms, Parse* parent_parser) {
+JVMState* LibraryIntrinsic::generate(JVMState* jvms) {
   LibraryCallKit kit(jvms, this);
   Compile* C = kit.C;
   int nodes = C->unique();
@@ -601,7 +629,7 @@
   const int bci    = kit.bci();
 
   // Try to inline the intrinsic.
-  if (kit.try_to_inline()) {
+  if (kit.try_to_inline(_last_predicate)) {
     if (C->print_intrinsics() || C->print_inlining()) {
       C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
     }
@@ -634,12 +662,13 @@
   return NULL;
 }
 
-Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) {
+Node* LibraryIntrinsic::generate_predicate(JVMState* jvms, int predicate) {
   LibraryCallKit kit(jvms, this);
   Compile* C = kit.C;
   int nodes = C->unique();
+  _last_predicate = predicate;
 #ifndef PRODUCT
-  assert(is_predicted(), "sanity");
+  assert(is_predicated() && predicate < predicates_count(), "sanity");
   if ((C->print_intrinsics() || C->print_inlining()) && Verbose) {
     char buf[1000];
     const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf));
@@ -649,10 +678,10 @@
   ciMethod* callee = kit.callee();
   const int bci    = kit.bci();
 
-  Node* slow_ctl = kit.try_to_predicate();
+  Node* slow_ctl = kit.try_to_predicate(predicate);
   if (!kit.failing()) {
     if (C->print_intrinsics() || C->print_inlining()) {
-      C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)");
+      C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual, predicate)" : "(intrinsic, predicate)");
     }
     C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked);
     if (C->log()) {
@@ -681,7 +710,7 @@
   return NULL;
 }
 
-bool LibraryCallKit::try_to_inline() {
+bool LibraryCallKit::try_to_inline(int predicate) {
   // Handle symbolic names for otherwise undistinguished boolean switches:
   const bool is_store       = true;
   const bool is_native_ptr  = true;
@@ -875,6 +904,14 @@
   case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
     return inline_cipherBlockChaining_AESCrypt(intrinsic_id());
 
+  case vmIntrinsics::_sha_implCompress:
+  case vmIntrinsics::_sha2_implCompress:
+  case vmIntrinsics::_sha5_implCompress:
+    return inline_sha_implCompress(intrinsic_id());
+
+  case vmIntrinsics::_digestBase_implCompressMB:
+    return inline_digestBase_implCompressMB(predicate);
+
   case vmIntrinsics::_encodeISOArray:
     return inline_encodeISOArray();
 
@@ -898,7 +935,7 @@
   }
 }
 
-Node* LibraryCallKit::try_to_predicate() {
+Node* LibraryCallKit::try_to_predicate(int predicate) {
   if (!jvms()->has_method()) {
     // Root JVMState has a null method.
     assert(map()->memory()->Opcode() == Op_Parm, "");
@@ -912,6 +949,8 @@
     return inline_cipherBlockChaining_AESCrypt_predicate(false);
   case vmIntrinsics::_cipherBlockChaining_decryptAESCrypt:
     return inline_cipherBlockChaining_AESCrypt_predicate(true);
+  case vmIntrinsics::_digestBase_implCompressMB:
+    return inline_digestBase_implCompressMB_predicate(predicate);
 
   default:
     // If you get here, it may be that someone has added a new intrinsic
@@ -5866,7 +5905,12 @@
   BasicType bt = field->layout_type();
 
   // Build the resultant type of the load
-  const Type *type = TypeOopPtr::make_from_klass(field_klass->as_klass());
+  const Type *type;
+  if (bt == T_OBJECT) {
+    type = TypeOopPtr::make_from_klass(field_klass->as_klass());
+  } else {
+    type = Type::get_const_basic_type(bt);
+  }
 
   // Build the load.
   Node* loadedField = make_load(NULL, adr, type, bt, adr_type, MemNode::unordered, is_vol);
@@ -5996,7 +6040,7 @@
   assert(tinst != NULL, "CBC obj is null");
   assert(tinst->klass()->is_loaded(), "CBC obj is not loaded");
   ciKlass* klass_AESCrypt = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make("com/sun/crypto/provider/AESCrypt"));
-  if (!klass_AESCrypt->is_loaded()) return false;
+  assert(klass_AESCrypt->is_loaded(), "predicate checks that this class is loaded");
 
   ciInstanceKlass* instklass_AESCrypt = klass_AESCrypt->as_instance_klass();
   const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_AESCrypt);
@@ -6071,11 +6115,8 @@
 //    note cipher==plain is more conservative than the original java code but that's OK
 //
 Node* LibraryCallKit::inline_cipherBlockChaining_AESCrypt_predicate(bool decrypting) {
-  // First, check receiver for NULL since it is virtual method.
+  // The receiver was checked for NULL already.
   Node* objCBC = argument(0);
-  objCBC = null_check(objCBC);
-
-  if (stopped()) return NULL; // Always NULL
 
   // Load embeddedCipher field of CipherBlockChaining object.
   Node* embeddedCipherObj = load_field_from_object(objCBC, "embeddedCipher", "Lcom/sun/crypto/provider/SymmetricCipher;", /*is_exact*/ false);
@@ -6122,3 +6163,258 @@
   record_for_igvn(region);
   return _gvn.transform(region);
 }
+
+//------------------------------inline_sha_implCompress-----------------------
+//
+// Calculate SHA (i.e., SHA-1) for single-block byte[] array.
+// void com.sun.security.provider.SHA.implCompress(byte[] buf, int ofs)
+//
+// Calculate SHA2 (i.e., SHA-244 or SHA-256) for single-block byte[] array.
+// void com.sun.security.provider.SHA2.implCompress(byte[] buf, int ofs)
+//
+// Calculate SHA5 (i.e., SHA-384 or SHA-512) for single-block byte[] array.
+// void com.sun.security.provider.SHA5.implCompress(byte[] buf, int ofs)
+//
+bool LibraryCallKit::inline_sha_implCompress(vmIntrinsics::ID id) {
+  assert(callee()->signature()->size() == 2, "sha_implCompress has 2 parameters");
+
+  Node* sha_obj = argument(0);
+  Node* src     = argument(1); // type oop
+  Node* ofs     = argument(2); // type int
+
+  const Type* src_type = src->Value(&_gvn);
+  const TypeAryPtr* top_src = src_type->isa_aryptr();
+  if (top_src  == NULL || top_src->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+  // Figure out the size and type of the elements we will be copying.
+  BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (src_elem != T_BYTE) {
+    return false;
+  }
+  // 'src_start' points to src array + offset
+  Node* src_start = array_element_address(src, ofs, src_elem);
+  Node* state = NULL;
+  address stubAddr;
+  const char *stubName;
+
+  switch(id) {
+  case vmIntrinsics::_sha_implCompress:
+    assert(UseSHA1Intrinsics, "need SHA1 instruction support");
+    state = get_state_from_sha_object(sha_obj);
+    stubAddr = StubRoutines::sha1_implCompress();
+    stubName = "sha1_implCompress";
+    break;
+  case vmIntrinsics::_sha2_implCompress:
+    assert(UseSHA256Intrinsics, "need SHA256 instruction support");
+    state = get_state_from_sha_object(sha_obj);
+    stubAddr = StubRoutines::sha256_implCompress();
+    stubName = "sha256_implCompress";
+    break;
+  case vmIntrinsics::_sha5_implCompress:
+    assert(UseSHA512Intrinsics, "need SHA512 instruction support");
+    state = get_state_from_sha5_object(sha_obj);
+    stubAddr = StubRoutines::sha512_implCompress();
+    stubName = "sha512_implCompress";
+    break;
+  default:
+    fatal_unexpected_iid(id);
+    return false;
+  }
+  if (state == NULL) return false;
+
+  // Call the stub.
+  Node* call = make_runtime_call(RC_LEAF|RC_NO_FP, OptoRuntime::sha_implCompress_Type(),
+                                 stubAddr, stubName, TypePtr::BOTTOM,
+                                 src_start, state);
+
+  return true;
+}
+
+//------------------------------inline_digestBase_implCompressMB-----------------------
+//
+// Calculate SHA/SHA2/SHA5 for multi-block byte[] array.
+// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit)
+//
+bool LibraryCallKit::inline_digestBase_implCompressMB(int predicate) {
+  assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
+         "need SHA1/SHA256/SHA512 instruction support");
+  assert((uint)predicate < 3, "sanity");
+  assert(callee()->signature()->size() == 3, "digestBase_implCompressMB has 3 parameters");
+
+  Node* digestBase_obj = argument(0); // The receiver was checked for NULL already.
+  Node* src            = argument(1); // byte[] array
+  Node* ofs            = argument(2); // type int
+  Node* limit          = argument(3); // type int
+
+  const Type* src_type = src->Value(&_gvn);
+  const TypeAryPtr* top_src = src_type->isa_aryptr();
+  if (top_src  == NULL || top_src->klass()  == NULL) {
+    // failed array check
+    return false;
+  }
+  // Figure out the size and type of the elements we will be copying.
+  BasicType src_elem = src_type->isa_aryptr()->klass()->as_array_klass()->element_type()->basic_type();
+  if (src_elem != T_BYTE) {
+    return false;
+  }
+  // 'src_start' points to src array + offset
+  Node* src_start = array_element_address(src, ofs, src_elem);
+
+  const char* klass_SHA_name = NULL;
+  const char* stub_name = NULL;
+  address     stub_addr = NULL;
+  bool        long_state = false;
+
+  switch (predicate) {
+  case 0:
+    if (UseSHA1Intrinsics) {
+      klass_SHA_name = "sun/security/provider/SHA";
+      stub_name = "sha1_implCompressMB";
+      stub_addr = StubRoutines::sha1_implCompressMB();
+    }
+    break;
+  case 1:
+    if (UseSHA256Intrinsics) {
+      klass_SHA_name = "sun/security/provider/SHA2";
+      stub_name = "sha256_implCompressMB";
+      stub_addr = StubRoutines::sha256_implCompressMB();
+    }
+    break;
+  case 2:
+    if (UseSHA512Intrinsics) {
+      klass_SHA_name = "sun/security/provider/SHA5";
+      stub_name = "sha512_implCompressMB";
+      stub_addr = StubRoutines::sha512_implCompressMB();
+      long_state = true;
+    }
+    break;
+  default:
+    fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate));
+  }
+  if (klass_SHA_name != NULL) {
+    // get DigestBase klass to lookup for SHA klass
+    const TypeInstPtr* tinst = _gvn.type(digestBase_obj)->isa_instptr();
+    assert(tinst != NULL, "digestBase_obj is not instance???");
+    assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
+
+    ciKlass* klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name));
+    assert(klass_SHA->is_loaded(), "predicate checks that this class is loaded");
+    ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass();
+    return inline_sha_implCompressMB(digestBase_obj, instklass_SHA, long_state, stub_addr, stub_name, src_start, ofs, limit);
+  }
+  return false;
+}
+//------------------------------inline_sha_implCompressMB-----------------------
+bool LibraryCallKit::inline_sha_implCompressMB(Node* digestBase_obj, ciInstanceKlass* instklass_SHA,
+                                               bool long_state, address stubAddr, const char *stubName,
+                                               Node* src_start, Node* ofs, Node* limit) {
+  const TypeKlassPtr* aklass = TypeKlassPtr::make(instklass_SHA);
+  const TypeOopPtr* xtype = aklass->as_instance_type();
+  Node* sha_obj = new (C) CheckCastPPNode(control(), digestBase_obj, xtype);
+  sha_obj = _gvn.transform(sha_obj);
+
+  Node* state;
+  if (long_state) {
+    state = get_state_from_sha5_object(sha_obj);
+  } else {
+    state = get_state_from_sha_object(sha_obj);
+  }
+  if (state == NULL) return false;
+
+  // Call the stub.
+  Node* call = make_runtime_call(RC_LEAF|RC_NO_FP,
+                                 OptoRuntime::digestBase_implCompressMB_Type(),
+                                 stubAddr, stubName, TypePtr::BOTTOM,
+                                 src_start, state, ofs, limit);
+  // return ofs (int)
+  Node* result = _gvn.transform(new (C) ProjNode(call, TypeFunc::Parms));
+  set_result(result);
+
+  return true;
+}
+
+//------------------------------get_state_from_sha_object-----------------------
+Node * LibraryCallKit::get_state_from_sha_object(Node *sha_object) {
+  Node* sha_state = load_field_from_object(sha_object, "state", "[I", /*is_exact*/ false);
+  assert (sha_state != NULL, "wrong version of sun.security.provider.SHA/SHA2");
+  if (sha_state == NULL) return (Node *) NULL;
+
+  // now have the array, need to get the start address of the state array
+  Node* state = array_element_address(sha_state, intcon(0), T_INT);
+  return state;
+}
+
+//------------------------------get_state_from_sha5_object-----------------------
+Node * LibraryCallKit::get_state_from_sha5_object(Node *sha_object) {
+  Node* sha_state = load_field_from_object(sha_object, "state", "[J", /*is_exact*/ false);
+  assert (sha_state != NULL, "wrong version of sun.security.provider.SHA5");
+  if (sha_state == NULL) return (Node *) NULL;
+
+  // now have the array, need to get the start address of the state array
+  Node* state = array_element_address(sha_state, intcon(0), T_LONG);
+  return state;
+}
+
+//----------------------------inline_digestBase_implCompressMB_predicate----------------------------
+// Return node representing slow path of predicate check.
+// the pseudo code we want to emulate with this predicate is:
+//    if (digestBaseObj instanceof SHA/SHA2/SHA5) do_intrinsic, else do_javapath
+//
+Node* LibraryCallKit::inline_digestBase_implCompressMB_predicate(int predicate) {
+  assert(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics,
+         "need SHA1/SHA256/SHA512 instruction support");
+  assert((uint)predicate < 3, "sanity");
+
+  // The receiver was checked for NULL already.
+  Node* digestBaseObj = argument(0);
+
+  // get DigestBase klass for instanceOf check
+  const TypeInstPtr* tinst = _gvn.type(digestBaseObj)->isa_instptr();
+  assert(tinst != NULL, "digestBaseObj is null");
+  assert(tinst->klass()->is_loaded(), "DigestBase is not loaded");
+
+  const char* klass_SHA_name = NULL;
+  switch (predicate) {
+  case 0:
+    if (UseSHA1Intrinsics) {
+      // we want to do an instanceof comparison against the SHA class
+      klass_SHA_name = "sun/security/provider/SHA";
+    }
+    break;
+  case 1:
+    if (UseSHA256Intrinsics) {
+      // we want to do an instanceof comparison against the SHA2 class
+      klass_SHA_name = "sun/security/provider/SHA2";
+    }
+    break;
+  case 2:
+    if (UseSHA512Intrinsics) {
+      // we want to do an instanceof comparison against the SHA5 class
+      klass_SHA_name = "sun/security/provider/SHA5";
+    }
+    break;
+  default:
+    fatal(err_msg_res("unknown SHA intrinsic predicate: %d", predicate));
+  }
+
+  ciKlass* klass_SHA = NULL;
+  if (klass_SHA_name != NULL) {
+    klass_SHA = tinst->klass()->as_instance_klass()->find_klass(ciSymbol::make(klass_SHA_name));
+  }
+  if ((klass_SHA == NULL) || !klass_SHA->is_loaded()) {
+    // if none of SHA/SHA2/SHA5 is loaded, we never take the intrinsic fast path
+    Node* ctrl = control();
+    set_control(top()); // no intrinsic path
+    return ctrl;
+  }
+  ciInstanceKlass* instklass_SHA = klass_SHA->as_instance_klass();
+
+  Node* instofSHA = gen_instanceof(digestBaseObj, makecon(TypeKlassPtr::make(instklass_SHA)));
+  Node* cmp_instof = _gvn.transform(new (C) CmpINode(instofSHA, intcon(1)));
+  Node* bool_instof = _gvn.transform(new (C) BoolNode(cmp_instof, BoolTest::ne));
+  Node* instof_false = generate_guard(bool_instof, NULL, PROB_MIN);
+
+  return instof_false;  // even if it is NULL
+}
diff --git a/hotspot/src/share/vm/opto/multnode.cpp b/hotspot/src/share/vm/opto/multnode.cpp
index 300f624..1da4b77 100644
--- a/hotspot/src/share/vm/opto/multnode.cpp
+++ b/hotspot/src/share/vm/opto/multnode.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -194,7 +194,9 @@
     }
   }
 
-  ProjNode* other_proj = iff->proj_out(1-_con)->as_Proj();
+  ProjNode* other_proj = iff->proj_out(1-_con);
+  if (other_proj == NULL) // Should never happen, but make Parfait happy.
+      return false;
   if (other_proj->is_uncommon_trap_proj(reason)) {
     assert(reason == Deoptimization::Reason_none ||
            Compile::current()->is_predicate_opaq(iff->in(1)->in(1)), "should be on the list");
diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp
index a05c5d2..dcb89f8 100644
--- a/hotspot/src/share/vm/opto/node.cpp
+++ b/hotspot/src/share/vm/opto/node.cpp
@@ -527,6 +527,9 @@
   if (n->is_Call()) {
     n->as_Call()->clone_jvms(C);
   }
+  if (n->is_SafePoint()) {
+    n->as_SafePoint()->clone_replaced_nodes();
+  }
   return n;                     // Return the clone
 }
 
@@ -622,6 +625,9 @@
   if (is_expensive()) {
     compile->remove_expensive_node(this);
   }
+  if (is_SafePoint()) {
+    as_SafePoint()->delete_replaced_nodes();
+  }
 #ifdef ASSERT
   // We will not actually delete the storage, but we'll make the node unusable.
   *(address*)this = badAddress;  // smash the C++ vtbl, probably
diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp
index ede7534..aba5d64 100644
--- a/hotspot/src/share/vm/opto/output.cpp
+++ b/hotspot/src/share/vm/opto/output.cpp
@@ -783,9 +783,10 @@
     // grow downwards in all implementations.
     // (If, on some machine, the interpreter's Java locals or stack
     // were to grow upwards, the embedded doubles would be word-swapped.)
-    jint   *dp = (jint*)&d;
-    array->append(new ConstantIntValue(dp[1]));
-    array->append(new ConstantIntValue(dp[0]));
+    jlong_accessor acc;
+    acc.long_value = jlong_cast(d);
+    array->append(new ConstantIntValue(acc.words[1]));
+    array->append(new ConstantIntValue(acc.words[0]));
 #endif
     break;
   }
@@ -802,9 +803,10 @@
     // grow downwards in all implementations.
     // (If, on some machine, the interpreter's Java locals or stack
     // were to grow upwards, the embedded doubles would be word-swapped.)
-    jint *dp = (jint*)&d;
-    array->append(new ConstantIntValue(dp[1]));
-    array->append(new ConstantIntValue(dp[0]));
+    jlong_accessor acc;
+    acc.long_value = d;
+    array->append(new ConstantIntValue(acc.words[1]));
+    array->append(new ConstantIntValue(acc.words[0]));
 #endif
     break;
   }
diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp
index bf39157..a83fcef 100644
--- a/hotspot/src/share/vm/opto/parse.hpp
+++ b/hotspot/src/share/vm/opto/parse.hpp
@@ -357,12 +357,13 @@
   int _est_switch_depth;        // Debugging SwitchRanges.
 #endif
 
-  // parser for the caller of the method of this object
-  Parse* const _parent;
+  bool         _first_return;                  // true if return is the first to be parsed
+  bool         _replaced_nodes_for_exceptions; // needs processing of replaced nodes in exception paths?
+  uint         _new_idx;                       // any node with _idx above were new during this parsing. Used to trim the replaced nodes list.
 
  public:
   // Constructor
-  Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent);
+  Parse(JVMState* caller, ciMethod* parse_method, float expected_uses);
 
   virtual Parse* is_Parse() const { return (Parse*)this; }
 
@@ -419,8 +420,6 @@
     return block()->successor_for_bci(bci);
   }
 
-  Parse* parent_parser() const { return _parent; }
-
  private:
   // Create a JVMS & map for the initial state of this method.
   SafePointNode* create_entry_map();
diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp
index 52e76c4..c377bf0 100644
--- a/hotspot/src/share/vm/opto/parse1.cpp
+++ b/hotspot/src/share/vm/opto/parse1.cpp
@@ -381,8 +381,8 @@
 
 //------------------------------Parse------------------------------------------
 // Main parser constructor.
-Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses, Parse* parent)
-  : _exits(caller), _parent(parent)
+Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses)
+  : _exits(caller)
 {
   // Init some variables
   _caller = caller;
@@ -395,6 +395,9 @@
   _entry_bci = InvocationEntryBci;
   _tf = NULL;
   _block = NULL;
+  _first_return = true;
+  _replaced_nodes_for_exceptions = false;
+  _new_idx = C->unique();
   debug_only(_block_count = -1);
   debug_only(_blocks = (Block*)-1);
 #ifndef PRODUCT
@@ -565,12 +568,13 @@
     set_map(entry_map);
     do_method_entry();
   }
-  if (depth() == 1) {
+
+  if (depth() == 1 && !failing()) {
     // Add check to deoptimize the nmethod if RTM state was changed
     rtm_deopt();
   }
 
-  // Check for bailouts during method entry.
+  // Check for bailouts during method entry or RTM state check setup.
   if (failing()) {
     if (log)  log->done("parse");
     C->set_default_node_notes(caller_nn);
@@ -894,6 +898,10 @@
   for (uint i = 0; i < TypeFunc::Parms; i++) {
     caller.map()->set_req(i, ex_map->in(i));
   }
+  if (ex_map->has_replaced_nodes()) {
+    _replaced_nodes_for_exceptions = true;
+  }
+  caller.map()->transfer_replaced_nodes_from(ex_map, _new_idx);
   // ...and the exception:
   Node*          ex_oop        = saved_ex_oop(ex_map);
   SafePointNode* caller_ex_map = caller.make_exception_state(ex_oop);
@@ -962,7 +970,7 @@
   bool do_synch = method()->is_synchronized() && GenerateSynchronizationCode;
 
   // record exit from a method if compiled while Dtrace is turned on.
-  if (do_synch || C->env()->dtrace_method_probes()) {
+  if (do_synch || C->env()->dtrace_method_probes() || _replaced_nodes_for_exceptions) {
     // First move the exception list out of _exits:
     GraphKit kit(_exits.transfer_exceptions_into_jvms());
     SafePointNode* normal_map = kit.map();  // keep this guy safe
@@ -987,6 +995,9 @@
       if (C->env()->dtrace_method_probes()) {
         kit.make_dtrace_method_exit(method());
       }
+      if (_replaced_nodes_for_exceptions) {
+        kit.map()->apply_replaced_nodes();
+      }
       // Done with exception-path processing.
       ex_map = kit.make_exception_state(ex_oop);
       assert(ex_jvms->same_calls_as(ex_map->jvms()), "sanity");
@@ -1006,6 +1017,7 @@
       _exits.add_exception_state(ex_map);
     }
   }
+  _exits.map()->apply_replaced_nodes();
 }
 
 //-----------------------------create_entry_map-------------------------------
@@ -1020,6 +1032,9 @@
     return NULL;
   }
 
+  // clear current replaced nodes that are of no use from here on (map was cloned in build_exits).
+  _caller->map()->delete_replaced_nodes();
+
   // If this is an inlined method, we may have to do a receiver null check.
   if (_caller->has_method() && is_normal_parse() && !method()->is_static()) {
     GraphKit kit(_caller);
@@ -1043,6 +1058,8 @@
 
   SafePointNode* inmap = _caller->map();
   assert(inmap != NULL, "must have inmap");
+  // In case of null check on receiver above
+  map()->transfer_replaced_nodes_from(inmap, _new_idx);
 
   uint i;
 
@@ -1672,6 +1689,8 @@
       set_control(r->nonnull_req());
     }
 
+    map()->merge_replaced_nodes_with(newin);
+
     // newin has been subsumed into the lazy merge, and is now dead.
     set_block(save_block);
 
@@ -2076,6 +2095,13 @@
     phi->add_req(value);
   }
 
+  if (_first_return) {
+    _exits.map()->transfer_replaced_nodes_from(map(), _new_idx);
+    _first_return = false;
+  } else {
+    _exits.map()->merge_replaced_nodes_with(map());
+  }
+
   stop_and_kill_map();          // This CFG path dies here
 }
 
diff --git a/hotspot/src/share/vm/opto/replacednodes.cpp b/hotspot/src/share/vm/opto/replacednodes.cpp
new file mode 100644
index 0000000..bf647e9
--- /dev/null
+++ b/hotspot/src/share/vm/opto/replacednodes.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "opto/cfgnode.hpp"
+#include "opto/phaseX.hpp"
+#include "opto/replacednodes.hpp"
+
+void ReplacedNodes::allocate_if_necessary() {
+  if (_replaced_nodes == NULL) {
+    _replaced_nodes = new GrowableArray<ReplacedNode>();
+  }
+}
+
+bool ReplacedNodes::is_empty() const {
+  return _replaced_nodes == NULL || _replaced_nodes->length() == 0;
+}
+
+bool ReplacedNodes::has_node(const ReplacedNode& r) const {
+  return _replaced_nodes->find(r) != -1;
+}
+
+bool ReplacedNodes::has_target_node(Node* n) const {
+  for (int i = 0; i < _replaced_nodes->length(); i++) {
+    if (_replaced_nodes->at(i).improved() == n) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Record replaced node if not seen before
+void ReplacedNodes::record(Node* initial, Node* improved) {
+  allocate_if_necessary();
+  ReplacedNode r(initial, improved);
+  if (!has_node(r)) {
+    _replaced_nodes->push(r);
+  }
+}
+
+// Copy replaced nodes from one map to another. idx is used to
+// identify nodes that are too new to be of interest in the target
+// node list.
+void ReplacedNodes::transfer_from(const ReplacedNodes& other, uint idx) {
+  if (other.is_empty()) {
+    return;
+  }
+  allocate_if_necessary();
+  for (int i = 0; i < other._replaced_nodes->length(); i++) {
+    ReplacedNode replaced = other._replaced_nodes->at(i);
+    // Only transfer the nodes that can actually be useful
+    if (!has_node(replaced) && (replaced.initial()->_idx < idx || has_target_node(replaced.initial()))) {
+      _replaced_nodes->push(replaced);
+    }
+  }
+}
+
+void ReplacedNodes::clone() {
+  if (_replaced_nodes != NULL) {
+    GrowableArray<ReplacedNode>* replaced_nodes_clone = new GrowableArray<ReplacedNode>();
+    replaced_nodes_clone->appendAll(_replaced_nodes);
+    _replaced_nodes = replaced_nodes_clone;
+  }
+}
+
+void ReplacedNodes::reset() {
+  if (_replaced_nodes != NULL) {
+    _replaced_nodes->clear();
+  }
+}
+
+// Perfom node replacement (used when returning to caller)
+void ReplacedNodes::apply(Node* n) {
+  if (is_empty()) {
+    return;
+  }
+  for (int i = 0; i < _replaced_nodes->length(); i++) {
+    ReplacedNode replaced = _replaced_nodes->at(i);
+    n->replace_edge(replaced.initial(), replaced.improved());
+  }
+}
+
+static void enqueue_use(Node* n, Node* use, Unique_Node_List& work) {
+  if (use->is_Phi()) {
+    Node* r = use->in(0);
+    assert(r->is_Region(), "Phi should have Region");
+    for (uint i = 1; i < use->req(); i++) {
+      if (use->in(i) == n) {
+        work.push(r->in(i));
+      }
+    }
+  } else {
+    work.push(use);
+  }
+}
+
+// Perfom node replacement following late inlining
+void ReplacedNodes::apply(Compile* C, Node* ctl) {
+  // ctl is the control on exit of the method that was late inlined
+  if (is_empty()) {
+    return;
+  }
+  for (int i = 0; i < _replaced_nodes->length(); i++) {
+    ReplacedNode replaced = _replaced_nodes->at(i);
+    Node* initial = replaced.initial();
+    Node* improved = replaced.improved();
+    assert (ctl != NULL && !ctl->is_top(), "replaced node should have actual control");
+
+    ResourceMark rm;
+    Unique_Node_List work;
+    // Go over all the uses of the node that is considered for replacement...
+    for (DUIterator j = initial->outs(); initial->has_out(j); j++) {
+      Node* use = initial->out(j);
+
+      if (use == improved || use->outcnt() == 0) {
+        continue;
+      }
+      work.clear();
+      enqueue_use(initial, use, work);
+      bool replace = true;
+      // Check that this use is dominated by ctl. Go ahead with the
+      // replacement if it is.
+      while (work.size() != 0 && replace) {
+        Node* n = work.pop();
+        if (use->outcnt() == 0) {
+          continue;
+        }
+        if (n->is_CFG() || (n->in(0) != NULL && !n->in(0)->is_top())) {
+          int depth = 0;
+          Node *m = n;
+          if (!n->is_CFG()) {
+            n = n->in(0);
+          }
+          assert(n->is_CFG(), "should be CFG now");
+          while(n != ctl) {
+            n = IfNode::up_one_dom(n);
+            depth++;
+            // limit search depth
+            if (depth >= 100 || n == NULL) {
+              replace = false;
+              break;
+            }
+          }
+        } else {
+          for (DUIterator k = n->outs(); n->has_out(k); k++) {
+            enqueue_use(n, n->out(k), work);
+          }
+        }
+      }
+      if (replace) {
+        bool is_in_table = C->initial_gvn()->hash_delete(use);
+        int replaced = use->replace_edge(initial, improved);
+        if (is_in_table) {
+          C->initial_gvn()->hash_find_insert(use);
+        }
+        C->record_for_igvn(use);
+
+        assert(replaced > 0, "inconsistent");
+        --j;
+      }
+    }
+  }
+}
+
+void ReplacedNodes::dump(outputStream *st) const {
+  if (!is_empty()) {
+    tty->print("replaced nodes: ");
+    for (int i = 0; i < _replaced_nodes->length(); i++) {
+      tty->print("%d->%d", _replaced_nodes->at(i).initial()->_idx, _replaced_nodes->at(i).improved()->_idx);
+      if (i < _replaced_nodes->length()-1) {
+        tty->print(",");
+      }
+    }
+  }
+}
+
+// Merge 2 list of replaced node at a point where control flow paths merge
+void ReplacedNodes::merge_with(const ReplacedNodes& other) {
+  if (is_empty()) {
+    return;
+  }
+  if (other.is_empty()) {
+    reset();
+    return;
+  }
+  int shift = 0;
+  int len = _replaced_nodes->length();
+  for (int i = 0; i < len; i++) {
+    if (!other.has_node(_replaced_nodes->at(i))) {
+      shift++;
+    } else if (shift > 0) {
+      _replaced_nodes->at_put(i-shift, _replaced_nodes->at(i));
+    }
+  }
+  if (shift > 0) {
+    _replaced_nodes->trunc_to(len - shift);
+  }
+}
diff --git a/hotspot/src/share/vm/opto/replacednodes.hpp b/hotspot/src/share/vm/opto/replacednodes.hpp
new file mode 100644
index 0000000..0f68fe9
--- /dev/null
+++ b/hotspot/src/share/vm/opto/replacednodes.hpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_OPTO_REPLACEDNODES_HPP
+#define SHARE_VM_OPTO_REPLACEDNODES_HPP
+
+#include "opto/connode.hpp"
+
+// During parsing, when a node is "improved",
+// GraphKit::replace_in_map() is called to update the current map so
+// that the improved node is used from that point
+// on. GraphKit::replace_in_map() doesn't operate on the callers maps
+// and so some optimization opportunities may be lost. The
+// ReplacedNodes class addresses that problem.
+//
+// A ReplacedNodes object is a list of pair of nodes. Every
+// SafePointNode carries a ReplacedNodes object. Every time
+// GraphKit::replace_in_map() is called, a new pair of nodes is pushed
+// on the list of replaced nodes. When control flow paths merge, their
+// replaced nodes are also merged. When parsing exits a method to
+// return to a caller, the replaced nodes on the exit path are used to
+// update the caller's map.
+class ReplacedNodes VALUE_OBJ_CLASS_SPEC {
+ private:
+  class ReplacedNode VALUE_OBJ_CLASS_SPEC {
+  private:
+    Node* _initial;
+    Node* _improved;
+  public:
+    ReplacedNode() : _initial(NULL), _improved(NULL) {}
+    ReplacedNode(Node* initial, Node* improved) : _initial(initial), _improved(improved) {}
+    Node* initial() const  { return _initial; }
+    Node* improved() const { return _improved; }
+
+    bool operator==(const ReplacedNode& other) {
+      return _initial == other._initial && _improved == other._improved;
+    }
+  };
+  GrowableArray<ReplacedNode>* _replaced_nodes;
+
+  void allocate_if_necessary();
+  bool has_node(const ReplacedNode& r) const;
+  bool has_target_node(Node* n) const;
+
+ public:
+  ReplacedNodes()
+    : _replaced_nodes(NULL) {}
+
+  void clone();
+  void record(Node* initial, Node* improved);
+  void transfer_from(const ReplacedNodes& other, uint idx);
+  void reset();
+  void apply(Node* n);
+  void merge_with(const ReplacedNodes& other);
+  bool is_empty() const;
+  void dump(outputStream *st) const;
+  void apply(Compile* C, Node* ctl);
+};
+
+#endif // SHARE_VM_OPTO_REPLACEDNODES_HPP
diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp
index 8ac04d8..4b2da96 100644
--- a/hotspot/src/share/vm/opto/runtime.cpp
+++ b/hotspot/src/share/vm/opto/runtime.cpp
@@ -898,6 +898,50 @@
   return TypeFunc::make(domain, range);
 }
 
+/*
+ * void implCompress(byte[] buf, int ofs)
+ */
+const TypeFunc* OptoRuntime::sha_implCompress_Type() {
+  // create input type (domain)
+  int num_args = 2;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL; // buf
+  fields[argp++] = TypePtr::NOTNULL; // state
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // no result type needed
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = NULL; // void
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms, fields);
+  return TypeFunc::make(domain, range);
+}
+
+/*
+ * int implCompressMultiBlock(byte[] b, int ofs, int limit)
+ */
+const TypeFunc* OptoRuntime::digestBase_implCompressMB_Type() {
+  // create input type (domain)
+  int num_args = 4;
+  int argcnt = num_args;
+  const Type** fields = TypeTuple::fields(argcnt);
+  int argp = TypeFunc::Parms;
+  fields[argp++] = TypePtr::NOTNULL; // buf
+  fields[argp++] = TypePtr::NOTNULL; // state
+  fields[argp++] = TypeInt::INT;     // ofs
+  fields[argp++] = TypeInt::INT;     // limit
+  assert(argp == TypeFunc::Parms+argcnt, "correct decoding");
+  const TypeTuple* domain = TypeTuple::make(TypeFunc::Parms+argcnt, fields);
+
+  // returning ofs (int)
+  fields = TypeTuple::fields(1);
+  fields[TypeFunc::Parms+0] = TypeInt::INT; // ofs
+  const TypeTuple* range = TypeTuple::make(TypeFunc::Parms+1, fields);
+  return TypeFunc::make(domain, range);
+}
+
 //------------- Interpreter state access for on stack replacement
 const TypeFunc* OptoRuntime::osr_end_Type() {
   // create input type (domain)
diff --git a/hotspot/src/share/vm/opto/runtime.hpp b/hotspot/src/share/vm/opto/runtime.hpp
index 9f2a26c..b8ad010 100644
--- a/hotspot/src/share/vm/opto/runtime.hpp
+++ b/hotspot/src/share/vm/opto/runtime.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -300,6 +300,9 @@
   static const TypeFunc* aescrypt_block_Type();
   static const TypeFunc* cipherBlockChaining_aescrypt_Type();
 
+  static const TypeFunc* sha_implCompress_Type();
+  static const TypeFunc* digestBase_implCompressMB_Type();
+
   static const TypeFunc* updateBytesCRC32_Type();
 
   // leaf on stack replacement interpreter accessor types
diff --git a/hotspot/src/share/vm/opto/superword.cpp b/hotspot/src/share/vm/opto/superword.cpp
index 47b7938..297e4d3 100644
--- a/hotspot/src/share/vm/opto/superword.cpp
+++ b/hotspot/src/share/vm/opto/superword.cpp
@@ -1374,6 +1374,20 @@
       if (n->is_Load()) {
         Node* ctl = n->in(MemNode::Control);
         Node* mem = first->in(MemNode::Memory);
+        SWPointer p1(n->as_Mem(), this);
+        // Identify the memory dependency for the new loadVector node by
+        // walking up through memory chain.
+        // This is done to give flexibility to the new loadVector node so that
+        // it can move above independent storeVector nodes.
+        while (mem->is_StoreVector()) {
+          SWPointer p2(mem->as_Mem(), this);
+          int cmp = p1.cmp(p2);
+          if (SWPointer::not_equal(cmp) || !SWPointer::comparable(cmp)) {
+            mem = mem->in(MemNode::Memory);
+          } else {
+            break; // dependent memory
+          }
+        }
         Node* adr = low_adr->in(MemNode::Address);
         const TypePtr* atyp = n->adr_type();
         vn = LoadVectorNode::make(C, opc, ctl, mem, adr, atyp, vlen, velt_basic_type(n));
diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp
index 17ebee7..e877ae9 100644
--- a/hotspot/src/share/vm/opto/type.cpp
+++ b/hotspot/src/share/vm/opto/type.cpp
@@ -265,7 +265,7 @@
   // locking.
 
   Arena* save = current->type_arena();
-  Arena* shared_type_arena = new (mtCompiler)Arena();
+  Arena* shared_type_arena = new (mtCompiler)Arena(mtCompiler);
 
   current->set_type_arena(shared_type_arena);
   _shared_type_dict =
diff --git a/hotspot/src/share/vm/precompiled/precompiled.hpp b/hotspot/src/share/vm/precompiled/precompiled.hpp
index 4026c0e..d7409fc 100644
--- a/hotspot/src/share/vm/precompiled/precompiled.hpp
+++ b/hotspot/src/share/vm/precompiled/precompiled.hpp
@@ -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
@@ -193,11 +193,13 @@
 # include "runtime/mutexLocker.hpp"
 # include "runtime/objectMonitor.hpp"
 # include "runtime/orderAccess.hpp"
+# include "runtime/orderAccess.inline.hpp"
 # include "runtime/os.hpp"
 # include "runtime/osThread.hpp"
 # include "runtime/perfData.hpp"
 # include "runtime/perfMemory.hpp"
 # include "runtime/prefetch.hpp"
+# include "runtime/prefetch.inline.hpp"
 # include "runtime/reflection.hpp"
 # include "runtime/reflectionUtils.hpp"
 # include "runtime/registerMap.hpp"
@@ -218,10 +220,17 @@
 # include "runtime/vmThread.hpp"
 # include "runtime/vm_operations.hpp"
 # include "runtime/vm_version.hpp"
+# include "services/allocationSite.hpp"
 # include "services/lowMemoryDetector.hpp"
+# include "services/mallocTracker.hpp"
+# include "services/memBaseline.hpp"
 # include "services/memoryPool.hpp"
 # include "services/memoryService.hpp"
 # include "services/memoryUsage.hpp"
+# include "services/memReporter.hpp"
+# include "services/memTracker.hpp"
+# include "services/nmtCommon.hpp"
+# include "services/virtualMemoryTracker.hpp"
 # include "utilities/accessFlags.hpp"
 # include "utilities/array.hpp"
 # include "utilities/bitMap.hpp"
@@ -235,6 +244,7 @@
 # include "utilities/hashtable.hpp"
 # include "utilities/histogram.hpp"
 # include "utilities/macros.hpp"
+# include "utilities/nativeCallStack.hpp"
 # include "utilities/numberSeq.hpp"
 # include "utilities/ostream.hpp"
 # include "utilities/preserveException.hpp"
diff --git a/hotspot/src/share/vm/prims/forte.cpp b/hotspot/src/share/vm/prims/forte.cpp
index c97df96..3d12b02 100644
--- a/hotspot/src/share/vm/prims/forte.cpp
+++ b/hotspot/src/share/vm/prims/forte.cpp
@@ -32,7 +32,7 @@
 #include "oops/oop.inline2.hpp"
 #include "prims/forte.hpp"
 #include "runtime/javaCalls.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframeArray.hpp"
 
diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp
index 60a6c46..e95b01f 100644
--- a/hotspot/src/share/vm/prims/jni.cpp
+++ b/hotspot/src/share/vm/prims/jni.cpp
@@ -67,11 +67,13 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jfieldIDWorkaround.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/sharedRuntime.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/thread.inline.hpp"
 #include "runtime/vm_operations.hpp"
+#include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/defaultStream.hpp"
@@ -291,15 +293,6 @@
       "Bug in native code: jfieldID offset must address interior of object");
 }
 
-// Pick a reasonable higher bound for local capacity requested
-// for EnsureLocalCapacity and PushLocalFrame.  We don't want it too
-// high because a test (or very unusual application) may try to allocate
-// that many handles and run out of swap space.  An implementation is
-// permitted to allocate more handles than the ensured capacity, so this
-// value is set high enough to prevent compatibility problems.
-const int MAX_REASONABLE_LOCAL_CAPACITY = 4*K;
-
-
 // Wrapper to trace JNI functions
 
 #ifdef ASSERT
@@ -879,7 +872,8 @@
                                    env, capacity);
 #endif /* USDT2 */
   //%note jni_11
-  if (capacity < 0 || capacity > MAX_REASONABLE_LOCAL_CAPACITY) {
+  if (capacity < 0 ||
+      ((MaxJNILocalCapacity > 0) && (capacity > MaxJNILocalCapacity))) {
 #ifndef USDT2
     DTRACE_PROBE1(hotspot_jni, PushLocalFrame__return, JNI_ERR);
 #else /* USDT2 */
@@ -1038,7 +1032,8 @@
                                         env, capacity);
 #endif /* USDT2 */
   jint ret;
-  if (capacity >= 0 && capacity <= MAX_REASONABLE_LOCAL_CAPACITY) {
+  if (capacity >= 0 &&
+      ((MaxJNILocalCapacity <= 0) || (capacity <= MaxJNILocalCapacity))) {
     ret = JNI_OK;
   } else {
     ret = JNI_ERR;
@@ -3588,6 +3583,7 @@
     if (bad_address != NULL) {
       os::protect_memory(bad_address, size, os::MEM_PROT_READ,
                          /*is_committed*/false);
+      MemTracker::record_virtual_memory_type((void*)bad_address, mtInternal);
     }
   }
   return bad_address;
@@ -5063,6 +5059,7 @@
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #endif
+#include "memory/guardedMemory.hpp"
 #include "utilities/quickSort.hpp"
 #include "utilities/ostream.hpp"
 #if INCLUDE_VM_STRUCTS
@@ -5081,10 +5078,14 @@
 void TestMetachunk_test();
 void TestVirtualSpaceNode_test();
 void TestNewSize_test();
+void TestKlass_test();
+void Test_linked_list();
 #if INCLUDE_ALL_GCS
 void TestOldFreeSpaceCalculation_test();
 void TestG1BiasedArray_test();
+void TestBufferingOopClosure_test();
 void TestCodeCacheRemSet_test();
+void FreeRegionList_test();
 #endif
 
 void execute_internal_vm_tests() {
@@ -5101,9 +5102,12 @@
     run_unit_test(arrayOopDesc::test_max_array_length());
     run_unit_test(CollectedHeap::test_is_in());
     run_unit_test(QuickSort::test_quick_sort());
+    run_unit_test(GuardedMemory::test_guarded_memory());
     run_unit_test(AltHashing::test_alt_hash());
     run_unit_test(test_loggc_filename());
     run_unit_test(TestNewSize_test());
+    run_unit_test(TestKlass_test());
+    run_unit_test(Test_linked_list());
 #if INCLUDE_VM_STRUCTS
     run_unit_test(VMStructs::test());
 #endif
@@ -5111,7 +5115,11 @@
     run_unit_test(TestOldFreeSpaceCalculation_test());
     run_unit_test(TestG1BiasedArray_test());
     run_unit_test(HeapRegionRemSet::test_prt());
+    run_unit_test(TestBufferingOopClosure_test());
     run_unit_test(TestCodeCacheRemSet_test());
+    if (UseG1GC) {
+      run_unit_test(FreeRegionList_test());
+    }
 #endif
     tty->print_cr("All internal VM tests passed");
   }
diff --git a/hotspot/src/share/vm/prims/jniCheck.cpp b/hotspot/src/share/vm/prims/jniCheck.cpp
index 5c2fa12..4038132 100644
--- a/hotspot/src/share/vm/prims/jniCheck.cpp
+++ b/hotspot/src/share/vm/prims/jniCheck.cpp
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "classfile/vmSymbols.hpp"
+#include "memory/guardedMemory.hpp"
 #include "oops/instanceKlass.hpp"
 #include "oops/oop.inline.hpp"
 #include "oops/symbol.hpp"
@@ -35,7 +36,7 @@
 #include "runtime/handles.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/jfieldIDWorkaround.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
 #ifdef TARGET_ARCH_x86
 # include "jniTypes_x86.hpp"
 #endif
@@ -323,6 +324,74 @@
   }
 }
 
+/*
+ * Copy and wrap array elements for bounds checking.
+ * Remember the original elements (GuardedMemory::get_tag())
+ */
+static void* check_jni_wrap_copy_array(JavaThread* thr, jarray array,
+    void* orig_elements) {
+  void* result;
+  IN_VM(
+    oop a = JNIHandles::resolve_non_null(array);
+    size_t len = arrayOop(a)->length() <<
+        TypeArrayKlass::cast(a->klass())->log2_element_size();
+    result = GuardedMemory::wrap_copy(orig_elements, len, orig_elements);
+  )
+  return result;
+}
+
+static void* check_wrapped_array(JavaThread* thr, const char* fn_name,
+    void* obj, void* carray, size_t* rsz) {
+  if (carray == NULL) {
+    tty->print_cr("%s: elements vector NULL" PTR_FORMAT, fn_name, p2i(obj));
+    NativeReportJNIFatalError(thr, "Elements vector NULL");
+  }
+  GuardedMemory guarded(carray);
+  void* orig_result = guarded.get_tag();
+  if (!guarded.verify_guards()) {
+    tty->print_cr("ReleasePrimitiveArrayCritical: release array failed bounds "
+        "check, incorrect pointer returned ? array: " PTR_FORMAT " carray: "
+        PTR_FORMAT, p2i(obj), p2i(carray));
+    guarded.print_on(tty);
+    NativeReportJNIFatalError(thr, "ReleasePrimitiveArrayCritical: "
+        "failed bounds check");
+  }
+  if (orig_result == NULL) {
+    tty->print_cr("ReleasePrimitiveArrayCritical: unrecognized elements. array: "
+        PTR_FORMAT " carray: " PTR_FORMAT, p2i(obj), p2i(carray));
+    guarded.print_on(tty);
+    NativeReportJNIFatalError(thr, "ReleasePrimitiveArrayCritical: "
+        "unrecognized elements");
+  }
+  if (rsz != NULL) {
+    *rsz = guarded.get_user_size();
+  }
+  return orig_result;
+}
+
+static void* check_wrapped_array_release(JavaThread* thr, const char* fn_name,
+    void* obj, void* carray, jint mode) {
+  size_t sz;
+  void* orig_result = check_wrapped_array(thr, fn_name, obj, carray, &sz);
+  switch (mode) {
+  case 0:
+    memcpy(orig_result, carray, sz);
+    GuardedMemory::free_copy(carray);
+    break;
+  case JNI_COMMIT:
+    memcpy(orig_result, carray, sz);
+    break;
+  case JNI_ABORT:
+    GuardedMemory::free_copy(carray);
+    break;
+  default:
+    tty->print_cr("%s: Unrecognized mode %i releasing array "
+        PTR_FORMAT " elements " PTR_FORMAT, fn_name, mode, p2i(obj), p2i(carray));
+    NativeReportJNIFatalError(thr, "Unrecognized array release mode");
+  }
+  return orig_result;
+}
+
 oop jniCheck::validate_handle(JavaThread* thr, jobject obj) {
   if (JNIHandles::is_frame_handle(thr, obj) ||
       JNIHandles::is_local_handle(thr, obj) ||
@@ -1314,7 +1383,7 @@
 JNI_END
 
 // Arbitrary (but well-known) tag
-const jint STRING_TAG = 0x47114711;
+const void* STRING_TAG = (void*)0x47114711;
 
 JNI_ENTRY_CHECKED(const jchar *,
   checked_jni_GetStringChars(JNIEnv *env,
@@ -1324,21 +1393,22 @@
     IN_VM(
       checkString(thr, str);
     )
-    jchar* newResult = NULL;
+    jchar* new_result = NULL;
     const jchar *result = UNCHECKED()->GetStringChars(env,str,isCopy);
     assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringChars didn't return a copy as expected");
     if (result != NULL) {
       size_t len = UNCHECKED()->GetStringLength(env,str) + 1; // + 1 for NULL termination
-      jint* tagLocation = (jint*) AllocateHeap(len * sizeof(jchar) + sizeof(jint), mtInternal);
-      *tagLocation = STRING_TAG;
-      newResult = (jchar*) (tagLocation + 1);
-      memcpy(newResult, result, len * sizeof(jchar));
+      len *= sizeof(jchar);
+      new_result = (jchar*) GuardedMemory::wrap_copy(result, len, STRING_TAG);
+      if (new_result == NULL) {
+        vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringChars");
+      }
       // Avoiding call to UNCHECKED()->ReleaseStringChars() since that will fire unexpected dtrace probes
       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
       FreeHeap((char*)result);
     }
     functionExit(env);
-    return newResult;
+    return new_result;
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1354,11 +1424,23 @@
        UNCHECKED()->ReleaseStringChars(env,str,chars);
     }
     else {
-       jint* tagLocation = ((jint*) chars) - 1;
-       if (*tagLocation != STRING_TAG) {
-          NativeReportJNIFatalError(thr, "ReleaseStringChars called on something not allocated by GetStringChars");
-       }
-       UNCHECKED()->ReleaseStringChars(env,str,(const jchar*)tagLocation);
+      GuardedMemory guarded((void*)chars);
+      if (!guarded.verify_guards()) {
+        tty->print_cr("ReleaseStringChars: release chars failed bounds check. "
+            "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
+        guarded.print_on(tty);
+        NativeReportJNIFatalError(thr, "ReleaseStringChars: "
+            "release chars failed bounds check.");
+      }
+      if (guarded.get_tag() != STRING_TAG) {
+        tty->print_cr("ReleaseStringChars: called on something not allocated "
+            "by GetStringChars. string: " PTR_FORMAT " chars: " PTR_FORMAT,
+            p2i(str), p2i(chars));
+        NativeReportJNIFatalError(thr, "ReleaseStringChars called on something "
+            "not allocated by GetStringChars");
+      }
+       UNCHECKED()->ReleaseStringChars(env, str,
+           (const jchar*) guarded.release_for_freeing());
     }
     functionExit(env);
 JNI_END
@@ -1385,7 +1467,7 @@
 JNI_END
 
 // Arbitrary (but well-known) tag - different than GetStringChars
-const jint STRING_UTF_TAG = 0x48124812;
+const void* STRING_UTF_TAG = (void*) 0x48124812;
 
 JNI_ENTRY_CHECKED(const char *,
   checked_jni_GetStringUTFChars(JNIEnv *env,
@@ -1395,21 +1477,21 @@
     IN_VM(
       checkString(thr, str);
     )
-    char* newResult = NULL;
+    char* new_result = NULL;
     const char *result = UNCHECKED()->GetStringUTFChars(env,str,isCopy);
     assert (isCopy == NULL || *isCopy == JNI_TRUE, "GetStringUTFChars didn't return a copy as expected");
     if (result != NULL) {
       size_t len = strlen(result) + 1; // + 1 for NULL termination
-      jint* tagLocation = (jint*) AllocateHeap(len + sizeof(jint), mtInternal);
-      *tagLocation = STRING_UTF_TAG;
-      newResult = (char*) (tagLocation + 1);
-      strcpy(newResult, result);
+      new_result = (char*) GuardedMemory::wrap_copy(result, len, STRING_UTF_TAG);
+      if (new_result == NULL) {
+        vm_exit_out_of_memory(len, OOM_MALLOC_ERROR, "checked_jni_GetStringUTFChars");
+      }
       // Avoiding call to UNCHECKED()->ReleaseStringUTFChars() since that will fire unexpected dtrace probes
       // Note that the dtrace arguments for the allocated memory will not match up with this solution.
       FreeHeap((char*)result, mtInternal);
     }
     functionExit(env);
-    return newResult;
+    return new_result;
 JNI_END
 
 JNI_ENTRY_CHECKED(void,
@@ -1425,11 +1507,23 @@
        UNCHECKED()->ReleaseStringUTFChars(env,str,chars);
     }
     else {
-       jint* tagLocation = ((jint*) chars) - 1;
-       if (*tagLocation != STRING_UTF_TAG) {
-          NativeReportJNIFatalError(thr, "ReleaseStringUTFChars called on something not allocated by GetStringUTFChars");
-       }
-       UNCHECKED()->ReleaseStringUTFChars(env,str,(const char*)tagLocation);
+      GuardedMemory guarded((void*)chars);
+      if (!guarded.verify_guards()) {
+        tty->print_cr("ReleaseStringUTFChars: release chars failed bounds check. "
+            "string: " PTR_FORMAT " chars: " PTR_FORMAT, p2i(str), p2i(chars));
+        guarded.print_on(tty);
+        NativeReportJNIFatalError(thr, "ReleaseStringUTFChars: "
+            "release chars failed bounds check.");
+      }
+      if (guarded.get_tag() != STRING_UTF_TAG) {
+        tty->print_cr("ReleaseStringUTFChars: called on something not "
+            "allocated by GetStringUTFChars. string: " PTR_FORMAT " chars: "
+            PTR_FORMAT, p2i(str), p2i(chars));
+        NativeReportJNIFatalError(thr, "ReleaseStringUTFChars "
+            "called on something not allocated by GetStringUTFChars");
+      }
+      UNCHECKED()->ReleaseStringUTFChars(env, str,
+          (const char*) guarded.release_for_freeing());
     }
     functionExit(env);
 JNI_END
@@ -1514,6 +1608,9 @@
     ElementType *result = UNCHECKED()->Get##Result##ArrayElements(env, \
                                                                   array, \
                                                                   isCopy); \
+    if (result != NULL) { \
+      result = (ElementType *) check_jni_wrap_copy_array(thr, array, result); \
+    } \
     functionExit(env); \
     return result; \
 JNI_END
@@ -1538,12 +1635,10 @@
       check_primitive_array_type(thr, array, ElementTag); \
       ASSERT_OOPS_ALLOWED; \
       typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(array)); \
-      /* cannot check validity of copy, unless every request is logged by
-       * checking code.  Implementation of this check is deferred until a
-       * subsequent release.
-       */ \
     ) \
-    UNCHECKED()->Release##Result##ArrayElements(env,array,elems,mode); \
+    ElementType* orig_result = (ElementType *) check_wrapped_array_release( \
+        thr, "checked_jni_Release"#Result"ArrayElements", array, elems, mode); \
+    UNCHECKED()->Release##Result##ArrayElements(env, array, orig_result, mode); \
     functionExit(env); \
 JNI_END
 
@@ -1694,6 +1789,9 @@
       check_is_primitive_array(thr, array);
     )
     void *result = UNCHECKED()->GetPrimitiveArrayCritical(env, array, isCopy);
+    if (result != NULL) {
+      result = check_jni_wrap_copy_array(thr, array, result);
+    }
     functionExit(env);
     return result;
 JNI_END
@@ -1707,10 +1805,9 @@
     IN_VM(
       check_is_primitive_array(thr, array);
     )
-    /* The Hotspot JNI code does not use the parameters, so just check the
-     * array parameter as a minor sanity check
-     */
-    UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, carray, mode);
+    // Check the element array...
+    void* orig_result = check_wrapped_array_release(thr, "ReleasePrimitiveArrayCritical", array, carray, mode);
+    UNCHECKED()->ReleasePrimitiveArrayCritical(env, array, orig_result, mode);
     functionExit(env);
 JNI_END
 
diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp
index 3beabbb..72c8574 100644
--- a/hotspot/src/share/vm/prims/jvm.cpp
+++ b/hotspot/src/share/vm/prims/jvm.cpp
@@ -51,6 +51,7 @@
 #include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jfieldIDWorkaround.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 #include "runtime/perfData.hpp"
 #include "runtime/reflection.hpp"
diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
index 597d7a1..c16f073 100644
--- a/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.cpp
@@ -41,6 +41,7 @@
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
 #include "runtime/signature.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
 #include "runtime/vframe_hp.hpp"
 #include "runtime/vmThread.hpp"
diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp
index 9af17df..86a173f 100644
--- a/hotspot/src/share/vm/prims/jvmtiExport.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp
@@ -47,7 +47,7 @@
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
 #include "services/attachListener.hpp"
 #include "services/serviceUtil.hpp"
diff --git a/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp b/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp
index 12e69b3..4be4d27 100644
--- a/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiRawMonitor.cpp
@@ -25,7 +25,8 @@
 #include "precompiled.hpp"
 #include "prims/jvmtiRawMonitor.hpp"
 #include "runtime/interfaceSupport.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/orderAccess.inline.hpp"
+#include "runtime/thread.inline.hpp"
 
 GrowableArray<JvmtiRawMonitor*> *JvmtiPendingMonitors::_monitors = new (ResourceObj::C_HEAP, mtInternal) GrowableArray<JvmtiRawMonitor*>(1,true);
 
diff --git a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp
index 9776146..3967e5b 100644
--- a/hotspot/src/share/vm/prims/jvmtiTagMap.cpp
+++ b/hotspot/src/share/vm/prims/jvmtiTagMap.cpp
@@ -3017,7 +3017,7 @@
 
   // If there are any non-perm roots in the code cache, visit them.
   blk.set_kind(JVMTI_HEAP_REFERENCE_OTHER);
-  CodeBlobToOopClosure look_in_blobs(&blk, false);
+  CodeBlobToOopClosure look_in_blobs(&blk, !CodeBlobToOopClosure::FixRelocations);
   CodeCache::scavenge_root_nmethods_do(&look_in_blobs);
 
   return true;
diff --git a/hotspot/src/share/vm/prims/jvmtiThreadState.inline.hpp b/hotspot/src/share/vm/prims/jvmtiThreadState.inline.hpp
index e6af3d4..1b9926f 100644
--- a/hotspot/src/share/vm/prims/jvmtiThreadState.inline.hpp
+++ b/hotspot/src/share/vm/prims/jvmtiThreadState.inline.hpp
@@ -27,6 +27,7 @@
 
 #include "prims/jvmtiEnvThreadState.hpp"
 #include "prims/jvmtiThreadState.hpp"
+#include "runtime/thread.inline.hpp"
 
 // JvmtiEnvThreadStateIterator implementation
 
diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp
index 3fe2fb0..a059528 100644
--- a/hotspot/src/share/vm/prims/unsafe.cpp
+++ b/hotspot/src/share/vm/prims/unsafe.cpp
@@ -33,6 +33,8 @@
 #include "prims/jvm.h"
 #include "runtime/globals.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/prefetch.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/synchronizer.hpp"
 #include "services/threadService.hpp"
diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp
index 8fdb676..9028a85 100644
--- a/hotspot/src/share/vm/prims/whitebox.cpp
+++ b/hotspot/src/share/vm/prims/whitebox.cpp
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 
+#include "memory/metadataFactory.hpp"
 #include "memory/universe.hpp"
 #include "oops/oop.inline.hpp"
 
@@ -36,18 +37,22 @@
 #include "runtime/arguments.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/os.hpp"
+#include "utilities/array.hpp"
 #include "utilities/debug.hpp"
 #include "utilities/macros.hpp"
 #include "utilities/exceptions.hpp"
 
 #if INCLUDE_ALL_GCS
+#include "gc_implementation/parallelScavenge/parallelScavengeHeap.inline.hpp"
 #include "gc_implementation/g1/concurrentMark.hpp"
 #include "gc_implementation/g1/g1CollectedHeap.inline.hpp"
 #include "gc_implementation/g1/heapRegionRemSet.hpp"
 #endif // INCLUDE_ALL_GCS
 
-#ifdef INCLUDE_NMT
+#if INCLUDE_NMT
+#include "services/mallocSiteTable.hpp"
 #include "services/memTracker.hpp"
+#include "utilities/nativeCallStack.hpp"
 #endif // INCLUDE_NMT
 
 #include "compiler/compileBroker.hpp"
@@ -219,6 +224,30 @@
                                         (size_t) magnitude, (size_t) iterations);
 WB_END
 
+WB_ENTRY(jboolean, WB_isObjectInOldGen(JNIEnv* env, jobject o, jobject obj))
+  oop p = JNIHandles::resolve(obj);
+#if INCLUDE_ALL_GCS
+  if (UseG1GC) {
+    G1CollectedHeap* g1 = G1CollectedHeap::heap();
+    const HeapRegion* hr = g1->heap_region_containing(p);
+    if (hr == NULL) {
+      return false;
+    }
+    return !(hr->is_young());
+  } else if (UseParallelGC) {
+    ParallelScavengeHeap* psh = ParallelScavengeHeap::heap();
+    return !psh->is_in_young(p);
+  }
+#endif // INCLUDE_ALL_GCS
+  GenCollectedHeap* gch = GenCollectedHeap::heap();
+  return !gch->is_in_young(p);
+WB_END
+
+WB_ENTRY(jlong, WB_GetObjectSize(JNIEnv* env, jobject o, jobject obj))
+  oop p = JNIHandles::resolve(obj);
+  return p->size() * HeapWordSize;
+WB_END
+
 #if INCLUDE_ALL_GCS
 WB_ENTRY(jboolean, WB_G1IsHumongous(JNIEnv* env, jobject o, jobject obj))
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
@@ -229,7 +258,7 @@
 
 WB_ENTRY(jlong, WB_G1NumFreeRegions(JNIEnv* env, jobject o))
   G1CollectedHeap* g1 = G1CollectedHeap::heap();
-  size_t nr = g1->free_regions();
+  size_t nr = g1->num_free_regions();
   return (jlong)nr;
 WB_END
 
@@ -249,14 +278,18 @@
 // NMT picks it up correctly
 WB_ENTRY(jlong, WB_NMTMalloc(JNIEnv* env, jobject o, jlong size))
   jlong addr = 0;
-
-  if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
     addr = (jlong)(uintptr_t)os::malloc(size, mtTest);
-  }
-
   return addr;
 WB_END
 
+// Alloc memory with pseudo call stack. The test can create psudo malloc
+// allocation site to stress the malloc tracking.
+WB_ENTRY(jlong, WB_NMTMallocWithPseudoStack(JNIEnv* env, jobject o, jlong size, jint pseudo_stack))
+  address pc = (address)(size_t)pseudo_stack;
+  NativeCallStack stack(&pc, 1);
+  return (jlong)os::malloc(size, mtTest, stack);
+WB_END
+
 // Free the memory allocated by NMTAllocTest
 WB_ENTRY(void, WB_NMTFree(JNIEnv* env, jobject o, jlong mem))
   os::free((void*)(uintptr_t)mem, mtTest);
@@ -265,10 +298,8 @@
 WB_ENTRY(jlong, WB_NMTReserveMemory(JNIEnv* env, jobject o, jlong size))
   jlong addr = 0;
 
-  if (MemTracker::is_on() && !MemTracker::shutdown_in_progress()) {
     addr = (jlong)(uintptr_t)os::reserve_memory(size);
     MemTracker::record_virtual_memory_type((address)addr, mtTest);
-  }
 
   return addr;
 WB_END
@@ -287,20 +318,20 @@
   os::release_memory((char *)(uintptr_t)addr, size);
 WB_END
 
-// Block until the current generation of NMT data to be merged, used to reliably test the NMT feature
-WB_ENTRY(jboolean, WB_NMTWaitForDataMerge(JNIEnv* env))
-
-  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
-    return false;
-  }
-
-  return MemTracker::wbtest_wait_for_data_merge();
-WB_END
-
 WB_ENTRY(jboolean, WB_NMTIsDetailSupported(JNIEnv* env))
-  return MemTracker::tracking_level() == MemTracker::NMT_detail;
+  return MemTracker::tracking_level() == NMT_detail;
 WB_END
 
+WB_ENTRY(void, WB_NMTOverflowHashBucket(JNIEnv* env, jobject o, jlong num))
+  address pc = (address)1;
+  for (jlong index = 0; index < num; index ++) {
+    NativeCallStack stack(&pc, 1);
+    os::malloc(0, mtTest, stack);
+    pc += MallocSiteTable::hash_buckets();
+  }
+WB_END
+
+
 #endif // INCLUDE_NMT
 
 static jmethodID reflected_method_to_jmid(JavaThread* thread, JNIEnv* env, jobject method) {
@@ -501,6 +532,159 @@
   }
 WB_END
 
+template <typename T>
+static bool GetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAt)(const char*, T*)) {
+  if (name == NULL) {
+    return false;
+  }
+  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+  const char* flag_name = env->GetStringUTFChars(name, NULL);
+  bool result = (*TAt)(flag_name, value);
+  env->ReleaseStringUTFChars(name, flag_name);
+  return result;
+}
+
+template <typename T>
+static bool SetVMFlag(JavaThread* thread, JNIEnv* env, jstring name, T* value, bool (*TAtPut)(const char*, T*, Flag::Flags)) {
+  if (name == NULL) {
+    return false;
+  }
+  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+  const char* flag_name = env->GetStringUTFChars(name, NULL);
+  bool result = (*TAtPut)(flag_name, value, Flag::INTERNAL);
+  env->ReleaseStringUTFChars(name, flag_name);
+  return result;
+}
+
+template <typename T>
+static jobject box(JavaThread* thread, JNIEnv* env, Symbol* name, Symbol* sig, T value) {
+  ResourceMark rm(thread);
+  jclass clazz = env->FindClass(name->as_C_string());
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  jmethodID methodID = env->GetStaticMethodID(clazz,
+        vmSymbols::valueOf_name()->as_C_string(),
+        sig->as_C_string());
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  jobject result = env->CallStaticObjectMethod(clazz, methodID, value);
+  CHECK_JNI_EXCEPTION_(env, NULL);
+  return result;
+}
+
+static jobject booleanBox(JavaThread* thread, JNIEnv* env, jboolean value) {
+  return box(thread, env, vmSymbols::java_lang_Boolean(), vmSymbols::Boolean_valueOf_signature(), value);
+}
+static jobject integerBox(JavaThread* thread, JNIEnv* env, jint value) {
+  return box(thread, env, vmSymbols::java_lang_Integer(), vmSymbols::Integer_valueOf_signature(), value);
+}
+static jobject longBox(JavaThread* thread, JNIEnv* env, jlong value) {
+  return box(thread, env, vmSymbols::java_lang_Long(), vmSymbols::Long_valueOf_signature(), value);
+}
+/* static jobject floatBox(JavaThread* thread, JNIEnv* env, jfloat value) {
+  return box(thread, env, vmSymbols::java_lang_Float(), vmSymbols::Float_valueOf_signature(), value);
+}*/
+static jobject doubleBox(JavaThread* thread, JNIEnv* env, jdouble value) {
+  return box(thread, env, vmSymbols::java_lang_Double(), vmSymbols::Double_valueOf_signature(), value);
+}
+
+WB_ENTRY(jobject, WB_GetBooleanVMFlag(JNIEnv* env, jobject o, jstring name))
+  bool result;
+  if (GetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    return booleanBox(thread, env, result);
+  }
+  return NULL;
+WB_END
+
+WB_ENTRY(jobject, WB_GetIntxVMFlag(JNIEnv* env, jobject o, jstring name))
+  intx result;
+  if (GetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    return longBox(thread, env, result);
+  }
+  return NULL;
+WB_END
+
+WB_ENTRY(jobject, WB_GetUintxVMFlag(JNIEnv* env, jobject o, jstring name))
+  uintx result;
+  if (GetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    return longBox(thread, env, result);
+  }
+  return NULL;
+WB_END
+
+WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
+  uint64_t result;
+  if (GetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    return longBox(thread, env, result);
+  }
+  return NULL;
+WB_END
+
+WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
+  double result;
+  if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    return doubleBox(thread, env, result);
+  }
+  return NULL;
+WB_END
+
+WB_ENTRY(jstring, WB_GetStringVMFlag(JNIEnv* env, jobject o, jstring name))
+  ccstr ccstrResult;
+  if (GetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAt)) {
+    ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+    jstring result = env->NewStringUTF(ccstrResult);
+    CHECK_JNI_EXCEPTION_(env, NULL);
+    return result;
+  }
+  return NULL;
+WB_END
+
+WB_ENTRY(void, WB_SetBooleanVMFlag(JNIEnv* env, jobject o, jstring name, jboolean value))
+  bool result = value == JNI_TRUE ? true : false;
+  SetVMFlag <bool> (thread, env, name, &result, &CommandLineFlags::boolAtPut);
+WB_END
+
+WB_ENTRY(void, WB_SetIntxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
+  intx result = value;
+  SetVMFlag <intx> (thread, env, name, &result, &CommandLineFlags::intxAtPut);
+WB_END
+
+WB_ENTRY(void, WB_SetUintxVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
+  uintx result = value;
+  SetVMFlag <uintx> (thread, env, name, &result, &CommandLineFlags::uintxAtPut);
+WB_END
+
+WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
+  uint64_t result = value;
+  SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
+WB_END
+
+WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
+  double result = value;
+  SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
+WB_END
+
+WB_ENTRY(void, WB_SetStringVMFlag(JNIEnv* env, jobject o, jstring name, jstring value))
+  ThreadToNativeFromVM ttnfv(thread);   // can't be in VM when we call JNI
+  const char* ccstrValue = (value == NULL) ? NULL : env->GetStringUTFChars(value, NULL);
+  ccstr ccstrResult = ccstrValue;
+  bool needFree;
+  {
+    ThreadInVMfromNative ttvfn(thread); // back to VM
+    needFree = SetVMFlag <ccstr> (thread, env, name, &ccstrResult, &CommandLineFlags::ccstrAtPut);
+  }
+  if (value != NULL) {
+    env->ReleaseStringUTFChars(value, ccstrValue);
+  }
+  if (needFree) {
+    FREE_C_HEAP_ARRAY(char, ccstrResult, mtInternal);
+  }
+WB_END
+
+
 WB_ENTRY(jboolean, WB_IsInStringTable(JNIEnv* env, jobject o, jstring javaString))
   ResourceMark rm(THREAD);
   int len;
@@ -513,6 +697,9 @@
   Universe::heap()->collect(GCCause::_last_ditch_collection);
 WB_END
 
+WB_ENTRY(void, WB_YoungGC(JNIEnv* env, jobject o))
+  Universe::heap()->collect(GCCause::_wb_young_gc);
+WB_END
 
 WB_ENTRY(void, WB_ReadReservedMemory(JNIEnv* env, jobject o))
   // static+volatile in order to force the read to happen
@@ -559,11 +746,7 @@
     return result;
   }
 
-  clazz = env->FindClass(vmSymbols::java_lang_Integer()->as_C_string());
-  CHECK_JNI_EXCEPTION_(env, NULL);
-  jmethodID constructor = env->GetMethodID(clazz, vmSymbols::object_initializer_name()->as_C_string(), vmSymbols::int_void_signature()->as_C_string());
-  CHECK_JNI_EXCEPTION_(env, NULL);
-  jobject obj = env->NewObject(clazz, constructor, code->comp_level());
+  jobject obj = integerBox(thread, env, code->comp_level());
   CHECK_JNI_EXCEPTION_(env, NULL);
   env->SetObjectArrayElement(result, 0, obj);
 
@@ -576,6 +759,35 @@
 WB_END
 
 
+int WhiteBox::array_bytes_to_length(size_t bytes) {
+  return Array<u1>::bytes_to_length(bytes);
+}
+
+WB_ENTRY(jlong, WB_AllocateMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong size))
+  if (size < 0) {
+    THROW_MSG_0(vmSymbols::java_lang_IllegalArgumentException(),
+        err_msg("WB_AllocateMetaspace: size is negative: " JLONG_FORMAT, size));
+  }
+
+  oop class_loader_oop = JNIHandles::resolve(class_loader);
+  ClassLoaderData* cld = class_loader_oop != NULL
+      ? java_lang_ClassLoader::loader_data(class_loader_oop)
+      : ClassLoaderData::the_null_class_loader_data();
+
+  void* metadata = MetadataFactory::new_writeable_array<u1>(cld, WhiteBox::array_bytes_to_length((size_t)size), thread);
+
+  return (jlong)(uintptr_t)metadata;
+WB_END
+
+WB_ENTRY(void, WB_FreeMetaspace(JNIEnv* env, jobject wb, jobject class_loader, jlong addr, jlong size))
+  oop class_loader_oop = JNIHandles::resolve(class_loader);
+  ClassLoaderData* cld = class_loader_oop != NULL
+      ? java_lang_ClassLoader::loader_data(class_loader_oop)
+      : ClassLoaderData::the_null_class_loader_data();
+
+  MetadataFactory::free_array(cld, (Array<u1>*)(uintptr_t)addr);
+WB_END
+
 //Some convenience methods to deal with objects from java
 int WhiteBox::offset_for_field(const char* field_name, oop object,
     Symbol* signature_symbol) {
@@ -631,6 +843,8 @@
 
 static JNINativeMethod methods[] = {
   {CC"getObjectAddress",   CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectAddress  },
+  {CC"getObjectSize",      CC"(Ljava/lang/Object;)J", (void*)&WB_GetObjectSize     },
+  {CC"isObjectInOldGen",   CC"(Ljava/lang/Object;)Z", (void*)&WB_isObjectInOldGen  },
   {CC"getHeapOopSize",     CC"()I",                   (void*)&WB_GetHeapOopSize    },
   {CC"isClassAlive0",      CC"(Ljava/lang/String;)Z", (void*)&WB_IsClassAlive      },
   {CC"parseCommandLine",
@@ -651,12 +865,13 @@
 #endif // INCLUDE_ALL_GCS
 #if INCLUDE_NMT
   {CC"NMTMalloc",           CC"(J)J",                 (void*)&WB_NMTMalloc          },
+  {CC"NMTMallocWithPseudoStack", CC"(JI)J",           (void*)&WB_NMTMallocWithPseudoStack},
   {CC"NMTFree",             CC"(J)V",                 (void*)&WB_NMTFree            },
   {CC"NMTReserveMemory",    CC"(J)J",                 (void*)&WB_NMTReserveMemory   },
   {CC"NMTCommitMemory",     CC"(JJ)V",                (void*)&WB_NMTCommitMemory    },
   {CC"NMTUncommitMemory",   CC"(JJ)V",                (void*)&WB_NMTUncommitMemory  },
   {CC"NMTReleaseMemory",    CC"(JJ)V",                (void*)&WB_NMTReleaseMemory   },
-  {CC"NMTWaitForDataMerge", CC"()Z",                  (void*)&WB_NMTWaitForDataMerge},
+  {CC"NMTOverflowHashBucket", CC"(J)V",               (void*)&WB_NMTOverflowHashBucket},
   {CC"NMTIsDetailSupported",CC"()Z",                  (void*)&WB_NMTIsDetailSupported},
 #endif // INCLUDE_NMT
   {CC"deoptimizeAll",      CC"()V",                   (void*)&WB_DeoptimizeAll     },
@@ -684,9 +899,33 @@
       CC"(Ljava/lang/reflect/Executable;II)Z",        (void*)&WB_EnqueueMethodForCompilation},
   {CC"clearMethodState",
       CC"(Ljava/lang/reflect/Executable;)V",          (void*)&WB_ClearMethodState},
-  {CC"isInStringTable",   CC"(Ljava/lang/String;)Z",  (void*)&WB_IsInStringTable  },
+  {CC"setBooleanVMFlag",   CC"(Ljava/lang/String;Z)V",(void*)&WB_SetBooleanVMFlag},
+  {CC"setIntxVMFlag",      CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
+  {CC"setUintxVMFlag",     CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
+  {CC"setUint64VMFlag",    CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
+  {CC"setDoubleVMFlag",    CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
+  {CC"setStringVMFlag",    CC"(Ljava/lang/String;Ljava/lang/String;)V",
+                                                      (void*)&WB_SetStringVMFlag},
+  {CC"getBooleanVMFlag",   CC"(Ljava/lang/String;)Ljava/lang/Boolean;",
+                                                      (void*)&WB_GetBooleanVMFlag},
+  {CC"getIntxVMFlag",      CC"(Ljava/lang/String;)Ljava/lang/Long;",
+                                                      (void*)&WB_GetIntxVMFlag},
+  {CC"getUintxVMFlag",     CC"(Ljava/lang/String;)Ljava/lang/Long;",
+                                                      (void*)&WB_GetUintxVMFlag},
+  {CC"getUint64VMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Long;",
+                                                      (void*)&WB_GetUint64VMFlag},
+  {CC"getDoubleVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/Double;",
+                                                      (void*)&WB_GetDoubleVMFlag},
+  {CC"getStringVMFlag",    CC"(Ljava/lang/String;)Ljava/lang/String;",
+                                                      (void*)&WB_GetStringVMFlag},
+  {CC"isInStringTable",    CC"(Ljava/lang/String;)Z", (void*)&WB_IsInStringTable  },
   {CC"fullGC",   CC"()V",                             (void*)&WB_FullGC },
+  {CC"youngGC",  CC"()V",                             (void*)&WB_YoungGC },
   {CC"readReservedMemory", CC"()V",                   (void*)&WB_ReadReservedMemory },
+  {CC"allocateMetaspace",
+     CC"(Ljava/lang/ClassLoader;J)J",                 (void*)&WB_AllocateMetaspace },
+  {CC"freeMetaspace",
+     CC"(Ljava/lang/ClassLoader;JJ)V",                (void*)&WB_FreeMetaspace },
   {CC"getCPUFeatures",     CC"()Ljava/lang/String;",  (void*)&WB_GetCPUFeatures     },
   {CC"getNMethod",         CC"(Ljava/lang/reflect/Executable;Z)[Ljava/lang/Object;",
                                                       (void*)&WB_GetNMethod         },
diff --git a/hotspot/src/share/vm/prims/whitebox.hpp b/hotspot/src/share/vm/prims/whitebox.hpp
index a9854f3..9ab406f 100644
--- a/hotspot/src/share/vm/prims/whitebox.hpp
+++ b/hotspot/src/share/vm/prims/whitebox.hpp
@@ -62,6 +62,8 @@
     Symbol* signature_symbol);
   static const char* lookup_jstring(const char* field_name, oop object);
   static bool lookup_bool(const char* field_name, oop object);
+
+  static int array_bytes_to_length(size_t bytes);
 };
 
 
diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp
index e6cbc2e..9802b9a 100644
--- a/hotspot/src/share/vm/runtime/arguments.cpp
+++ b/hotspot/src/share/vm/runtime/arguments.cpp
@@ -98,6 +98,8 @@
 bool   Arguments::_has_profile                  = false;
 size_t Arguments::_conservative_max_heap_alignment = 0;
 uintx  Arguments::_min_heap_size                = 0;
+uintx  Arguments::_min_heap_free_ratio          = 0;
+uintx  Arguments::_max_heap_free_ratio          = 0;
 Arguments::Mode Arguments::_mode                = _mixed;
 bool   Arguments::_java_compiler                = false;
 bool   Arguments::_xdebug_mode                  = false;
@@ -294,6 +296,7 @@
   { "UseMPSS",                       JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseStringCache",                JDK_Version::jdk(8), JDK_Version::jdk(9) },
   { "UseOldInlining",                JDK_Version::jdk(9), JDK_Version::jdk(10) },
+  { "AutoShutdownNMT",               JDK_Version::jdk(9), JDK_Version::jdk(10) },
 #ifdef PRODUCT
   { "DesiredMethodLimit",
                            JDK_Version::jdk_update(7, 2), JDK_Version::jdk(8) },
@@ -1398,10 +1401,26 @@
                 (int)ObjectAlignmentInBytes, os::vm_page_size());
     return false;
   }
+  if(SurvivorAlignmentInBytes == 0) {
+    SurvivorAlignmentInBytes = ObjectAlignmentInBytes;
+  } else {
+    if (!is_power_of_2(SurvivorAlignmentInBytes)) {
+      jio_fprintf(defaultStream::error_stream(),
+            "error: SurvivorAlignmentInBytes=%d must be power of 2\n",
+            (int)SurvivorAlignmentInBytes);
+      return false;
+    }
+    if (SurvivorAlignmentInBytes < ObjectAlignmentInBytes) {
+      jio_fprintf(defaultStream::error_stream(),
+          "error: SurvivorAlignmentInBytes=%d must be greater than ObjectAlignmentInBytes=%d \n",
+          (int)SurvivorAlignmentInBytes, (int)ObjectAlignmentInBytes);
+      return false;
+    }
+  }
   return true;
 }
 
-uintx Arguments::max_heap_for_compressed_oops() {
+size_t Arguments::max_heap_for_compressed_oops() {
   // Avoid sign flip.
   assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size");
   // We need to fit both the NULL page and the heap into the memory budget, while
@@ -1505,8 +1524,10 @@
     heap_alignment = G1CollectedHeap::conservative_max_heap_alignment();
   }
 #endif // INCLUDE_ALL_GCS
-  _conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(),
-    CollectorPolicy::compute_heap_alignment());
+  _conservative_max_heap_alignment = MAX4(heap_alignment,
+                                          (size_t)os::vm_allocation_granularity(),
+                                          os::max_page_size(),
+                                          CollectorPolicy::compute_heap_alignment());
 }
 
 void Arguments::set_ergonomics_flags() {
@@ -1578,9 +1599,11 @@
     // unless the user actually sets these flags.
     if (FLAG_IS_DEFAULT(MinHeapFreeRatio)) {
       FLAG_SET_DEFAULT(MinHeapFreeRatio, 0);
+      _min_heap_free_ratio = MinHeapFreeRatio;
     }
     if (FLAG_IS_DEFAULT(MaxHeapFreeRatio)) {
       FLAG_SET_DEFAULT(MaxHeapFreeRatio, 100);
+      _max_heap_free_ratio = MaxHeapFreeRatio;
     }
   }
 
@@ -1955,6 +1978,8 @@
                   MaxHeapFreeRatio);
     return false;
   }
+  // This does not set the flag itself, but stores the value in a safe place for later usage.
+  _min_heap_free_ratio = min_heap_free_ratio;
   return true;
 }
 
@@ -1969,6 +1994,8 @@
                   MinHeapFreeRatio);
     return false;
   }
+  // This does not set the flag itself, but stores the value in a safe place for later usage.
+  _max_heap_free_ratio = max_heap_free_ratio;
   return true;
 }
 
@@ -2325,7 +2352,7 @@
 
   if (PrintNMTStatistics) {
 #if INCLUDE_NMT
-    if (MemTracker::tracking_level() == MemTracker::NMT_off) {
+    if (MemTracker::tracking_level() == NMT_off) {
 #endif // INCLUDE_NMT
       warning("PrintNMTStatistics is disabled, because native memory tracking is not enabled");
       PrintNMTStatistics = false;
@@ -2387,6 +2414,8 @@
     warning("The VM option CICompilerCountPerCPU overrides CICompilerCount.");
   }
 
+  status &= check_vm_args_consistency_ext();
+
   return status;
 }
 
@@ -3513,15 +3542,24 @@
       CommandLineFlags::printFlags(tty, false);
       vm_exit(0);
     }
-    if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
 #if INCLUDE_NMT
-      MemTracker::init_tracking_options(tail);
-#else
-      jio_fprintf(defaultStream::error_stream(),
-        "Native Memory Tracking is not supported in this VM\n");
-      return JNI_ERR;
-#endif
+    if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
+      // The launcher did not setup nmt environment variable properly.
+//      if (!MemTracker::check_launcher_nmt_support(tail)) {
+//        warning("Native Memory Tracking did not setup properly, using wrong launcher?");
+//      }
+
+      // Verify if nmt option is valid.
+      if (MemTracker::verify_nmt_option()) {
+        // Late initialization, still in single-threaded mode.
+        if (MemTracker::tracking_level() >= NMT_summary) {
+          MemTracker::init();
+        }
+      } else {
+        vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
+      }
     }
+#endif
 
 
 #ifndef PRODUCT
@@ -3772,10 +3810,6 @@
     // nothing to use the profiling, turn if off
     FLAG_SET_DEFAULT(TypeProfileLevel, 0);
   }
-  if (UseTypeSpeculation && FLAG_IS_DEFAULT(ReplaceInParentMaps)) {
-    // Doing the replace in parent maps helps speculation
-    FLAG_SET_DEFAULT(ReplaceInParentMaps, true);
-  }
 #endif
 
   if (PrintAssembly && FLAG_IS_DEFAULT(DebugNonSafepoints)) {
@@ -3833,18 +3867,24 @@
 }
 
 jint Arguments::adjust_after_os() {
-#if INCLUDE_ALL_GCS
-  if (UseParallelGC || UseParallelOldGC) {
-    if (UseNUMA) {
+  if (UseNUMA) {
+    if (UseParallelGC || UseParallelOldGC) {
       if (FLAG_IS_DEFAULT(MinHeapDeltaBytes)) {
-        FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M);
+         FLAG_SET_DEFAULT(MinHeapDeltaBytes, 64*M);
       }
-      // For those collectors or operating systems (eg, Windows) that do
-      // not support full UseNUMA, we will map to UseNUMAInterleaving for now
-      UseNUMAInterleaving = true;
+    }
+    // UseNUMAInterleaving is set to ON for all collectors and
+    // platforms when UseNUMA is set to ON. NUMA-aware collectors
+    // such as the parallel collector for Linux and Solaris will
+    // interleave old gen and survivor spaces on top of NUMA
+    // allocation policy for the eden space.
+    // Non NUMA-aware collectors such as CMS, G1 and Serial-GC on
+    // all platforms and ParallelGC on Windows will interleave all
+    // of the heap spaces across NUMA nodes.
+    if (FLAG_IS_DEFAULT(UseNUMAInterleaving)) {
+      FLAG_SET_ERGO(bool, UseNUMAInterleaving, true);
     }
   }
-#endif // INCLUDE_ALL_GCS
   return JNI_OK;
 }
 
diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp
index 8101cb5..8e3c606 100644
--- a/hotspot/src/share/vm/runtime/arguments.hpp
+++ b/hotspot/src/share/vm/runtime/arguments.hpp
@@ -284,7 +284,11 @@
   // Value of the conservative maximum heap alignment needed
   static size_t  _conservative_max_heap_alignment;
 
-  static uintx  _min_heap_size;
+  static uintx _min_heap_size;
+
+  // Used to store original flag values
+  static uintx _min_heap_free_ratio;
+  static uintx _max_heap_free_ratio;
 
   // -Xrun arguments
   static AgentLibraryList _libraryList;
@@ -461,6 +465,7 @@
   static void check_deprecated_gc_flags();
   // Check consistecy or otherwise of VM argument settings
   static bool check_vm_args_consistency();
+  static bool check_vm_args_consistency_ext();
   // Check stack pages settings
   static bool check_stack_pages();
   // Used by os_solaris
@@ -513,6 +518,10 @@
   static uintx min_heap_size()              { return _min_heap_size; }
   static void  set_min_heap_size(uintx v)   { _min_heap_size = v;  }
 
+  // Returns the original values of -XX:MinHeapFreeRatio and -XX:MaxHeapFreeRatio
+  static uintx min_heap_free_ratio()        { return _min_heap_free_ratio; }
+  static uintx max_heap_free_ratio()        { return _max_heap_free_ratio; }
+
   // -Xrun
   static AgentLibrary* libraries()          { return _libraryList.first(); }
   static bool init_libraries_at_startup()   { return !_libraryList.is_empty(); }
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/hotspot/src/share/vm/runtime/arguments_ext.cpp
similarity index 77%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to hotspot/src/share/vm/runtime/arguments_ext.cpp
index db358d2..5edd449 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/hotspot/src/share/vm/runtime/arguments_ext.cpp
@@ -1,33 +1,30 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
- */
-
-/**
- * runsunspider : runs the sunspider tests and checks for compliance
  *
- * @test
- * @option -timezone=PST
- * @runif external.sunspider
  */
 
-load(__DIR__ + "runsunspider.js");
+#include "precompiled.hpp"
+#include "runtime/arguments.hpp"
 
+bool Arguments::check_vm_args_consistency_ext() {
+  return true;
+}
diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp
index 79e1c25..f67129f 100644
--- a/hotspot/src/share/vm/runtime/deoptimization.cpp
+++ b/hotspot/src/share/vm/runtime/deoptimization.cpp
@@ -698,7 +698,7 @@
              (iframe->interpreter_frame_expression_stack_size() == (next_mask_expression_stack_size -
                                                                     top_frame_expression_stack_adjustment))) ||
             (is_top_frame && (exec_mode == Unpack_exception) && iframe->interpreter_frame_expression_stack_size() == 0) ||
-            (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute) &&
+            (is_top_frame && (exec_mode == Unpack_uncommon_trap || exec_mode == Unpack_reexecute || el->should_reexecute()) &&
              (iframe->interpreter_frame_expression_stack_size() == mask.expression_stack_size() + cur_invoke_parameter_size))
             )) {
         ttyLocker ttyl;
diff --git a/hotspot/src/share/vm/runtime/fprofiler.cpp b/hotspot/src/share/vm/runtime/fprofiler.cpp
index 0527238..58cb6e8 100644
--- a/hotspot/src/share/vm/runtime/fprofiler.cpp
+++ b/hotspot/src/share/vm/runtime/fprofiler.cpp
@@ -38,6 +38,7 @@
 #include "runtime/stubCodeGenerator.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/task.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vframe.hpp"
 #include "utilities/macros.hpp"
 
diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp
index 2d06c83..fa1ab5e 100644
--- a/hotspot/src/share/vm/runtime/frame.cpp
+++ b/hotspot/src/share/vm/runtime/frame.cpp
@@ -900,7 +900,7 @@
 }
 
 
-void frame::oops_interpreted_do(OopClosure* f, CLDToOopClosure* cld_f,
+void frame::oops_interpreted_do(OopClosure* f, CLDClosure* cld_f,
     const RegisterMap* map, bool query_oop_map_cache) {
   assert(is_interpreted_frame(), "Not an interpreted frame");
   assert(map != NULL, "map must be set");
@@ -1140,7 +1140,7 @@
 }
 
 
-void frame::oops_do_internal(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
+void frame::oops_do_internal(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache) {
 #ifndef PRODUCT
   // simulate GC crash here to dump java thread in error report
   if (CrashGCForDumpingJavaThread) {
diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp
index ef515fb..f715f68 100644
--- a/hotspot/src/share/vm/runtime/frame.hpp
+++ b/hotspot/src/share/vm/runtime/frame.hpp
@@ -419,19 +419,19 @@
 
   // Oops-do's
   void oops_compiled_arguments_do(Symbol* signature, bool has_receiver, bool has_appendix, const RegisterMap* reg_map, OopClosure* f);
-  void oops_interpreted_do(OopClosure* f, CLDToOopClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache = true);
+  void oops_interpreted_do(OopClosure* f, CLDClosure* cld_f, const RegisterMap* map, bool query_oop_map_cache = true);
 
  private:
   void oops_interpreted_arguments_do(Symbol* signature, bool has_receiver, OopClosure* f);
 
   // Iteration of oops
-  void oops_do_internal(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache);
+  void oops_do_internal(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map, bool use_interpreter_oop_map_cache);
   void oops_entry_do(OopClosure* f, const RegisterMap* map);
   void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map);
   int adjust_offset(Method* method, int index); // helper for above fn
  public:
   // Memory management
-  void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cld_f, cf, map, true); }
+  void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf, RegisterMap* map) { oops_do_internal(f, cld_f, cf, map, true); }
   void nmethods_do(CodeBlobClosure* cf);
 
   // RedefineClasses support for finding live interpreted methods on the stack
diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp
index c57cc13..928f713 100644
--- a/hotspot/src/share/vm/runtime/globals.cpp
+++ b/hotspot/src/share/vm/runtime/globals.cpp
@@ -611,7 +611,7 @@
   e.commit();
 }
 
-bool CommandLineFlags::boolAt(char* name, size_t len, bool* value) {
+bool CommandLineFlags::boolAt(const char* name, size_t len, bool* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_bool()) return false;
@@ -619,7 +619,7 @@
   return true;
 }
 
-bool CommandLineFlags::boolAtPut(char* name, size_t len, bool* value, Flag::Flags origin) {
+bool CommandLineFlags::boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_bool()) return false;
@@ -639,7 +639,7 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::intxAt(char* name, size_t len, intx* value) {
+bool CommandLineFlags::intxAt(const char* name, size_t len, intx* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_intx()) return false;
@@ -647,7 +647,7 @@
   return true;
 }
 
-bool CommandLineFlags::intxAtPut(char* name, size_t len, intx* value, Flag::Flags origin) {
+bool CommandLineFlags::intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_intx()) return false;
@@ -667,7 +667,7 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::uintxAt(char* name, size_t len, uintx* value) {
+bool CommandLineFlags::uintxAt(const char* name, size_t len, uintx* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_uintx()) return false;
@@ -675,7 +675,7 @@
   return true;
 }
 
-bool CommandLineFlags::uintxAtPut(char* name, size_t len, uintx* value, Flag::Flags origin) {
+bool CommandLineFlags::uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_uintx()) return false;
@@ -695,7 +695,7 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::uint64_tAt(char* name, size_t len, uint64_t* value) {
+bool CommandLineFlags::uint64_tAt(const char* name, size_t len, uint64_t* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_uint64_t()) return false;
@@ -703,7 +703,7 @@
   return true;
 }
 
-bool CommandLineFlags::uint64_tAtPut(char* name, size_t len, uint64_t* value, Flag::Flags origin) {
+bool CommandLineFlags::uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_uint64_t()) return false;
@@ -723,7 +723,7 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::doubleAt(char* name, size_t len, double* value) {
+bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_double()) return false;
@@ -731,7 +731,7 @@
   return true;
 }
 
-bool CommandLineFlags::doubleAtPut(char* name, size_t len, double* value, Flag::Flags origin) {
+bool CommandLineFlags::doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_double()) return false;
@@ -751,7 +751,7 @@
   faddr->set_origin(origin);
 }
 
-bool CommandLineFlags::ccstrAt(char* name, size_t len, ccstr* value) {
+bool CommandLineFlags::ccstrAt(const char* name, size_t len, ccstr* value) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_ccstr()) return false;
@@ -759,9 +759,7 @@
   return true;
 }
 
-// Contract:  Flag will make private copy of the incoming value.
-// Outgoing value is always malloc-ed, and caller MUST call free.
-bool CommandLineFlags::ccstrAtPut(char* name, size_t len, ccstr* value, Flag::Flags origin) {
+bool CommandLineFlags::ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin) {
   Flag* result = Flag::find_flag(name, len);
   if (result == NULL) return false;
   if (!result->is_ccstr()) return false;
@@ -784,7 +782,6 @@
   return true;
 }
 
-// Contract:  Flag will make private copy of the incoming value.
 void CommandLineFlagsEx::ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin) {
   Flag* faddr = address_of_flag(flag);
   guarantee(faddr != NULL && faddr->is_ccstr(), "wrong flag type");
diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp
index fdd6db5..336a861 100644
--- a/hotspot/src/share/vm/runtime/globals.hpp
+++ b/hotspot/src/share/vm/runtime/globals.hpp
@@ -363,35 +363,37 @@
 
 class CommandLineFlags {
  public:
-  static bool boolAt(char* name, size_t len, bool* value);
-  static bool boolAt(char* name, bool* value)      { return boolAt(name, strlen(name), value); }
-  static bool boolAtPut(char* name, size_t len, bool* value, Flag::Flags origin);
-  static bool boolAtPut(char* name, bool* value, Flag::Flags origin)   { return boolAtPut(name, strlen(name), value, origin); }
+  static bool boolAt(const char* name, size_t len, bool* value);
+  static bool boolAt(const char* name, bool* value)      { return boolAt(name, strlen(name), value); }
+  static bool boolAtPut(const char* name, size_t len, bool* value, Flag::Flags origin);
+  static bool boolAtPut(const char* name, bool* value, Flag::Flags origin)   { return boolAtPut(name, strlen(name), value, origin); }
 
-  static bool intxAt(char* name, size_t len, intx* value);
-  static bool intxAt(char* name, intx* value)      { return intxAt(name, strlen(name), value); }
-  static bool intxAtPut(char* name, size_t len, intx* value, Flag::Flags origin);
-  static bool intxAtPut(char* name, intx* value, Flag::Flags origin)   { return intxAtPut(name, strlen(name), value, origin); }
+  static bool intxAt(const char* name, size_t len, intx* value);
+  static bool intxAt(const char* name, intx* value)      { return intxAt(name, strlen(name), value); }
+  static bool intxAtPut(const char* name, size_t len, intx* value, Flag::Flags origin);
+  static bool intxAtPut(const char* name, intx* value, Flag::Flags origin)   { return intxAtPut(name, strlen(name), value, origin); }
 
-  static bool uintxAt(char* name, size_t len, uintx* value);
-  static bool uintxAt(char* name, uintx* value)    { return uintxAt(name, strlen(name), value); }
-  static bool uintxAtPut(char* name, size_t len, uintx* value, Flag::Flags origin);
-  static bool uintxAtPut(char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
+  static bool uintxAt(const char* name, size_t len, uintx* value);
+  static bool uintxAt(const char* name, uintx* value)    { return uintxAt(name, strlen(name), value); }
+  static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
+  static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
 
-  static bool uint64_tAt(char* name, size_t len, uint64_t* value);
-  static bool uint64_tAt(char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
-  static bool uint64_tAtPut(char* name, size_t len, uint64_t* value, Flag::Flags origin);
-  static bool uint64_tAtPut(char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
+  static bool uint64_tAt(const char* name, size_t len, uint64_t* value);
+  static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
+  static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
+  static bool uint64_tAtPut(const char* name, uint64_t* value, Flag::Flags origin) { return uint64_tAtPut(name, strlen(name), value, origin); }
 
-  static bool doubleAt(char* name, size_t len, double* value);
-  static bool doubleAt(char* name, double* value)    { return doubleAt(name, strlen(name), value); }
-  static bool doubleAtPut(char* name, size_t len, double* value, Flag::Flags origin);
-  static bool doubleAtPut(char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
+  static bool doubleAt(const char* name, size_t len, double* value);
+  static bool doubleAt(const char* name, double* value)    { return doubleAt(name, strlen(name), value); }
+  static bool doubleAtPut(const char* name, size_t len, double* value, Flag::Flags origin);
+  static bool doubleAtPut(const char* name, double* value, Flag::Flags origin) { return doubleAtPut(name, strlen(name), value, origin); }
 
-  static bool ccstrAt(char* name, size_t len, ccstr* value);
-  static bool ccstrAt(char* name, ccstr* value)    { return ccstrAt(name, strlen(name), value); }
-  static bool ccstrAtPut(char* name, size_t len, ccstr* value, Flag::Flags origin);
-  static bool ccstrAtPut(char* name, ccstr* value, Flag::Flags origin) { return ccstrAtPut(name, strlen(name), value, origin); }
+  static bool ccstrAt(const char* name, size_t len, ccstr* value);
+  static bool ccstrAt(const char* name, ccstr* value)    { return ccstrAt(name, strlen(name), value); }
+  // Contract:  Flag will make private copy of the incoming value.
+  // Outgoing value is always malloc-ed, and caller MUST call free.
+  static bool ccstrAtPut(const char* name, size_t len, ccstr* value, Flag::Flags origin);
+  static bool ccstrAtPut(const char* name, ccstr* value, Flag::Flags origin) { return ccstrAtPut(name, strlen(name), value, origin); }
 
   // Returns false if name is not a command line flag.
   static bool wasSetOnCmdline(const char* name, bool* value);
@@ -595,6 +597,9 @@
   product(bool, UseAES, false,                                              \
           "Control whether AES instructions can be used on x86/x64")        \
                                                                             \
+  product(bool, UseSHA, false,                                              \
+          "Control whether SHA instructions can be used on SPARC")          \
+                                                                            \
   product(uintx, LargePageSizeInBytes, 0,                                   \
           "Large page size (0 to let VM choose the page size)")             \
                                                                             \
@@ -701,6 +706,15 @@
   product(bool, UseAESIntrinsics, false,                                    \
           "Use intrinsics for AES versions of crypto")                      \
                                                                             \
+  product(bool, UseSHA1Intrinsics, false,                                   \
+          "Use intrinsics for SHA-1 crypto hash function")                  \
+                                                                            \
+  product(bool, UseSHA256Intrinsics, false,                                 \
+          "Use intrinsics for SHA-224 and SHA-256 crypto hash functions")   \
+                                                                            \
+  product(bool, UseSHA512Intrinsics, false,                                 \
+          "Use intrinsics for SHA-384 and SHA-512 crypto hash functions")   \
+                                                                            \
   product(bool, UseCRC32Intrinsics, false,                                  \
           "use intrinsics for java.util.zip.CRC32")                         \
                                                                             \
@@ -929,11 +943,6 @@
   diagnostic(bool, PrintNMTStatistics, false,                               \
           "Print native memory tracking summary data if it is on")          \
                                                                             \
-  diagnostic(bool, AutoShutdownNMT, true,                                   \
-          "Automatically shutdown native memory tracking under stress "     \
-          "situations. When set to false, native memory tracking tries to " \
-          "stay alive at the expense of JVM performance")                   \
-                                                                            \
   diagnostic(bool, LogCompilation, false,                                   \
           "Log compilation activity in detail to LogFile")                  \
                                                                             \
@@ -1062,6 +1071,9 @@
   product(bool, ClassUnloading, true,                                       \
           "Do unloading of classes")                                        \
                                                                             \
+  product(bool, ClassUnloadingWithConcurrentMark, true,                     \
+          "Do unloading of classes with a concurrent marking cycle")        \
+                                                                            \
   develop(bool, DisableStartThread, false,                                  \
           "Disable starting of additional Java threads "                    \
           "(for debugging only)")                                           \
@@ -1199,6 +1211,11 @@
   product(bool, UseFastJNIAccessors, true,                                  \
           "Use optimized versions of Get<Primitive>Field")                  \
                                                                             \
+  product(intx, MaxJNILocalCapacity, 65536,                                 \
+          "Maximum allowable local JNI handle capacity to "                 \
+          "EnsureLocalCapacity() and PushLocalFrame(), "                    \
+          "where <= 0 is unlimited, default: 65536")                        \
+                                                                            \
   product(bool, EagerXrunInit, false,                                       \
           "Eagerly initialize -Xrun libraries; allows startup profiling, "  \
           "but not all -Xrun libraries may support the state of the VM "    \
@@ -1923,6 +1940,10 @@
           "not just one of the generations (e.g., G1). A value of 0 "       \
           "denotes 'do constant GC cycles'.")                               \
                                                                             \
+  manageable(intx, CMSTriggerInterval, -1,                                  \
+          "Commence a CMS collection cycle (at least) every so many "       \
+          "milliseconds (0 permanently, -1 disabled)")                      \
+                                                                            \
   product(bool, UseCMSInitiatingOccupancyOnly, false,                       \
           "Only use occupancy as a criterion for starting a CMS collection")\
                                                                             \
@@ -2287,6 +2308,9 @@
   manageable(bool, PrintGCTimeStamps, false,                                \
           "Print timestamps at garbage collection")                         \
                                                                             \
+  manageable(bool, PrintGCID, false,                                        \
+          "Print an identifier for each garbage collection")                \
+                                                                            \
   product(bool, PrintGCTaskTimeStamps, false,                               \
           "Print timestamps for individual gc worker thread tasks")         \
                                                                             \
@@ -3865,6 +3889,9 @@
   product(bool, PrintGCCause, true,                                         \
           "Include GC cause in GC logging")                                 \
                                                                             \
+  experimental(intx, SurvivorAlignmentInBytes, 0,                           \
+           "Default survivor space alignment in bytes")                     \
+                                                                            \
   product(bool , AllowNonVirtualCalls, false,                               \
           "Obey the ACC_SUPER flag and allow invokenonvirtual calls")       \
                                                                             \
diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp
index 9d8e388..b746beb 100644
--- a/hotspot/src/share/vm/runtime/globals_extension.hpp
+++ b/hotspot/src/share/vm/runtime/globals_extension.hpp
@@ -201,6 +201,7 @@
   static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin);
   static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin);
   static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin);
+  // Contract:  Flag will make private copy of the incoming value
   static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin);
 
   static bool is_default(CommandLineFlag flag);
diff --git a/hotspot/src/share/vm/runtime/handles.hpp b/hotspot/src/share/vm/runtime/handles.hpp
index c2ce4b3..8f3d6c1 100644
--- a/hotspot/src/share/vm/runtime/handles.hpp
+++ b/hotspot/src/share/vm/runtime/handles.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -227,7 +227,7 @@
   HandleArea* _prev;          // link to outer (older) area
  public:
   // Constructor
-  HandleArea(HandleArea* prev) : Arena(Chunk::tiny_size) {
+  HandleArea(HandleArea* prev) : Arena(mtThread, Chunk::tiny_size) {
     debug_only(_handle_mark_nesting    = 0);
     debug_only(_no_handle_mark_nesting = 0);
     _prev = prev;
diff --git a/hotspot/src/share/vm/runtime/init.cpp b/hotspot/src/share/vm/runtime/init.cpp
index 4533c7e..1512ccc 100644
--- a/hotspot/src/share/vm/runtime/init.cpp
+++ b/hotspot/src/share/vm/runtime/init.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -34,8 +34,10 @@
 #include "runtime/init.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/sharedRuntime.hpp"
+#include "services/memTracker.hpp"
 #include "utilities/macros.hpp"
 
+
 // Initialization done by VM thread in vm_init_globals()
 void check_ThreadShadow();
 void eventlog_init();
@@ -131,6 +133,12 @@
   javaClasses_init();   // must happen after vtable initialization
   stubRoutines_init2(); // note: StubRoutines need 2-phase init
 
+#if INCLUDE_NMT
+  // Solaris stack is walkable only after stubRoutines are set up.
+  // On Other platforms, the stack is always walkable.
+  NMT_stack_walkable = true;
+#endif // INCLUDE_NMT
+
   // All the flags that get adjusted by VM_Version_init and os::init_2
   // have been set so dump the flags now.
   if (PrintFlagsFinal) {
diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.cpp b/hotspot/src/share/vm/runtime/interfaceSupport.cpp
index b30d2f8..0975715 100644
--- a/hotspot/src/share/vm/runtime/interfaceSupport.cpp
+++ b/hotspot/src/share/vm/runtime/interfaceSupport.cpp
@@ -30,6 +30,7 @@
 #include "memory/resourceArea.hpp"
 #include "runtime/init.hpp"
 #include "runtime/interfaceSupport.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/threadLocalStorage.hpp"
 #include "runtime/vframe.hpp"
 #include "utilities/preserveException.hpp"
diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp
index 902d946..f1444d4 100644
--- a/hotspot/src/share/vm/runtime/java.cpp
+++ b/hotspot/src/share/vm/runtime/java.cpp
@@ -57,7 +57,6 @@
 #include "runtime/thread.inline.hpp"
 #include "runtime/timer.hpp"
 #include "runtime/vm_operations.hpp"
-#include "services/memReporter.hpp"
 #include "services/memTracker.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/dtrace.hpp"
@@ -364,12 +363,7 @@
 #endif // ENABLE_ZAP_DEAD_LOCALS
   // Native memory tracking data
   if (PrintNMTStatistics) {
-    if (MemTracker::is_on()) {
-      BaselineTTYOutputer outputer(tty);
-      MemTracker::print_memory_usage(outputer, K, false);
-    } else {
-      tty->print_cr("%s", MemTracker::reason());
-    }
+    MemTracker::final_report(tty);
   }
 }
 
@@ -401,12 +395,7 @@
 
   // Native memory tracking data
   if (PrintNMTStatistics) {
-    if (MemTracker::is_on()) {
-      BaselineTTYOutputer outputer(tty);
-      MemTracker::print_memory_usage(outputer, K, false);
-    } else {
-      tty->print_cr("%s", MemTracker::reason());
-    }
+    MemTracker::final_report(tty);
   }
 }
 
@@ -555,10 +544,6 @@
     BeforeExit_lock->notify_all();
   }
 
-  // Shutdown NMT before exit. Otherwise,
-  // it will run into trouble when system destroys static variables.
-  MemTracker::shutdown(MemTracker::NMT_normal);
-
   if (VerifyStringTableAtExit) {
     int fail_cnt = 0;
     {
diff --git a/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp b/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp
index f634092..02d2eec 100644
--- a/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp
+++ b/hotspot/src/share/vm/runtime/javaFrameAnchor.hpp
@@ -26,39 +26,7 @@
 #define SHARE_VM_RUNTIME_JAVAFRAMEANCHOR_HPP
 
 #include "utilities/globalDefinitions.hpp"
-#ifdef TARGET_OS_ARCH_linux_x86
-# include "orderAccess_linux_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_sparc
-# include "orderAccess_linux_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_zero
-# include "orderAccess_linux_zero.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_x86
-# include "orderAccess_solaris_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_sparc
-# include "orderAccess_solaris_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_windows_x86
-# include "orderAccess_windows_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_arm
-# include "orderAccess_linux_arm.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_ppc
-# include "orderAccess_linux_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_aix_ppc
-# include "orderAccess_aix_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_x86
-# include "orderAccess_bsd_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_zero
-# include "orderAccess_bsd_zero.inline.hpp"
-#endif
+#include "runtime/orderAccess.inline.hpp"
 
 //
 // An object for encapsulating the machine/os dependent part of a JavaThread frame state
diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp
index 19be8e8..5973e4f 100644
--- a/hotspot/src/share/vm/runtime/mutex.cpp
+++ b/hotspot/src/share/vm/runtime/mutex.cpp
@@ -25,6 +25,7 @@
 
 #include "precompiled.hpp"
 #include "runtime/mutex.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/thread.inline.hpp"
 #include "utilities/events.hpp"
diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp
index a798bd8..136bc4d 100644
--- a/hotspot/src/share/vm/runtime/mutexLocker.cpp
+++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp
@@ -69,7 +69,7 @@
 Monitor* SerializePage_lock           = NULL;
 Monitor* Threads_lock                 = NULL;
 Monitor* CGC_lock                     = NULL;
-Mutex*   STS_init_lock                = NULL;
+Monitor* STS_lock                     = NULL;
 Monitor* SLT_lock                     = NULL;
 Monitor* iCMS_lock                    = NULL;
 Monitor* FullGCCount_lock             = NULL;
@@ -173,7 +173,7 @@
   def(tty_lock                     , Mutex  , event,       true ); // allow to lock in VM
 
   def(CGC_lock                   , Monitor, special,     true ); // coordinate between fore- and background GC
-  def(STS_init_lock              , Mutex,   leaf,        true );
+  def(STS_lock                   , Monitor, leaf,        true );
   if (UseConcMarkSweepGC) {
     def(iCMS_lock                  , Monitor, special,     true ); // CMS incremental mode start/stop notification
   }
diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp
index 6f581a0..0aa19a3 100644
--- a/hotspot/src/share/vm/runtime/mutexLocker.hpp
+++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp
@@ -79,7 +79,7 @@
                                                  // (also used by Safepoints too to block threads creation/destruction)
 extern Monitor* CGC_lock;                        // used for coordination between
                                                  // fore- & background GC threads.
-extern Mutex*   STS_init_lock;                   // coordinate initialization of SuspendibleThreadSets.
+extern Monitor* STS_lock;                        // used for joining/leaving SuspendibleThreadSet.
 extern Monitor* SLT_lock;                        // used in CMS GC for acquiring PLL
 extern Monitor* iCMS_lock;                       // CMS incremental mode start/stop notification
 extern Monitor* FullGCCount_lock;                // in support of "concurrent" full gc
diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp
index 5c8f6cc..20fe5e8 100644
--- a/hotspot/src/share/vm/runtime/objectMonitor.cpp
+++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp
@@ -32,6 +32,7 @@
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
 #include "runtime/objectMonitor.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
diff --git a/hotspot/src/share/vm/runtime/orderAccess.inline.hpp b/hotspot/src/share/vm/runtime/orderAccess.inline.hpp
new file mode 100644
index 0000000..4fdd50d
--- /dev/null
+++ b/hotspot/src/share/vm/runtime/orderAccess.inline.hpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 SAP AG. 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP
+#define SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP
+
+#include "runtime/orderAccess.hpp"
+
+// Linux
+#ifdef TARGET_OS_ARCH_linux_x86
+# include "orderAccess_linux_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_sparc
+# include "orderAccess_linux_sparc.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_zero
+# include "orderAccess_linux_zero.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_arm
+# include "orderAccess_linux_arm.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_ppc
+# include "orderAccess_linux_ppc.inline.hpp"
+#endif
+
+// Solaris
+#ifdef TARGET_OS_ARCH_solaris_x86
+# include "orderAccess_solaris_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_solaris_sparc
+# include "orderAccess_solaris_sparc.inline.hpp"
+#endif
+
+// Windows
+#ifdef TARGET_OS_ARCH_windows_x86
+# include "orderAccess_windows_x86.inline.hpp"
+#endif
+
+// AIX
+#ifdef TARGET_OS_ARCH_aix_ppc
+# include "orderAccess_aix_ppc.inline.hpp"
+#endif
+
+// BSD
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "orderAccess_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "orderAccess_bsd_zero.inline.hpp"
+#endif
+
+#endif // SHARE_VM_RUNTIME_ORDERACCESS_INLINE_HPP
diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp
index c1f9b5a..e8cdd1c 100644
--- a/hotspot/src/share/vm/runtime/os.cpp
+++ b/hotspot/src/share/vm/runtime/os.cpp
@@ -32,6 +32,9 @@
 #include "gc_implementation/shared/vmGCOperations.hpp"
 #include "interpreter/interpreter.hpp"
 #include "memory/allocation.inline.hpp"
+#ifdef ASSERT
+#include "memory/guardedMemory.hpp"
+#endif
 #include "oops/oop.inline.hpp"
 #include "prims/jvm.h"
 #include "prims/jvm_misc.hpp"
@@ -46,6 +49,7 @@
 #include "runtime/stubRoutines.hpp"
 #include "runtime/thread.inline.hpp"
 #include "services/attachListener.hpp"
+#include "services/nmtCommon.hpp"
 #include "services/memTracker.hpp"
 #include "services/threadService.hpp"
 #include "utilities/defaultStream.hpp"
@@ -524,118 +528,16 @@
 
 
 
-#ifdef ASSERT
-#define space_before             (MallocCushion + sizeof(double))
-#define space_after              MallocCushion
-#define size_addr_from_base(p)   (size_t*)(p + space_before - sizeof(size_t))
-#define size_addr_from_obj(p)    ((size_t*)p - 1)
-// MallocCushion: size of extra cushion allocated around objects with +UseMallocOnly
-// NB: cannot be debug variable, because these aren't set from the command line until
-// *after* the first few allocs already happened
-#define MallocCushion            16
-#else
-#define space_before             0
-#define space_after              0
-#define size_addr_from_base(p)   should not use w/o ASSERT
-#define size_addr_from_obj(p)    should not use w/o ASSERT
-#define MallocCushion            0
-#endif
 #define paranoid                 0  /* only set to 1 if you suspect checking code has bug */
 
 #ifdef ASSERT
-inline size_t get_size(void* obj) {
-  size_t size = *size_addr_from_obj(obj);
-  if (size < 0) {
-    fatal(err_msg("free: size field of object #" PTR_FORMAT " was overwritten ("
-                  SIZE_FORMAT ")", obj, size));
-  }
-  return size;
-}
-
-u_char* find_cushion_backwards(u_char* start) {
-  u_char* p = start;
-  while (p[ 0] != badResourceValue || p[-1] != badResourceValue ||
-         p[-2] != badResourceValue || p[-3] != badResourceValue) p--;
-  // ok, we have four consecutive marker bytes; find start
-  u_char* q = p - 4;
-  while (*q == badResourceValue) q--;
-  return q + 1;
-}
-
-u_char* find_cushion_forwards(u_char* start) {
-  u_char* p = start;
-  while (p[0] != badResourceValue || p[1] != badResourceValue ||
-         p[2] != badResourceValue || p[3] != badResourceValue) p++;
-  // ok, we have four consecutive marker bytes; find end of cushion
-  u_char* q = p + 4;
-  while (*q == badResourceValue) q++;
-  return q - MallocCushion;
-}
-
-void print_neighbor_blocks(void* ptr) {
-  // find block allocated before ptr (not entirely crash-proof)
-  if (MallocCushion < 4) {
-    tty->print_cr("### cannot find previous block (MallocCushion < 4)");
-    return;
-  }
-  u_char* start_of_this_block = (u_char*)ptr - space_before;
-  u_char* end_of_prev_block_data = start_of_this_block - space_after -1;
-  // look for cushion in front of prev. block
-  u_char* start_of_prev_block = find_cushion_backwards(end_of_prev_block_data);
-  ptrdiff_t size = *size_addr_from_base(start_of_prev_block);
-  u_char* obj = start_of_prev_block + space_before;
-  if (size <= 0 ) {
-    // start is bad; mayhave been confused by OS data inbetween objects
-    // search one more backwards
-    start_of_prev_block = find_cushion_backwards(start_of_prev_block);
-    size = *size_addr_from_base(start_of_prev_block);
-    obj = start_of_prev_block + space_before;
-  }
-
-  if (start_of_prev_block + space_before + size + space_after == start_of_this_block) {
-    tty->print_cr("### previous object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size);
-  } else {
-    tty->print_cr("### previous object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", obj, size);
-  }
-
-  // now find successor block
-  u_char* start_of_next_block = (u_char*)ptr + *size_addr_from_obj(ptr) + space_after;
-  start_of_next_block = find_cushion_forwards(start_of_next_block);
-  u_char* next_obj = start_of_next_block + space_before;
-  ptrdiff_t next_size = *size_addr_from_base(start_of_next_block);
-  if (start_of_next_block[0] == badResourceValue &&
-      start_of_next_block[1] == badResourceValue &&
-      start_of_next_block[2] == badResourceValue &&
-      start_of_next_block[3] == badResourceValue) {
-    tty->print_cr("### next object: " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size);
-  } else {
-    tty->print_cr("### next object (not sure if correct): " PTR_FORMAT " (" SSIZE_FORMAT " bytes)", next_obj, next_size);
-  }
-}
-
-
-void report_heap_error(void* memblock, void* bad, const char* where) {
-  tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
-  tty->print_cr("## memory stomp: byte at " PTR_FORMAT " %s object " PTR_FORMAT, bad, where, memblock);
-  print_neighbor_blocks(memblock);
-  fatal("memory stomping error");
-}
-
-void verify_block(void* memblock) {
-  size_t size = get_size(memblock);
-  if (MallocCushion) {
-    u_char* ptr = (u_char*)memblock - space_before;
-    for (int i = 0; i < MallocCushion; i++) {
-      if (ptr[i] != badResourceValue) {
-        report_heap_error(memblock, ptr+i, "in front of");
-      }
-    }
-    u_char* end = (u_char*)memblock + size + space_after;
-    for (int j = -MallocCushion; j < 0; j++) {
-      if (end[j] != badResourceValue) {
-        report_heap_error(memblock, end+j, "after");
-      }
-    }
+static void verify_memory(void* ptr) {
+  GuardedMemory guarded(ptr);
+  if (!guarded.verify_guards()) {
+    tty->print_cr("## nof_mallocs = " UINT64_FORMAT ", nof_frees = " UINT64_FORMAT, os::num_mallocs, os::num_frees);
+    tty->print_cr("## memory stomp:");
+    guarded.print_on(tty);
+    fatal("memory stomping error");
   }
 }
 #endif
@@ -660,7 +562,11 @@
   return ptr;
 }
 
-void* os::malloc(size_t size, MEMFLAGS memflags, address caller) {
+void* os::malloc(size_t size, MEMFLAGS flags) {
+  return os::malloc(size, flags, CALLER_PC);
+}
+
+void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
   NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
   NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
 
@@ -686,16 +592,22 @@
     size = 1;
   }
 
-  const size_t alloc_size = size + space_before + space_after;
+  // NMT support
+  NMT_TrackingLevel level = MemTracker::tracking_level();
+  size_t            nmt_header_size = MemTracker::malloc_header_size(level);
 
-  if (size > alloc_size) { // Check for rollover.
+#ifndef ASSERT
+  const size_t alloc_size = size + nmt_header_size;
+#else
+  const size_t alloc_size = GuardedMemory::get_total_size(size + nmt_header_size);
+  if (size + nmt_header_size > alloc_size) { // Check for rollover.
     return NULL;
   }
+#endif
 
   NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
 
   u_char* ptr;
-
   if (MallocMaxTestWords > 0) {
     ptr = testMalloc(alloc_size);
   } else {
@@ -703,67 +615,72 @@
   }
 
 #ifdef ASSERT
-  if (ptr == NULL) return NULL;
-  if (MallocCushion) {
-    for (u_char* p = ptr; p < ptr + MallocCushion; p++) *p = (u_char)badResourceValue;
-    u_char* end = ptr + space_before + size;
-    for (u_char* pq = ptr+MallocCushion; pq < end; pq++) *pq = (u_char)uninitBlockPad;
-    for (u_char* q = end; q < end + MallocCushion; q++) *q = (u_char)badResourceValue;
+  if (ptr == NULL) {
+    return NULL;
   }
-  // put size just before data
-  *size_addr_from_base(ptr) = size;
+  // Wrap memory with guard
+  GuardedMemory guarded(ptr, size + nmt_header_size);
+  ptr = guarded.get_user_ptr();
 #endif
-  u_char* memblock = ptr + space_before;
-  if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
-    tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
+  if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
+    tty->print_cr("os::malloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
     breakpoint();
   }
-  debug_only(if (paranoid) verify_block(memblock));
-  if (PrintMalloc && tty != NULL) tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, memblock);
+  debug_only(if (paranoid) verify_memory(ptr));
+  if (PrintMalloc && tty != NULL) {
+    tty->print_cr("os::malloc " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
+  }
 
-  // we do not track MallocCushion memory
-    MemTracker::record_malloc((address)memblock, size, memflags, caller == 0 ? CALLER_PC : caller);
-
-  return memblock;
+  // we do not track guard memory
+  return MemTracker::record_malloc((address)ptr, size, memflags, stack, level);
 }
 
+void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) {
+  return os::realloc(memblock, size, flags, CALLER_PC);
+}
 
-void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, address caller) {
+void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
 #ifndef ASSERT
   NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
   NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
-  MemTracker::Tracker tkr = MemTracker::get_realloc_tracker();
-  void* ptr = ::realloc(memblock, size);
-  if (ptr != NULL) {
-    tkr.record((address)memblock, (address)ptr, size, memflags,
-     caller == 0 ? CALLER_PC : caller);
-  } else {
-    tkr.discard();
-  }
-  return ptr;
+   // NMT support
+  void* membase = MemTracker::record_free(memblock);
+  NMT_TrackingLevel level = MemTracker::tracking_level();
+  size_t  nmt_header_size = MemTracker::malloc_header_size(level);
+  void* ptr = ::realloc(membase, size + nmt_header_size);
+  return MemTracker::record_malloc(ptr, size, memflags, stack, level);
 #else
   if (memblock == NULL) {
-    return malloc(size, memflags, (caller == 0 ? CALLER_PC : caller));
+    return os::malloc(size, memflags, stack);
   }
   if ((intptr_t)memblock == (intptr_t)MallocCatchPtr) {
     tty->print_cr("os::realloc caught " PTR_FORMAT, memblock);
     breakpoint();
   }
-  verify_block(memblock);
+  // NMT support
+  void* membase = MemTracker::malloc_base(memblock);
+  verify_memory(membase);
   NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
-  if (size == 0) return NULL;
+  if (size == 0) {
+    return NULL;
+  }
   // always move the block
-  void* ptr = malloc(size, memflags, caller == 0 ? CALLER_PC : caller);
-  if (PrintMalloc) tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
+  void* ptr = os::malloc(size, memflags, stack);
+  if (PrintMalloc) {
+    tty->print_cr("os::remalloc " SIZE_FORMAT " bytes, " PTR_FORMAT " --> " PTR_FORMAT, size, memblock, ptr);
+  }
   // Copy to new memory if malloc didn't fail
   if ( ptr != NULL ) {
-    memcpy(ptr, memblock, MIN2(size, get_size(memblock)));
-    if (paranoid) verify_block(ptr);
+    GuardedMemory guarded(MemTracker::malloc_base(memblock));
+    // Guard's user data contains NMT header
+    size_t memblock_size = guarded.get_user_size() - MemTracker::malloc_header_size(memblock);
+    memcpy(ptr, memblock, MIN2(size, memblock_size));
+    if (paranoid) verify_memory(MemTracker::malloc_base(ptr));
     if ((intptr_t)ptr == (intptr_t)MallocCatchPtr) {
       tty->print_cr("os::realloc caught, " SIZE_FORMAT " bytes --> " PTR_FORMAT, size, ptr);
       breakpoint();
     }
-    free(memblock);
+    os::free(memblock);
   }
   return ptr;
 #endif
@@ -778,34 +695,22 @@
     if (tty != NULL) tty->print_cr("os::free caught " PTR_FORMAT, memblock);
     breakpoint();
   }
-  verify_block(memblock);
+  void* membase = MemTracker::record_free(memblock);
+  verify_memory(membase);
   NOT_PRODUCT(if (MallocVerifyInterval > 0) check_heap());
-  // Added by detlefs.
-  if (MallocCushion) {
-    u_char* ptr = (u_char*)memblock - space_before;
-    for (u_char* p = ptr; p < ptr + MallocCushion; p++) {
-      guarantee(*p == badResourceValue,
-                "Thing freed should be malloc result.");
-      *p = (u_char)freeBlockPad;
-    }
-    size_t size = get_size(memblock);
-    inc_stat_counter(&free_bytes, size);
-    u_char* end = ptr + space_before + size;
-    for (u_char* q = end; q < end + MallocCushion; q++) {
-      guarantee(*q == badResourceValue,
-                "Thing freed should be malloc result.");
-      *q = (u_char)freeBlockPad;
-    }
-    if (PrintMalloc && tty != NULL)
-      fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)memblock);
-  } else if (PrintMalloc && tty != NULL) {
-    // tty->print_cr("os::free %p", memblock);
-    fprintf(stderr, "os::free " PTR_FORMAT "\n", (uintptr_t)memblock);
-  }
-#endif
-  MemTracker::record_free((address)memblock, memflags);
 
-  ::free((char*)memblock - space_before);
+  GuardedMemory guarded(membase);
+  size_t size = guarded.get_user_size();
+  inc_stat_counter(&free_bytes, size);
+  membase = guarded.release_for_freeing();
+  if (PrintMalloc && tty != NULL) {
+      fprintf(stderr, "os::free " SIZE_FORMAT " bytes --> " PTR_FORMAT "\n", size, (uintptr_t)membase);
+  }
+  ::free(membase);
+#else
+  void* membase = MemTracker::record_free(memblock);
+  ::free(membase);
+#endif
 }
 
 void os::init_random(long initval) {
@@ -1519,7 +1424,7 @@
 char* os::reserve_memory(size_t bytes, char* addr, size_t alignment_hint) {
   char* result = pd_reserve_memory(bytes, addr, alignment_hint);
   if (result != NULL) {
-    MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC);
+    MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
   }
 
   return result;
@@ -1529,7 +1434,7 @@
    MEMFLAGS flags) {
   char* result = pd_reserve_memory(bytes, addr, alignment_hint);
   if (result != NULL) {
-    MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC);
+    MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
     MemTracker::record_virtual_memory_type((address)result, flags);
   }
 
@@ -1539,7 +1444,7 @@
 char* os::attempt_reserve_memory_at(size_t bytes, char* addr) {
   char* result = pd_attempt_reserve_memory_at(bytes, addr);
   if (result != NULL) {
-    MemTracker::record_virtual_memory_reserve((address)result, bytes, mtNone, CALLER_PC);
+    MemTracker::record_virtual_memory_reserve((address)result, bytes, CALLER_PC);
   }
   return result;
 }
@@ -1579,23 +1484,29 @@
 }
 
 bool os::uncommit_memory(char* addr, size_t bytes) {
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
-  bool res = pd_uncommit_memory(addr, bytes);
-  if (res) {
-    tkr.record((address)addr, bytes);
+  bool res;
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
+    res = pd_uncommit_memory(addr, bytes);
+    if (res) {
+      tkr.record((address)addr, bytes);
+    }
   } else {
-    tkr.discard();
+    res = pd_uncommit_memory(addr, bytes);
   }
   return res;
 }
 
 bool os::release_memory(char* addr, size_t bytes) {
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
-  bool res = pd_release_memory(addr, bytes);
-  if (res) {
-    tkr.record((address)addr, bytes);
+  bool res;
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+    res = pd_release_memory(addr, bytes);
+    if (res) {
+      tkr.record((address)addr, bytes);
+    }
   } else {
-    tkr.discard();
+    res = pd_release_memory(addr, bytes);
   }
   return res;
 }
@@ -1606,7 +1517,7 @@
                            bool allow_exec) {
   char* result = pd_map_memory(fd, file_name, file_offset, addr, bytes, read_only, allow_exec);
   if (result != NULL) {
-    MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, mtNone, CALLER_PC);
+    MemTracker::record_virtual_memory_reserve_and_commit((address)result, bytes, CALLER_PC);
   }
   return result;
 }
@@ -1619,12 +1530,15 @@
 }
 
 bool os::unmap_memory(char *addr, size_t bytes) {
-  MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
-  bool result = pd_unmap_memory(addr, bytes);
-  if (result) {
-    tkr.record((address)addr, bytes);
+  bool result;
+  if (MemTracker::tracking_level() > NMT_minimal) {
+    Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
+    result = pd_unmap_memory(addr, bytes);
+    if (result) {
+      tkr.record((address)addr, bytes);
+    }
   } else {
-    tkr.discard();
+    result = pd_unmap_memory(addr, bytes);
   }
   return result;
 }
diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp
index a0b6434..f65d1dc 100644
--- a/hotspot/src/share/vm/runtime/os.hpp
+++ b/hotspot/src/share/vm/runtime/os.hpp
@@ -66,6 +66,8 @@
 class Event;
 class DLL;
 class FileHandle;
+class NativeCallStack;
+
 template<class E> class GrowableArray;
 
 // %%%%% Moved ThreadState, START_FN, OSThread to new osThread.hpp. -- Rose
@@ -97,9 +99,11 @@
 // Typedef for structured exception handling support
 typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread);
 
+class MallocTracker;
+
 class os: AllStatic {
   friend class VMStructs;
-
+  friend class MallocTracker;
  public:
   enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel)
 
@@ -161,7 +165,10 @@
   // Override me as needed
   static int    file_name_strcmp(const char* s1, const char* s2);
 
+  // get/unset environment variable
   static bool getenv(const char* name, char* buffer, int len);
+  static bool unsetenv(const char* name);
+
   static bool have_special_privileges();
 
   static jlong  javaTimeMillis();
@@ -207,8 +214,13 @@
 
   // Interface for detecting multiprocessor system
   static inline bool is_MP() {
+#if !INCLUDE_NMT
     assert(_processor_count > 0, "invalid processor count");
     return _processor_count > 1 || AssumeMP;
+#else
+    // NMT needs atomic operations before this initialization.
+    return true;
+#endif
   }
   static julong available_memory();
   static julong physical_memory();
@@ -651,12 +663,20 @@
   static void* thread_local_storage_at(int index);
   static void  free_thread_local_storage(int index);
 
-  // Stack walk
-  static address get_caller_pc(int n = 0);
+  // Retrieve native stack frames.
+  // Parameter:
+  //   stack:  an array to storage stack pointers.
+  //   frames: size of above array.
+  //   toSkip: number of stack frames to skip at the beginning.
+  // Return: number of stack frames captured.
+  static int get_native_stack(address* stack, int size, int toSkip = 0);
 
   // General allocation (must be MT-safe)
-  static void* malloc  (size_t size, MEMFLAGS flags, address caller_pc = 0);
-  static void* realloc (void *memblock, size_t size, MEMFLAGS flags, address caller_pc = 0);
+  static void* malloc  (size_t size, MEMFLAGS flags, const NativeCallStack& stack);
+  static void* malloc  (size_t size, MEMFLAGS flags);
+  static void* realloc (void *memblock, size_t size, MEMFLAGS flag, const NativeCallStack& stack);
+  static void* realloc (void *memblock, size_t size, MEMFLAGS flag);
+
   static void  free    (void *memblock, MEMFLAGS flags = mtNone);
   static bool  check_heap(bool force = false);      // verify C heap integrity
   static char* strdup(const char *, MEMFLAGS flags = mtInternal);  // Like strdup
diff --git a/hotspot/src/share/vm/runtime/perfMemory.cpp b/hotspot/src/share/vm/runtime/perfMemory.cpp
index 51c9322..4eddf2a 100644
--- a/hotspot/src/share/vm/runtime/perfMemory.cpp
+++ b/hotspot/src/share/vm/runtime/perfMemory.cpp
@@ -28,6 +28,7 @@
 #include "runtime/java.hpp"
 #include "runtime/mutex.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 #include "runtime/perfData.hpp"
 #include "runtime/perfMemory.hpp"
diff --git a/hotspot/src/share/vm/runtime/prefetch.inline.hpp b/hotspot/src/share/vm/runtime/prefetch.inline.hpp
new file mode 100644
index 0000000..e147a21
--- /dev/null
+++ b/hotspot/src/share/vm/runtime/prefetch.inline.hpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP
+#define SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP
+
+#include "runtime/prefetch.hpp"
+
+// Linux
+#ifdef TARGET_OS_ARCH_linux_x86
+# include "prefetch_linux_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_sparc
+# include "prefetch_linux_sparc.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_zero
+# include "prefetch_linux_zero.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_arm
+# include "prefetch_linux_arm.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_linux_ppc
+# include "prefetch_linux_ppc.inline.hpp"
+#endif
+
+// Solaris
+#ifdef TARGET_OS_ARCH_solaris_x86
+# include "prefetch_solaris_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_solaris_sparc
+# include "prefetch_solaris_sparc.inline.hpp"
+#endif
+
+// Windows
+#ifdef TARGET_OS_ARCH_windows_x86
+# include "prefetch_windows_x86.inline.hpp"
+#endif
+
+// AIX
+#ifdef TARGET_OS_ARCH_aix_ppc
+# include "prefetch_aix_ppc.inline.hpp"
+#endif
+
+// BSD
+#ifdef TARGET_OS_ARCH_bsd_x86
+# include "prefetch_bsd_x86.inline.hpp"
+#endif
+#ifdef TARGET_OS_ARCH_bsd_zero
+# include "prefetch_bsd_zero.inline.hpp"
+#endif
+
+#endif // SHARE_VM_RUNTIME_PREFETCH_INLINE_HPP
diff --git a/hotspot/src/share/vm/runtime/safepoint.cpp b/hotspot/src/share/vm/runtime/safepoint.cpp
index 6b588f1..52f59be 100644
--- a/hotspot/src/share/vm/runtime/safepoint.cpp
+++ b/hotspot/src/share/vm/runtime/safepoint.cpp
@@ -41,6 +41,7 @@
 #include "runtime/frame.inline.hpp"
 #include "runtime/interfaceSupport.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/signature.hpp"
@@ -49,7 +50,6 @@
 #include "runtime/sweeper.hpp"
 #include "runtime/synchronizer.hpp"
 #include "runtime/thread.inline.hpp"
-#include "services/memTracker.hpp"
 #include "services/runtimeService.hpp"
 #include "utilities/events.hpp"
 #include "utilities/macros.hpp"
@@ -75,7 +75,7 @@
 #endif
 #if INCLUDE_ALL_GCS
 #include "gc_implementation/concurrentMarkSweep/concurrentMarkSweepThread.hpp"
-#include "gc_implementation/shared/concurrentGCThread.hpp"
+#include "gc_implementation/shared/suspendibleThreadSet.hpp"
 #endif // INCLUDE_ALL_GCS
 #ifdef COMPILER1
 #include "c1/c1_globals.hpp"
@@ -112,7 +112,7 @@
     // more-general mechanism below.  DLD (01/05).
     ConcurrentMarkSweepThread::synchronize(false);
   } else if (UseG1GC) {
-    ConcurrentGCThread::safepoint_synchronize();
+    SuspendibleThreadSet::synchronize();
   }
 #endif // INCLUDE_ALL_GCS
 
@@ -488,7 +488,7 @@
   if (UseConcMarkSweepGC) {
     ConcurrentMarkSweepThread::desynchronize(false);
   } else if (UseG1GC) {
-    ConcurrentGCThread::safepoint_desynchronize();
+    SuspendibleThreadSet::desynchronize();
   }
 #endif // INCLUDE_ALL_GCS
   // record this time so VMThread can keep track how much time has elasped
@@ -546,10 +546,6 @@
     TraceTime t7("purging class loader data graph", TraceSafepointCleanupTime);
     ClassLoaderDataGraph::purge_if_needed();
   }
-
-  if (MemTracker::is_on()) {
-    MemTracker::sync();
-  }
 }
 
 
diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp b/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp
new file mode 100644
index 0000000..26c9147
--- /dev/null
+++ b/hotspot/src/share/vm/runtime/sharedRuntimeMath.hpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP
+#define SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP
+
+#include <math.h>
+
+// Used to access the lower/higher 32 bits of a double
+typedef union {
+    double d;
+    struct {
+#ifdef VM_LITTLE_ENDIAN
+      int lo;
+      int hi;
+#else
+      int hi;
+      int lo;
+#endif
+    } split;
+} DoubleIntConv;
+
+static inline int high(double d) {
+  DoubleIntConv x;
+  x.d = d;
+  return x.split.hi;
+}
+
+static inline int low(double d) {
+  DoubleIntConv x;
+  x.d = d;
+  return x.split.lo;
+}
+
+static inline void set_high(double* d, int high) {
+  DoubleIntConv conv;
+  conv.d = *d;
+  conv.split.hi = high;
+  *d = conv.d;
+}
+
+static inline void set_low(double* d, int low) {
+  DoubleIntConv conv;
+  conv.d = *d;
+  conv.split.lo = low;
+  *d = conv.d;
+}
+
+static double copysignA(double x, double y) {
+  DoubleIntConv convX;
+  convX.d = x;
+  convX.split.hi = (convX.split.hi & 0x7fffffff) | (high(y) & 0x80000000);
+  return convX.d;
+}
+
+/*
+ * ====================================================
+ * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved.
+ *
+ * Developed at SunSoft, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+/*
+ * scalbn (double x, int n)
+ * scalbn(x,n) returns x* 2**n  computed by  exponent
+ * manipulation rather than by actually performing an
+ * exponentiation or a multiplication.
+ */
+
+static const double
+two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+hugeX  = 1.0e+300,
+tiny   = 1.0e-300;
+
+static double scalbnA(double x, int n) {
+  int  k,hx,lx;
+  hx = high(x);
+  lx = low(x);
+  k = (hx&0x7ff00000)>>20;              /* extract exponent */
+  if (k==0) {                           /* 0 or subnormal x */
+    if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+    x *= two54;
+    hx = high(x);
+    k = ((hx&0x7ff00000)>>20) - 54;
+    if (n< -50000) return tiny*x;       /*underflow*/
+  }
+  if (k==0x7ff) return x+x;             /* NaN or Inf */
+  k = k+n;
+  if (k > 0x7fe) return hugeX*copysignA(hugeX,x); /* overflow  */
+  if (k > 0) {                          /* normal result */
+    set_high(&x, (hx&0x800fffff)|(k<<20));
+    return x;
+  }
+  if (k <= -54) {
+    if (n > 50000)      /* in case integer overflow in n+k */
+      return hugeX*copysignA(hugeX,x);  /*overflow*/
+    else return tiny*copysignA(tiny,x); /*underflow*/
+  }
+  k += 54;                              /* subnormal result */
+  set_high(&x, (hx&0x800fffff)|(k<<20));
+  return x*twom54;
+}
+
+#endif // SHARE_VM_RUNTIME_SHAREDRUNTIMEMATH_HPP
diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp
index d3a795b..eac4b4b 100644
--- a/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp
+++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrans.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 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
@@ -40,81 +40,11 @@
 // generated; can not figure out how to turn down optimization for one
 // file in the IDE on Windows
 #ifdef WIN32
+# pragma warning( disable: 4748 ) // /GS can not protect parameters and local variables from local buffer overrun because optimizations are disabled in function
 # pragma optimize ( "", off )
 #endif
 
-#include <math.h>
-
-// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles
-// [jk] this is not 100% correct because the float word order may different
-// from the byte order (e.g. on ARM)
-#ifdef VM_LITTLE_ENDIAN
-# define __HI(x) *(1+(int*)&x)
-# define __LO(x) *(int*)&x
-#else
-# define __HI(x) *(int*)&x
-# define __LO(x) *(1+(int*)&x)
-#endif
-
-#if !defined(AIX)
-double copysign(double x, double y) {
-  __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000);
-  return x;
-}
-#endif
-
-/*
- * ====================================================
- * Copyright (c) 1998 Oracle and/or its affiliates. All rights reserved.
- *
- * Developed at SunSoft, a Sun Microsystems, Inc. business.
- * Permission to use, copy, modify, and distribute this
- * software is freely granted, provided that this notice
- * is preserved.
- * ====================================================
- */
-
-/*
- * scalbn (double x, int n)
- * scalbn(x,n) returns x* 2**n  computed by  exponent
- * manipulation rather than by actually performing an
- * exponentiation or a multiplication.
- */
-
-static const double
-two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
-  twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
-  hugeX   = 1.0e+300,
-  tiny   = 1.0e-300;
-
-#if !defined(AIX)
-double scalbn (double x, int n) {
-  int  k,hx,lx;
-  hx = __HI(x);
-  lx = __LO(x);
-  k = (hx&0x7ff00000)>>20;              /* extract exponent */
-  if (k==0) {                           /* 0 or subnormal x */
-    if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
-    x *= two54;
-    hx = __HI(x);
-    k = ((hx&0x7ff00000)>>20) - 54;
-    if (n< -50000) return tiny*x;       /*underflow*/
-  }
-  if (k==0x7ff) return x+x;             /* NaN or Inf */
-  k = k+n;
-  if (k >  0x7fe) return hugeX*copysign(hugeX,x); /* overflow  */
-  if (k > 0)                            /* normal result */
-    {__HI(x) = (hx&0x800fffff)|(k<<20); return x;}
-  if (k <= -54) {
-    if (n > 50000)      /* in case integer overflow in n+k */
-      return hugeX*copysign(hugeX,x);   /*overflow*/
-    else return tiny*copysign(tiny,x);  /*underflow*/
-  }
-  k += 54;                              /* subnormal result */
-  __HI(x) = (hx&0x800fffff)|(k<<20);
-  return x*twom54;
-}
-#endif
+#include "runtime/sharedRuntimeMath.hpp"
 
 /* __ieee754_log(x)
  * Return the logrithm of x
@@ -185,8 +115,8 @@
   int k,hx,i,j;
   unsigned lx;
 
-  hx = __HI(x);               /* high word of x */
-  lx = __LO(x);               /* low  word of x */
+  hx = high(x);               /* high word of x */
+  lx = low(x);                /* low  word of x */
 
   k=0;
   if (hx < 0x00100000) {                   /* x < 2**-1022  */
@@ -194,13 +124,13 @@
       return -two54/zero;             /* log(+-0)=-inf */
     if (hx<0) return (x-x)/zero;   /* log(-#) = NaN */
     k -= 54; x *= two54; /* subnormal number, scale up x */
-    hx = __HI(x);             /* high word of x */
+    hx = high(x);             /* high word of x */
   }
   if (hx >= 0x7ff00000) return x+x;
   k += (hx>>20)-1023;
   hx &= 0x000fffff;
   i = (hx+0x95f64)&0x100000;
-  __HI(x) = hx|(i^0x3ff00000);        /* normalize x or x/2 */
+  set_high(&x, hx|(i^0x3ff00000)); /* normalize x or x/2 */
   k += (i>>20);
   f = x-1.0;
   if((0x000fffff&(2+hx))<3) {  /* |f| < 2**-20 */
@@ -279,8 +209,8 @@
   int i,k,hx;
   unsigned lx;
 
-  hx = __HI(x);       /* high word of x */
-  lx = __LO(x);       /* low word of x */
+  hx = high(x);       /* high word of x */
+  lx = low(x);        /* low word of x */
 
   k=0;
   if (hx < 0x00100000) {                  /* x < 2**-1022  */
@@ -288,14 +218,14 @@
       return -two54/zero;             /* log(+-0)=-inf */
     if (hx<0) return (x-x)/zero;        /* log(-#) = NaN */
     k -= 54; x *= two54; /* subnormal number, scale up x */
-    hx = __HI(x);                /* high word of x */
+    hx = high(x);                /* high word of x */
   }
   if (hx >= 0x7ff00000) return x+x;
   k += (hx>>20)-1023;
   i  = ((unsigned)k&0x80000000)>>31;
   hx = (hx&0x000fffff)|((0x3ff-i)<<20);
   y  = (double)(k+i);
-  __HI(x) = hx;
+  set_high(&x, hx);
   z  = y*log10_2lo + ivln10*__ieee754_log(x);
   return  z+y*log10_2hi;
 }
@@ -390,14 +320,14 @@
   int k=0,xsb;
   unsigned hx;
 
-  hx  = __HI(x);        /* high word of x */
+  hx  = high(x);                /* high word of x */
   xsb = (hx>>31)&1;             /* sign bit of x */
   hx &= 0x7fffffff;             /* high word of |x| */
 
   /* filter out non-finite argument */
   if(hx >= 0x40862E42) {                        /* if |x|>=709.78... */
     if(hx>=0x7ff00000) {
-      if(((hx&0xfffff)|__LO(x))!=0)
+      if(((hx&0xfffff)|low(x))!=0)
         return x+x;             /* NaN */
       else return (xsb==0)? x:0.0;      /* exp(+-inf)={inf,0} */
     }
@@ -428,10 +358,10 @@
   if(k==0)      return one-((x*c)/(c-2.0)-x);
   else          y = one-((lo-(x*c)/(2.0-c))-hi);
   if(k >= -1021) {
-    __HI(y) += (k<<20); /* add k to y's exponent */
+    set_high(&y, high(y) + (k<<20)); /* add k to y's exponent */
     return y;
   } else {
-    __HI(y) += ((k+1000)<<20);/* add k to y's exponent */
+    set_high(&y, high(y) + ((k+1000)<<20)); /* add k to y's exponent */
     return y*twom1000;
   }
 }
@@ -518,8 +448,8 @@
   unsigned lx,ly;
 
   i0 = ((*(int*)&one)>>29)^1; i1=1-i0;
-  hx = __HI(x); lx = __LO(x);
-  hy = __HI(y); ly = __LO(y);
+  hx = high(x); lx = low(x);
+  hy = high(y); ly = low(y);
   ix = hx&0x7fffffff;  iy = hy&0x7fffffff;
 
   /* y==zero: x**0 = 1 */
@@ -619,14 +549,14 @@
     u = ivln2_h*t;      /* ivln2_h has 21 sig. bits */
     v = t*ivln2_l-w*ivln2;
     t1 = u+v;
-    __LO(t1) = 0;
+    set_low(&t1, 0);
     t2 = v-(t1-u);
   } else {
     double ss,s2,s_h,s_l,t_h,t_l;
     n = 0;
     /* take care subnormal number */
     if(ix<0x00100000)
-      {ax *= two53; n -= 53; ix = __HI(ax); }
+      {ax *= two53; n -= 53; ix = high(ax); }
     n  += ((ix)>>20)-0x3ff;
     j  = ix&0x000fffff;
     /* determine interval */
@@ -634,17 +564,17 @@
     if(j<=0x3988E) k=0;         /* |x|<sqrt(3/2) */
     else if(j<0xBB67A) k=1;     /* |x|<sqrt(3)   */
     else {k=0;n+=1;ix -= 0x00100000;}
-    __HI(ax) = ix;
+    set_high(&ax, ix);
 
     /* compute ss = s_h+s_l = (x-1)/(x+1) or (x-1.5)/(x+1.5) */
     u = ax-bp[k];               /* bp[0]=1.0, bp[1]=1.5 */
     v = one/(ax+bp[k]);
     ss = u*v;
     s_h = ss;
-    __LO(s_h) = 0;
+    set_low(&s_h, 0);
     /* t_h=ax+bp[k] High */
     t_h = zeroX;
-    __HI(t_h)=((ix>>1)|0x20000000)+0x00080000+(k<<18);
+    set_high(&t_h, ((ix>>1)|0x20000000)+0x00080000+(k<<18));
     t_l = ax - (t_h-bp[k]);
     s_l = v*((u-s_h*t_h)-s_h*t_l);
     /* compute log(ax) */
@@ -653,32 +583,32 @@
     r += s_l*(s_h+ss);
     s2  = s_h*s_h;
     t_h = 3.0+s2+r;
-    __LO(t_h) = 0;
+    set_low(&t_h, 0);
     t_l = r-((t_h-3.0)-s2);
     /* u+v = ss*(1+...) */
     u = s_h*t_h;
     v = s_l*t_h+t_l*ss;
     /* 2/(3log2)*(ss+...) */
     p_h = u+v;
-    __LO(p_h) = 0;
+    set_low(&p_h, 0);
     p_l = v-(p_h-u);
     z_h = cp_h*p_h;             /* cp_h+cp_l = 2/(3*log2) */
     z_l = cp_l*p_h+p_l*cp+dp_l[k];
     /* log2(ax) = (ss+..)*2/(3*log2) = n + dp_h + z_h + z_l */
     t = (double)n;
     t1 = (((z_h+z_l)+dp_h[k])+t);
-    __LO(t1) = 0;
+    set_low(&t1, 0);
     t2 = z_l-(((t1-t)-dp_h[k])-z_h);
   }
 
   /* split up y into y1+y2 and compute (y1+y2)*(t1+t2) */
   y1  = y;
-  __LO(y1) = 0;
+  set_low(&y1, 0);
   p_l = (y-y1)*t1+y*t2;
   p_h = y1*t1;
   z = p_l+p_h;
-  j = __HI(z);
-  i = __LO(z);
+  j = high(z);
+  i = low(z);
   if (j>=0x40900000) {                          /* z >= 1024 */
     if(((j-0x40900000)|i)!=0)                   /* if z > 1024 */
       return s*hugeX*hugeX;                     /* overflow */
@@ -702,13 +632,13 @@
     n = j+(0x00100000>>(k+1));
     k = ((n&0x7fffffff)>>20)-0x3ff;     /* new k for n */
     t = zeroX;
-    __HI(t) = (n&~(0x000fffff>>k));
+    set_high(&t, (n&~(0x000fffff>>k)));
     n = ((n&0x000fffff)|0x00100000)>>(20-k);
     if(j<0) n = -n;
     p_h -= t;
   }
   t = p_l+p_h;
-  __LO(t) = 0;
+  set_low(&t, 0);
   u = t*lg2_h;
   v = (p_l-(t-p_h))*lg2+t*lg2_l;
   z = u+v;
@@ -717,10 +647,10 @@
   t1  = z - t*(P1+t*(P2+t*(P3+t*(P4+t*P5))));
   r  = (z*t1)/(t1-two)-(w+z*w);
   z  = one-(r-z);
-  j  = __HI(z);
+  j  = high(z);
   j += (n<<20);
-  if((j>>20)<=0) z = scalbn(z,n);       /* subnormal output */
-  else __HI(z) += (n<<20);
+  if((j>>20)<=0) z = scalbnA(z,n);       /* subnormal output */
+  else set_high(&z, high(z) + (n<<20));
   return s*z;
 }
 
diff --git a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp
index a3590df..37880d8 100644
--- a/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp
+++ b/hotspot/src/share/vm/runtime/sharedRuntimeTrig.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 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
@@ -63,63 +63,7 @@
 #define SAFEBUF
 #endif
 
-#include <math.h>
-
-// VM_LITTLE_ENDIAN is #defined appropriately in the Makefiles
-// [jk] this is not 100% correct because the float word order may different
-// from the byte order (e.g. on ARM)
-#ifdef VM_LITTLE_ENDIAN
-# define __HI(x) *(1+(int*)&x)
-# define __LO(x) *(int*)&x
-#else
-# define __HI(x) *(int*)&x
-# define __LO(x) *(1+(int*)&x)
-#endif
-
-static double copysignA(double x, double y) {
-  __HI(x) = (__HI(x)&0x7fffffff)|(__HI(y)&0x80000000);
-  return x;
-}
-
-/*
- * scalbn (double x, int n)
- * scalbn(x,n) returns x* 2**n  computed by  exponent
- * manipulation rather than by actually performing an
- * exponentiation or a multiplication.
- */
-
-static const double
-two54   =  1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
-twom54  =  5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
-hugeX  = 1.0e+300,
-tiny   = 1.0e-300;
-
-static double scalbnA (double x, int n) {
-  int  k,hx,lx;
-  hx = __HI(x);
-  lx = __LO(x);
-  k = (hx&0x7ff00000)>>20;              /* extract exponent */
-  if (k==0) {                           /* 0 or subnormal x */
-    if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
-    x *= two54;
-    hx = __HI(x);
-    k = ((hx&0x7ff00000)>>20) - 54;
-    if (n< -50000) return tiny*x;       /*underflow*/
-  }
-  if (k==0x7ff) return x+x;             /* NaN or Inf */
-  k = k+n;
-  if (k >  0x7fe) return hugeX*copysignA(hugeX,x); /* overflow  */
-  if (k > 0)                            /* normal result */
-    {__HI(x) = (hx&0x800fffff)|(k<<20); return x;}
-  if (k <= -54) {
-    if (n > 50000)      /* in case integer overflow in n+k */
-      return hugeX*copysignA(hugeX,x);  /*overflow*/
-    else return tiny*copysignA(tiny,x); /*underflow*/
-  }
-  k += 54;                              /* subnormal result */
-  __HI(x) = (hx&0x800fffff)|(k<<20);
-  return x*twom54;
-}
+#include "runtime/sharedRuntimeMath.hpp"
 
 /*
  * __kernel_rem_pio2(x,y,e0,nx,prec,ipio2)
@@ -603,7 +547,7 @@
 {
         double z,r,v;
         int ix;
-        ix = __HI(x)&0x7fffffff;        /* high word of x */
+        ix = high(x)&0x7fffffff;                /* high word of x */
         if(ix<0x3e400000)                       /* |x| < 2**-27 */
            {if((int)x==0) return x;}            /* generate inexact */
         z       =  x*x;
@@ -658,9 +602,9 @@
 
 static double __kernel_cos(double x, double y)
 {
-  double a,h,z,r,qx;
+  double a,h,z,r,qx=0;
   int ix;
-  ix = __HI(x)&0x7fffffff;      /* ix = |x|'s high word*/
+  ix = high(x)&0x7fffffff;              /* ix = |x|'s high word*/
   if(ix<0x3e400000) {                   /* if x < 2**27 */
     if(((int)x)==0) return one;         /* generate inexact */
   }
@@ -672,8 +616,8 @@
     if(ix > 0x3fe90000) {               /* x > 0.78125 */
       qx = 0.28125;
     } else {
-      __HI(qx) = ix-0x00200000; /* x/4 */
-      __LO(qx) = 0;
+      set_high(&qx, ix-0x00200000); /* x/4 */
+      set_low(&qx, 0);
     }
     h = 0.5*z-qx;
     a = one-qx;
@@ -738,11 +682,11 @@
 {
   double z,r,v,w,s;
   int ix,hx;
-  hx = __HI(x);   /* high word of x */
+  hx = high(x);           /* high word of x */
   ix = hx&0x7fffffff;     /* high word of |x| */
   if(ix<0x3e300000) {                     /* x < 2**-28 */
     if((int)x==0) {                       /* generate inexact */
-      if (((ix | __LO(x)) | (iy + 1)) == 0)
+      if (((ix | low(x)) | (iy + 1)) == 0)
         return one / fabsd(x);
       else {
         if (iy == 1)
@@ -751,10 +695,10 @@
           double a, t;
 
           z = w = x + y;
-          __LO(z) = 0;
+          set_low(&z, 0);
           v = y - (z - x);
           t = a = -one / w;
-          __LO(t) = 0;
+          set_low(&t, 0);
           s = one + t * z;
           return t + a * (s + t * v);
         }
@@ -789,10 +733,10 @@
     /*  compute -1.0/(x+r) accurately */
     double a,t;
     z  = w;
-    __LO(z) = 0;
+    set_low(&z, 0);
     v  = r-(z - x);     /* z+v = r+x */
     t = a  = -1.0/w;    /* a = -1.0/w */
-    __LO(t) = 0;
+    set_low(&t, 0);
     s  = 1.0+t*z;
     return t+a*(s+t*v);
   }
@@ -841,7 +785,7 @@
   int n, ix;
 
   /* High word of x. */
-  ix = __HI(x);
+  ix = high(x);
 
   /* |x| ~< pi/4 */
   ix &= 0x7fffffff;
@@ -899,7 +843,7 @@
   int n, ix;
 
   /* High word of x. */
-  ix = __HI(x);
+  ix = high(x);
 
   /* |x| ~< pi/4 */
   ix &= 0x7fffffff;
@@ -956,7 +900,7 @@
   int n, ix;
 
   /* High word of x. */
-  ix = __HI(x);
+  ix = high(x);
 
   /* |x| ~< pi/4 */
   ix &= 0x7fffffff;
diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp
index ff12ca6..6febb5b 100644
--- a/hotspot/src/share/vm/runtime/stubRoutines.cpp
+++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -125,6 +125,13 @@
 address StubRoutines::_cipherBlockChaining_encryptAESCrypt = NULL;
 address StubRoutines::_cipherBlockChaining_decryptAESCrypt = NULL;
 
+address StubRoutines::_sha1_implCompress     = NULL;
+address StubRoutines::_sha1_implCompressMB   = NULL;
+address StubRoutines::_sha256_implCompress   = NULL;
+address StubRoutines::_sha256_implCompressMB = NULL;
+address StubRoutines::_sha512_implCompress   = NULL;
+address StubRoutines::_sha512_implCompressMB = NULL;
+
 address StubRoutines::_updateBytesCRC32 = NULL;
 address StubRoutines::_crc_table_adr = NULL;
 
diff --git a/hotspot/src/share/vm/runtime/stubRoutines.hpp b/hotspot/src/share/vm/runtime/stubRoutines.hpp
index 9548ede..7838116 100644
--- a/hotspot/src/share/vm/runtime/stubRoutines.hpp
+++ b/hotspot/src/share/vm/runtime/stubRoutines.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 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
@@ -207,6 +207,13 @@
   static address _cipherBlockChaining_encryptAESCrypt;
   static address _cipherBlockChaining_decryptAESCrypt;
 
+  static address _sha1_implCompress;
+  static address _sha1_implCompressMB;
+  static address _sha256_implCompress;
+  static address _sha256_implCompressMB;
+  static address _sha512_implCompress;
+  static address _sha512_implCompressMB;
+
   static address _updateBytesCRC32;
   static address _crc_table_adr;
 
@@ -356,6 +363,13 @@
   static address cipherBlockChaining_encryptAESCrypt()  { return _cipherBlockChaining_encryptAESCrypt; }
   static address cipherBlockChaining_decryptAESCrypt()  { return _cipherBlockChaining_decryptAESCrypt; }
 
+  static address sha1_implCompress()     { return _sha1_implCompress; }
+  static address sha1_implCompressMB()   { return _sha1_implCompressMB; }
+  static address sha256_implCompress()   { return _sha256_implCompress; }
+  static address sha256_implCompressMB() { return _sha256_implCompressMB; }
+  static address sha512_implCompress()   { return _sha512_implCompress; }
+  static address sha512_implCompressMB() { return _sha512_implCompressMB; }
+
   static address updateBytesCRC32()    { return _updateBytesCRC32; }
   static address crc_table_addr()      { return _crc_table_adr; }
 
diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp
index bb5ebaf..4eba81d 100644
--- a/hotspot/src/share/vm/runtime/sweeper.cpp
+++ b/hotspot/src/share/vm/runtime/sweeper.cpp
@@ -33,8 +33,10 @@
 #include "runtime/atomic.hpp"
 #include "runtime/compilationPolicy.hpp"
 #include "runtime/mutexLocker.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/os.hpp"
 #include "runtime/sweeper.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vm_operations.hpp"
 #include "trace/tracing.hpp"
 #include "utilities/events.hpp"
diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp
index 8e47964..95e6a36 100644
--- a/hotspot/src/share/vm/runtime/thread.cpp
+++ b/hotspot/src/share/vm/runtime/thread.cpp
@@ -58,6 +58,7 @@
 #include "runtime/memprofiler.hpp"
 #include "runtime/mutexLocker.hpp"
 #include "runtime/objectMonitor.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "runtime/osThread.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/sharedRuntime.hpp"
@@ -330,8 +331,7 @@
 #if INCLUDE_NMT
   // record thread's native stack, stack grows downward
   address stack_low_addr = stack_base() - stack_size();
-  MemTracker::record_thread_stack(stack_low_addr, stack_size(), this,
-      CURRENT_PC);
+  MemTracker::record_thread_stack(stack_low_addr, stack_size());
 #endif // INCLUDE_NMT
 }
 
@@ -349,7 +349,7 @@
 #if INCLUDE_NMT
   if (_stack_base != NULL) {
     address low_stack_addr = stack_base() - stack_size();
-    MemTracker::release_thread_stack(low_stack_addr, stack_size(), this);
+    MemTracker::release_thread_stack(low_stack_addr, stack_size());
 #ifdef ASSERT
     set_stack_base(NULL);
 #endif
@@ -833,7 +833,7 @@
   return false;
 }
 
-void Thread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) {
+void Thread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   active_handles()->oops_do(f);
   // Do oop for ThreadShadow
   f->do_oop((oop*)&_pending_exception);
@@ -1441,9 +1441,6 @@
   set_monitor_chunks(NULL);
   set_next(NULL);
   set_thread_state(_thread_new);
-#if INCLUDE_NMT
-  set_recorder(NULL);
-#endif
   _terminated = _not_terminated;
   _privileged_stack_top = NULL;
   _array_for_gc = NULL;
@@ -1518,7 +1515,6 @@
     _jni_attach_state = _not_attaching_via_jni;
   }
   assert(deferred_card_mark().is_empty(), "Default MemRegion ctor");
-  _safepoint_visible = false;
 }
 
 bool JavaThread::reguard_stack(address cur_sp) {
@@ -1581,7 +1577,6 @@
   thr_type = entry_point == &compiler_thread_entry ? os::compiler_thread :
                                                      os::java_thread;
   os::create_thread(this, thr_type, stack_sz);
-  _safepoint_visible = false;
   // The _osthread may be NULL here because we ran out of memory (too many threads active).
   // We need to throw and OutOfMemoryError - however we cannot do this here because the caller
   // may hold a lock and all locks must be unlocked before throwing the exception (throwing
@@ -1599,13 +1594,6 @@
       tty->print_cr("terminate thread %p", this);
   }
 
-  // By now, this thread should already be invisible to safepoint,
-  // and its per-thread recorder also collected.
-  assert(!is_safepoint_visible(), "wrong state");
-#if INCLUDE_NMT
-  assert(get_recorder() == NULL, "Already collected");
-#endif // INCLUDE_NMT
-
   // JSR166 -- return the parker to the free list
   Parker::Release(_parker);
   _parker = NULL ;
@@ -2729,7 +2717,7 @@
   }
 };
 
-void JavaThread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) {
+void JavaThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   // Verify that the deferred card marks have been flushed.
   assert(deferred_card_mark().is_empty(), "Should be empty during GC");
 
@@ -3252,7 +3240,7 @@
 #endif
 }
 
-void CompilerThread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) {
+void CompilerThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   JavaThread::oops_do(f, cld_f, cf);
   if (_scanned_nmethod != NULL && cf != NULL) {
     // Safepoints can occur when the sweeper is scanning an nmethod so
@@ -3369,11 +3357,6 @@
   // intialize TLS
   ThreadLocalStorage::init();
 
-  // Bootstrap native memory tracking, so it can start recording memory
-  // activities before worker thread is started. This is the first phase
-  // of bootstrapping, VM is currently running in single-thread mode.
-  MemTracker::bootstrap_single_thread();
-
   // Initialize output stream logging
   ostream_init_log();
 
@@ -3424,9 +3407,6 @@
   // Initialize Java-Level synchronization subsystem
   ObjectMonitor::Initialize() ;
 
-  // Second phase of bootstrapping, VM is about entering multi-thread mode
-  MemTracker::bootstrap_multi_thread();
-
   // Initialize global modules
   jint status = init_globals();
   if (status != JNI_OK) {
@@ -3448,9 +3428,6 @@
   // real raw monitor. VM is setup enough here for raw monitor enter.
   JvmtiExport::transition_pending_onload_raw_monitors();
 
-  // Fully start NMT
-  MemTracker::start();
-
   // Create the VMThread
   { TraceTime timer("Start VMThread", TraceStartupTime);
     VMThread::create();
@@ -4088,8 +4065,6 @@
     daemon = false;
   }
 
-  p->set_safepoint_visible(true);
-
   ThreadService::add_thread(p, daemon);
 
   // Possible GC point.
@@ -4135,13 +4110,6 @@
     // to do callbacks into the safepoint code. However, the safepoint code is not aware
     // of this thread since it is removed from the queue.
     p->set_terminated_value();
-
-    // Now, this thread is not visible to safepoint
-    p->set_safepoint_visible(false);
-    // once the thread becomes safepoint invisible, we can not use its per-thread
-    // recorder. And Threads::do_threads() no longer walks this thread, so we have
-    // to release its per-thread recorder here.
-    MemTracker::thread_exiting(p);
   } // unlock Threads_lock
 
   // Since Events::log uses a lock, we grab it outside the Threads_lock
@@ -4166,22 +4134,22 @@
 // uses the Threads_lock to gurantee this property. It also makes sure that
 // all threads gets blocked when exiting or starting).
 
-void Threads::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) {
+void Threads::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   ALL_JAVA_THREADS(p) {
     p->oops_do(f, cld_f, cf);
   }
   VMThread::vm_thread()->oops_do(f, cld_f, cf);
 }
 
-void Threads::possibly_parallel_oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) {
+void Threads::possibly_parallel_oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   // Introduce a mechanism allowing parallel threads to claim threads as
   // root groups.  Overhead should be small enough to use all the time,
   // even in sequential code.
   SharedHeap* sh = SharedHeap::heap();
   // Cannot yet substitute active_workers for n_par_threads
   // because of G1CollectedHeap::verify() use of
-  // SharedHeap::process_strong_roots().  n_par_threads == 0 will
-  // turn off parallelism in process_strong_roots while active_workers
+  // SharedHeap::process_roots().  n_par_threads == 0 will
+  // turn off parallelism in process_roots while active_workers
   // is being used for parallelism elsewhere.
   bool is_par = sh->n_par_threads() > 0;
   assert(!is_par ||
diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp
index 082629a..fabb2b8 100644
--- a/hotspot/src/share/vm/runtime/thread.hpp
+++ b/hotspot/src/share/vm/runtime/thread.hpp
@@ -43,10 +43,6 @@
 #include "runtime/unhandledOops.hpp"
 #include "utilities/macros.hpp"
 
-#if INCLUDE_NMT
-#include "services/memRecorder.hpp"
-#endif // INCLUDE_NMT
-
 #include "trace/traceBackend.hpp"
 #include "trace/traceMacros.hpp"
 #include "utilities/exceptions.hpp"
@@ -436,18 +432,7 @@
   jlong allocated_bytes()               { return _allocated_bytes; }
   void set_allocated_bytes(jlong value) { _allocated_bytes = value; }
   void incr_allocated_bytes(jlong size) { _allocated_bytes += size; }
-  jlong cooked_allocated_bytes() {
-    jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes);
-    if (UseTLAB) {
-      size_t used_bytes = tlab().used_bytes();
-      if ((ssize_t)used_bytes > 0) {
-        // More-or-less valid tlab.  The load_acquire above should ensure
-        // that the result of the add is <= the instantaneous value
-        return allocated_bytes + used_bytes;
-      }
-    }
-    return allocated_bytes;
-  }
+  inline jlong cooked_allocated_bytes();
 
   TRACE_DATA* trace_data()              { return &_trace_data; }
 
@@ -483,13 +468,13 @@
   // Apply "cld_f->do_cld" to CLDs that are otherwise not kept alive.
   //   Used by JavaThread::oops_do.
   // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames
-  virtual void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf);
+  virtual void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
 
   // Handles the parallel case for the method below.
 private:
   bool claim_oops_do_par_case(int collection_parity);
 public:
-  // Requires that "collection_parity" is that of the current strong roots
+  // Requires that "collection_parity" is that of the current roots
   // iteration.  If "is_par" is false, sets the parity of "this" to
   // "collection_parity", and returns "true".  If "is_par" is true,
   // uses an atomic instruction to set the current threads parity to
@@ -1046,12 +1031,8 @@
 #else
   // Use membars when accessing volatile _thread_state. See
   // Threads::create_vm() for size checks.
-  JavaThreadState thread_state() const           {
-    return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state);
-  }
-  void set_thread_state(JavaThreadState s)       {
-    OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s);
-  }
+  inline JavaThreadState thread_state() const;
+  inline void set_thread_state(JavaThreadState s);
 #endif
   ThreadSafepointState *safepoint_state() const  { return _safepoint_state; }
   void set_safepoint_state(ThreadSafepointState *state) { _safepoint_state = state; }
@@ -1074,16 +1055,6 @@
   bool do_not_unlock_if_synchronized()             { return _do_not_unlock_if_synchronized; }
   void set_do_not_unlock_if_synchronized(bool val) { _do_not_unlock_if_synchronized = val; }
 
-#if INCLUDE_NMT
-  // native memory tracking
-  inline MemRecorder* get_recorder() const          { return (MemRecorder*)_recorder; }
-  inline void         set_recorder(MemRecorder* rc) { _recorder = rc; }
-
- private:
-  // per-thread memory recorder
-  MemRecorder* volatile _recorder;
-#endif // INCLUDE_NMT
-
   // Suspend/resume support for JavaThread
  private:
   void set_ext_suspended()       { set_suspend_flag (_ext_suspended);  }
@@ -1444,7 +1415,7 @@
   void frames_do(void f(frame*, const RegisterMap*));
 
   // Memory operations
-  void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf);
+  void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
 
   // Sweeper operations
   void nmethods_do(CodeBlobClosure* cf);
@@ -1526,19 +1497,6 @@
      return result;
    }
 
- // NMT (Native memory tracking) support.
- // This flag helps NMT to determine if this JavaThread will be blocked
- // at safepoint. If not, ThreadCritical is needed for writing memory records.
- // JavaThread is only safepoint visible when it is in Threads' thread list,
- // it is not visible until it is added to the list and becomes invisible
- // once it is removed from the list.
- public:
-  bool is_safepoint_visible() const { return _safepoint_visible; }
-  void set_safepoint_visible(bool visible) { _safepoint_visible = visible; }
- private:
-  bool _safepoint_visible;
-
-  // Static operations
  public:
   // Returns the running thread as a JavaThread
   static inline JavaThread* current();
@@ -1775,7 +1733,7 @@
   // clearing/querying jni attach status
   bool is_attaching_via_jni() const { return _jni_attach_state == _attaching_via_jni; }
   bool has_attached_via_jni() const { return is_attaching_via_jni() || _jni_attach_state == _attached_via_jni; }
-  void set_done_attaching_via_jni() { _jni_attach_state = _attached_via_jni; OrderAccess::fence(); }
+  inline void set_done_attaching_via_jni();
 private:
   // This field is used to determine if a thread has claimed
   // a par_id: it is UINT_MAX if the thread has not claimed a par_id;
@@ -1875,7 +1833,7 @@
   // GC support
   // Apply "f->do_oop" to all root oops in "this".
   // Apply "cf->do_code_blob" (if !NULL) to all code blobs active in frames
-  void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf);
+  void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
 
 #ifndef PRODUCT
 private:
@@ -1942,9 +1900,9 @@
 
   // Apply "f->do_oop" to all root oops in all threads.
   // This version may only be called by sequential code.
-  static void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf);
+  static void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
   // This version may be called by sequential or parallel code.
-  static void possibly_parallel_oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf);
+  static void possibly_parallel_oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
   // This creates a list of GCTasks, one per thread.
   static void create_thread_roots_tasks(GCTaskQueue* q);
   // This creates a list of GCTasks, one per thread, for marking objects.
diff --git a/hotspot/src/share/vm/runtime/thread.inline.hpp b/hotspot/src/share/vm/runtime/thread.inline.hpp
index 2a95d70..b68e7d1 100644
--- a/hotspot/src/share/vm/runtime/thread.inline.hpp
+++ b/hotspot/src/share/vm/runtime/thread.inline.hpp
@@ -46,4 +46,32 @@
 
 #undef SHARE_VM_RUNTIME_THREAD_INLINE_HPP_SCOPE
 
+inline jlong Thread::cooked_allocated_bytes() {
+  jlong allocated_bytes = OrderAccess::load_acquire(&_allocated_bytes);
+  if (UseTLAB) {
+    size_t used_bytes = tlab().used_bytes();
+    if ((ssize_t)used_bytes > 0) {
+      // More-or-less valid tlab. The load_acquire above should ensure
+      // that the result of the add is <= the instantaneous value.
+      return allocated_bytes + used_bytes;
+    }
+  }
+  return allocated_bytes;
+}
+
+#ifdef PPC64
+inline JavaThreadState JavaThread::thread_state() const    {
+  return (JavaThreadState) OrderAccess::load_acquire((volatile jint*)&_thread_state);
+}
+
+inline void JavaThread::set_thread_state(JavaThreadState s) {
+  OrderAccess::release_store((volatile jint*)&_thread_state, (jint)s);
+}
+#endif
+
+inline void JavaThread::set_done_attaching_via_jni() {
+  _jni_attach_state = _attached_via_jni;
+  OrderAccess::fence();
+}
+
 #endif // SHARE_VM_RUNTIME_THREAD_INLINE_HPP
diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp
index daf9c4e..0ee5982 100644
--- a/hotspot/src/share/vm/runtime/vmThread.cpp
+++ b/hotspot/src/share/vm/runtime/vmThread.cpp
@@ -682,7 +682,7 @@
 }
 
 
-void VMThread::oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf) {
+void VMThread::oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf) {
   Thread::oops_do(f, cld_f, cf);
   _vm_queue->oops_do(f);
 }
diff --git a/hotspot/src/share/vm/runtime/vmThread.hpp b/hotspot/src/share/vm/runtime/vmThread.hpp
index d7a45b3..2682d9d 100644
--- a/hotspot/src/share/vm/runtime/vmThread.hpp
+++ b/hotspot/src/share/vm/runtime/vmThread.hpp
@@ -126,7 +126,7 @@
   static VMThread* vm_thread()                    { return _vm_thread; }
 
   // GC support
-  void oops_do(OopClosure* f, CLDToOopClosure* cld_f, CodeBlobClosure* cf);
+  void oops_do(OopClosure* f, CLDClosure* cld_f, CodeBlobClosure* cf);
 
   // Debugging
   void print_on(outputStream* st) const;
diff --git a/hotspot/src/share/vm/services/allocationSite.hpp b/hotspot/src/share/vm/services/allocationSite.hpp
new file mode 100644
index 0000000..07f8595
--- /dev/null
+++ b/hotspot/src/share/vm/services/allocationSite.hpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_SERVICES_ALLOCATION_SITE_HPP
+#define SHARE_VM_SERVICES_ALLOCATION_SITE_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/nativeCallStack.hpp"
+
+// Allocation site represents a code path that makes a memory
+// allocation
+template <class E> class AllocationSite VALUE_OBJ_CLASS_SPEC {
+ private:
+  NativeCallStack  _call_stack;
+  E                e;
+ public:
+  AllocationSite(const NativeCallStack& stack) : _call_stack(stack) { }
+  int hash() const { return _call_stack.hash(); }
+  bool equals(const NativeCallStack& stack) const {
+    return _call_stack.equals(stack);
+  }
+
+  bool equals(const AllocationSite<E>& other) const {
+    return other.equals(_call_stack);
+  }
+
+  const NativeCallStack* call_stack() const {
+    return &_call_stack;
+  }
+
+  // Information regarding this allocation
+  E* data()             { return &e; }
+  const E* peek() const { return &e; }
+};
+
+#endif  // SHARE_VM_SERVICES_ALLOCATION_SITE_HPP
diff --git a/hotspot/src/share/vm/services/mallocSiteTable.cpp b/hotspot/src/share/vm/services/mallocSiteTable.cpp
new file mode 100644
index 0000000..8090de8
--- /dev/null
+++ b/hotspot/src/share/vm/services/mallocSiteTable.cpp
@@ -0,0 +1,261 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+#include "precompiled.hpp"
+
+
+#include "memory/allocation.inline.hpp"
+#include "runtime/atomic.hpp"
+#include "services/mallocSiteTable.hpp"
+
+/*
+ * Early os::malloc() calls come from initializations of static variables, long before entering any
+ * VM code. Upon the arrival of the first os::malloc() call, malloc site hashtable has to be
+ * initialized, along with the allocation site for the hashtable entries.
+ * To ensure that malloc site hashtable can be initialized without triggering any additional os::malloc()
+ * call, the hashtable bucket array and hashtable entry allocation site have to be static.
+ * It is not a problem for hashtable bucket, since it is an array of pointer type, C runtime just
+ * allocates a block memory and zero the memory for it.
+ * But for hashtable entry allocation site object, things get tricky. C runtime not only allocates
+ * memory for it, but also calls its constructor at some later time. If we initialize the allocation site
+ * at the first os::malloc() call, the object will be reinitialized when its constructor is called
+ * by C runtime.
+ * To workaround above issue, we declare a static size_t array with the size of the CallsiteHashtableEntry,
+ * the memory is used to instantiate CallsiteHashtableEntry for the hashtable entry allocation site.
+ * Given it is a primitive type array, C runtime will do nothing other than assign the memory block for the variable,
+ * which is exactly what we want.
+ * The same trick is also applied to create NativeCallStack object for CallsiteHashtableEntry memory allocation.
+ *
+ * Note: C++ object usually aligns to particular alignment, depends on compiler implementation, we declare
+ * the memory as size_t arrays, to ensure the memory is aligned to native machine word alignment.
+ */
+
+// Reserve enough memory for NativeCallStack and MallocSiteHashtableEntry objects
+size_t MallocSiteTable::_hash_entry_allocation_stack[CALC_OBJ_SIZE_IN_TYPE(NativeCallStack, size_t)];
+size_t MallocSiteTable::_hash_entry_allocation_site[CALC_OBJ_SIZE_IN_TYPE(MallocSiteHashtableEntry, size_t)];
+
+// Malloc site hashtable buckets
+MallocSiteHashtableEntry*  MallocSiteTable::_table[MallocSiteTable::table_size];
+
+// concurrent access counter
+volatile int MallocSiteTable::_access_count = 0;
+
+// Tracking hashtable contention
+NOT_PRODUCT(int MallocSiteTable::_peak_count = 0;)
+
+
+/*
+ * Initialize malloc site table.
+ * Hashtable entry is malloc'd, so it can cause infinite recursion.
+ * To avoid above problem, we pre-initialize a hash entry for
+ * this allocation site.
+ * The method is called during C runtime static variable initialization
+ * time, it is in single-threaded mode from JVM perspective.
+ */
+bool MallocSiteTable::initialize() {
+  assert(sizeof(_hash_entry_allocation_stack) >= sizeof(NativeCallStack), "Sanity Check");
+  assert(sizeof(_hash_entry_allocation_site) >= sizeof(MallocSiteHashtableEntry),
+    "Sanity Check");
+  assert((size_t)table_size <= MAX_MALLOCSITE_TABLE_SIZE, "Hashtable overflow");
+
+  // Fake the call stack for hashtable entry allocation
+  assert(NMT_TrackingStackDepth > 1, "At least one tracking stack");
+
+  // Create pseudo call stack for hashtable entry allocation
+  address pc[3];
+  if (NMT_TrackingStackDepth >= 3) {
+    pc[2] = (address)MallocSiteTable::allocation_at;
+  }
+  if (NMT_TrackingStackDepth >= 2) {
+    pc[1] = (address)MallocSiteTable::lookup_or_add;
+  }
+  pc[0] = (address)MallocSiteTable::new_entry;
+
+  // Instantiate NativeCallStack object, have to use placement new operator. (see comments above)
+  NativeCallStack* stack = ::new ((void*)_hash_entry_allocation_stack)
+    NativeCallStack(pc, MIN2(((int)(sizeof(pc) / sizeof(address))), ((int)NMT_TrackingStackDepth)));
+
+  // Instantiate hash entry for hashtable entry allocation callsite
+  MallocSiteHashtableEntry* entry = ::new ((void*)_hash_entry_allocation_site)
+    MallocSiteHashtableEntry(*stack);
+
+  // Add the allocation site to hashtable.
+  int index = hash_to_index(stack->hash());
+  _table[index] = entry;
+
+  return true;
+}
+
+// Walks entries in the hashtable.
+// It stops walk if the walker returns false.
+bool MallocSiteTable::walk(MallocSiteWalker* walker) {
+  MallocSiteHashtableEntry* head;
+  for (int index = 0; index < table_size; index ++) {
+    head = _table[index];
+    while (head != NULL) {
+      if (!walker->do_malloc_site(head->peek())) {
+        return false;
+      }
+      head = (MallocSiteHashtableEntry*)head->next();
+    }
+  }
+  return true;
+}
+
+/*
+ *  The hashtable does not have deletion policy on individual entry,
+ *  and each linked list node is inserted via compare-and-swap,
+ *  so each linked list is stable, the contention only happens
+ *  at the end of linked list.
+ *  This method should not return NULL under normal circumstance.
+ *  If NULL is returned, it indicates:
+ *    1. Out of memory, it cannot allocate new hash entry.
+ *    2. Overflow hash bucket.
+ *  Under any of above circumstances, caller should handle the situation.
+ */
+MallocSite* MallocSiteTable::lookup_or_add(const NativeCallStack& key, size_t* bucket_idx,
+  size_t* pos_idx) {
+  int index = hash_to_index(key.hash());
+  assert(index >= 0, "Negative index");
+  *bucket_idx = (size_t)index;
+  *pos_idx = 0;
+
+  // First entry for this hash bucket
+  if (_table[index] == NULL) {
+    MallocSiteHashtableEntry* entry = new_entry(key);
+    // OOM check
+    if (entry == NULL) return NULL;
+
+    // swap in the head
+    if (Atomic::cmpxchg_ptr((void*)entry, (volatile void *)&_table[index], NULL) == NULL) {
+      return entry->data();
+    }
+
+    delete entry;
+  }
+
+  MallocSiteHashtableEntry* head = _table[index];
+  while (head != NULL && (*pos_idx) <= MAX_BUCKET_LENGTH) {
+    MallocSite* site = head->data();
+    if (site->equals(key)) {
+      // found matched entry
+      return head->data();
+    }
+
+    if (head->next() == NULL && (*pos_idx) < MAX_BUCKET_LENGTH) {
+      MallocSiteHashtableEntry* entry = new_entry(key);
+      // OOM check
+      if (entry == NULL) return NULL;
+      if (head->atomic_insert(entry)) {
+        (*pos_idx) ++;
+        return entry->data();
+      }
+      // contended, other thread won
+      delete entry;
+    }
+    head = (MallocSiteHashtableEntry*)head->next();
+    (*pos_idx) ++;
+  }
+  return NULL;
+}
+
+// Access malloc site
+MallocSite* MallocSiteTable::malloc_site(size_t bucket_idx, size_t pos_idx) {
+  assert(bucket_idx < table_size, "Invalid bucket index");
+  MallocSiteHashtableEntry* head = _table[bucket_idx];
+  for (size_t index = 0; index < pos_idx && head != NULL;
+    index ++, head = (MallocSiteHashtableEntry*)head->next());
+  assert(head != NULL, "Invalid position index");
+  return head->data();
+}
+
+// Allocates MallocSiteHashtableEntry object. Special call stack
+// (pre-installed allocation site) has to be used to avoid infinite
+// recursion.
+MallocSiteHashtableEntry* MallocSiteTable::new_entry(const NativeCallStack& key) {
+  void* p = AllocateHeap(sizeof(MallocSiteHashtableEntry), mtNMT,
+    *hash_entry_allocation_stack(), AllocFailStrategy::RETURN_NULL);
+  return ::new (p) MallocSiteHashtableEntry(key);
+}
+
+void MallocSiteTable::reset() {
+  for (int index = 0; index < table_size; index ++) {
+    MallocSiteHashtableEntry* head = _table[index];
+    _table[index] = NULL;
+    delete_linked_list(head);
+  }
+}
+
+void MallocSiteTable::delete_linked_list(MallocSiteHashtableEntry* head) {
+  MallocSiteHashtableEntry* p;
+  while (head != NULL) {
+    p = head;
+    head = (MallocSiteHashtableEntry*)head->next();
+    if (p != (MallocSiteHashtableEntry*)_hash_entry_allocation_site) {
+      delete p;
+    }
+  }
+}
+
+void MallocSiteTable::shutdown() {
+  AccessLock locker(&_access_count);
+  locker.exclusiveLock();
+  reset();
+}
+
+bool MallocSiteTable::walk_malloc_site(MallocSiteWalker* walker) {
+  assert(walker != NULL, "NuLL walker");
+  AccessLock locker(&_access_count);
+  if (locker.sharedLock()) {
+    NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);)
+    return walk(walker);
+  }
+  return false;
+}
+
+
+void MallocSiteTable::AccessLock::exclusiveLock() {
+  jint target;
+  jint val;
+
+  assert(_lock_state != ExclusiveLock, "Can only call once");
+  assert(*_lock >= 0, "Can not content exclusive lock");
+
+  // make counter negative to block out shared locks
+  do {
+    val = *_lock;
+    target = _MAGIC_ + *_lock;
+  } while (Atomic::cmpxchg(target, _lock, val) != val);
+
+  // wait for all readers to exit
+  while (*_lock != _MAGIC_) {
+#ifdef _WINDOWS
+    os::naked_short_sleep(1);
+#else
+    os::NakedYield();
+#endif
+  }
+  _lock_state = ExclusiveLock;
+}
+
+
diff --git a/hotspot/src/share/vm/services/mallocSiteTable.hpp b/hotspot/src/share/vm/services/mallocSiteTable.hpp
new file mode 100644
index 0000000..cff9816
--- /dev/null
+++ b/hotspot/src/share/vm/services/mallocSiteTable.hpp
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_SERVICES_MALLOC_SITE_TABLE_HPP
+#define SHARE_VM_SERVICES_MALLOC_SITE_TABLE_HPP
+
+#if INCLUDE_NMT
+
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "services/allocationSite.hpp"
+#include "services/mallocTracker.hpp"
+#include "services/nmtCommon.hpp"
+#include "utilities/nativeCallStack.hpp"
+
+// MallocSite represents a code path that eventually calls
+// os::malloc() to allocate memory
+class MallocSite : public AllocationSite<MemoryCounter> {
+ public:
+  MallocSite() :
+    AllocationSite<MemoryCounter>(NativeCallStack::EMPTY_STACK) { }
+
+  MallocSite(const NativeCallStack& stack) :
+    AllocationSite<MemoryCounter>(stack) { }
+
+  void allocate(size_t size)      { data()->allocate(size);   }
+  void deallocate(size_t size)    { data()->deallocate(size); }
+
+  // Memory allocated from this code path
+  size_t size()  const { return peek()->size(); }
+  // The number of calls were made
+  size_t count() const { return peek()->count(); }
+};
+
+// Malloc site hashtable entry
+class MallocSiteHashtableEntry : public CHeapObj<mtNMT> {
+ private:
+  MallocSite                _malloc_site;
+  MallocSiteHashtableEntry* _next;
+
+ public:
+  MallocSiteHashtableEntry() : _next(NULL) { }
+
+  MallocSiteHashtableEntry(NativeCallStack stack):
+    _malloc_site(stack), _next(NULL) { }
+
+  inline const MallocSiteHashtableEntry* next() const {
+    return _next;
+  }
+
+  // Insert an entry atomically.
+  // Return true if the entry is inserted successfully.
+  // The operation can be failed due to contention from other thread.
+  bool atomic_insert(const MallocSiteHashtableEntry* entry) {
+    return (Atomic::cmpxchg_ptr((void*)entry, (volatile void*)&_next,
+      NULL) == NULL);
+  }
+
+  void set_callsite(const MallocSite& site) {
+    _malloc_site = site;
+  }
+
+  inline const MallocSite* peek() const { return &_malloc_site; }
+  inline MallocSite* data()             { return &_malloc_site; }
+
+  inline long hash() const { return _malloc_site.hash(); }
+  inline bool equals(const NativeCallStack& stack) const {
+    return _malloc_site.equals(stack);
+  }
+  // Allocation/deallocation on this allocation site
+  inline void allocate(size_t size)   { _malloc_site.allocate(size);   }
+  inline void deallocate(size_t size) { _malloc_site.deallocate(size); }
+  // Memory counters
+  inline size_t size() const  { return _malloc_site.size();  }
+  inline size_t count() const { return _malloc_site.count(); }
+};
+
+// The walker walks every entry on MallocSiteTable
+class MallocSiteWalker : public StackObj {
+ public:
+   virtual bool do_malloc_site(const MallocSite* e) { return false; }
+};
+
+/*
+ * Native memory tracking call site table.
+ * The table is only needed when detail tracking is enabled.
+ */
+class MallocSiteTable : AllStatic {
+ private:
+  // The number of hash bucket in this hashtable. The number should
+  // be tuned if malloc activities changed significantly.
+  // The statistics data can be obtained via Jcmd
+  // jcmd <pid> VM.native_memory statistics.
+
+  // Currently, (number of buckets / number of entires) ratio is
+  // about 1 / 6
+  enum {
+    table_base_size = 128,   // The base size is calculated from statistics to give
+                             // table ratio around 1:6
+    table_size = (table_base_size * NMT_TrackingStackDepth - 1)
+  };
+
+
+  // This is a very special lock, that allows multiple shared accesses (sharedLock), but
+  // once exclusive access (exclusiveLock) is requested, all shared accesses are
+  // rejected forever.
+  class AccessLock : public StackObj {
+    enum LockState {
+      NoLock,
+      SharedLock,
+      ExclusiveLock
+    };
+
+   private:
+    // A very large negative number. The only possibility to "overflow"
+    // this number is when there are more than -min_jint threads in
+    // this process, which is not going to happen in foreseeable future.
+    const static int _MAGIC_ = min_jint;
+
+    LockState      _lock_state;
+    volatile int*  _lock;
+   public:
+    AccessLock(volatile int* lock) :
+      _lock(lock), _lock_state(NoLock) {
+    }
+
+    ~AccessLock() {
+      if (_lock_state == SharedLock) {
+        Atomic::dec((volatile jint*)_lock);
+      }
+    }
+    // Acquire shared lock.
+    // Return true if shared access is granted.
+    inline bool sharedLock() {
+      jint res = Atomic::add(1, _lock);
+      if (res < 0) {
+        Atomic::add(-1, _lock);
+        return false;
+      }
+      _lock_state = SharedLock;
+      return true;
+    }
+    // Acquire exclusive lock
+    void exclusiveLock();
+ };
+
+ public:
+  static bool initialize();
+  static void shutdown();
+
+  NOT_PRODUCT(static int access_peak_count() { return _peak_count; })
+
+  // Number of hash buckets
+  static inline int hash_buckets()      { return (int)table_size; }
+
+  // Access and copy a call stack from this table. Shared lock should be
+  // acquired before access the entry.
+  static inline bool access_stack(NativeCallStack& stack, size_t bucket_idx,
+    size_t pos_idx) {
+    AccessLock locker(&_access_count);
+    if (locker.sharedLock()) {
+      NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);)
+      MallocSite* site = malloc_site(bucket_idx, pos_idx);
+      if (site != NULL) {
+        stack = *site->call_stack();
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Record a new allocation from specified call path.
+  // Return true if the allocation is recorded successfully, bucket_idx
+  // and pos_idx are also updated to indicate the entry where the allocation
+  // information was recorded.
+  // Return false only occurs under rare scenarios:
+  //  1. out of memory
+  //  2. overflow hash bucket
+  static inline bool allocation_at(const NativeCallStack& stack, size_t size,
+    size_t* bucket_idx, size_t* pos_idx) {
+    AccessLock locker(&_access_count);
+    if (locker.sharedLock()) {
+      NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);)
+      MallocSite* site = lookup_or_add(stack, bucket_idx, pos_idx);
+      if (site != NULL) site->allocate(size);
+      return site != NULL;
+    }
+    return false;
+  }
+
+  // Record memory deallocation. bucket_idx and pos_idx indicate where the allocation
+  // information was recorded.
+  static inline bool deallocation_at(size_t size, size_t bucket_idx, size_t pos_idx) {
+    AccessLock locker(&_access_count);
+    if (locker.sharedLock()) {
+      NOT_PRODUCT(_peak_count = MAX2(_peak_count, _access_count);)
+      MallocSite* site = malloc_site(bucket_idx, pos_idx);
+      if (site != NULL) {
+        site->deallocate(size);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Walk this table.
+  static bool walk_malloc_site(MallocSiteWalker* walker);
+
+ private:
+  static MallocSiteHashtableEntry* new_entry(const NativeCallStack& key);
+  static void reset();
+
+  // Delete a bucket linked list
+  static void delete_linked_list(MallocSiteHashtableEntry* head);
+
+  static MallocSite* lookup_or_add(const NativeCallStack& key, size_t* bucket_idx, size_t* pos_idx);
+  static MallocSite* malloc_site(size_t bucket_idx, size_t pos_idx);
+  static bool walk(MallocSiteWalker* walker);
+
+  static inline int hash_to_index(int  hash) {
+    hash = (hash > 0) ? hash : (-hash);
+    return (hash % table_size);
+  }
+
+  static inline const NativeCallStack* hash_entry_allocation_stack() {
+    return (NativeCallStack*)_hash_entry_allocation_stack;
+  }
+
+ private:
+  // Counter for counting concurrent access
+  static volatile int                _access_count;
+
+  // The callsite hashtable. It has to be a static table,
+  // since malloc call can come from C runtime linker.
+  static MallocSiteHashtableEntry*   _table[table_size];
+
+
+  // Reserve enough memory for placing the objects
+
+  // The memory for hashtable entry allocation stack object
+  static size_t _hash_entry_allocation_stack[CALC_OBJ_SIZE_IN_TYPE(NativeCallStack, size_t)];
+  // The memory for hashtable entry allocation callsite object
+  static size_t _hash_entry_allocation_site[CALC_OBJ_SIZE_IN_TYPE(MallocSiteHashtableEntry, size_t)];
+  NOT_PRODUCT(static int     _peak_count;)
+};
+
+#endif // INCLUDE_NMT
+#endif // SHARE_VM_SERVICES_MALLOC_SITE_TABLE_HPP
diff --git a/hotspot/src/share/vm/services/mallocTracker.cpp b/hotspot/src/share/vm/services/mallocTracker.cpp
new file mode 100644
index 0000000..d60dd38
--- /dev/null
+++ b/hotspot/src/share/vm/services/mallocTracker.cpp
@@ -0,0 +1,200 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+#include "precompiled.hpp"
+
+#include "runtime/atomic.hpp"
+#include "runtime/atomic.inline.hpp"
+#include "services/mallocSiteTable.hpp"
+#include "services/mallocTracker.hpp"
+#include "services/mallocTracker.inline.hpp"
+#include "services/memTracker.hpp"
+
+size_t MallocMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)];
+
+// Total malloc'd memory amount
+size_t MallocMemorySnapshot::total() const {
+  size_t amount = 0;
+  for (int index = 0; index < mt_number_of_types; index ++) {
+    amount += _malloc[index].malloc_size();
+  }
+  amount += _tracking_header.size() + total_arena();
+  return amount;
+}
+
+// Total malloc'd memory used by arenas
+size_t MallocMemorySnapshot::total_arena() const {
+  size_t amount = 0;
+  for (int index = 0; index < mt_number_of_types; index ++) {
+    amount += _malloc[index].arena_size();
+  }
+  return amount;
+}
+
+
+void MallocMemorySnapshot::reset() {
+  _tracking_header.reset();
+  for (int index = 0; index < mt_number_of_types; index ++) {
+    _malloc[index].reset();
+  }
+}
+
+// Make adjustment by subtracting chunks used by arenas
+// from total chunks to get total free chunck size
+void MallocMemorySnapshot::make_adjustment() {
+  size_t arena_size = total_arena();
+  int chunk_idx = NMTUtil::flag_to_index(mtChunk);
+  _malloc[chunk_idx].record_free(arena_size);
+}
+
+
+void MallocMemorySummary::initialize() {
+  assert(sizeof(_snapshot) >= sizeof(MallocMemorySnapshot), "Sanity Check");
+  // Uses placement new operator to initialize static area.
+  ::new ((void*)_snapshot)MallocMemorySnapshot();
+}
+
+void MallocHeader::release() const {
+  // Tracking already shutdown, no housekeeping is needed anymore
+  if (MemTracker::tracking_level() <= NMT_minimal) return;
+
+  MallocMemorySummary::record_free(size(), flags());
+  MallocMemorySummary::record_free_malloc_header(sizeof(MallocHeader));
+  if (tracking_level() == NMT_detail) {
+    MallocSiteTable::deallocation_at(size(), _bucket_idx, _pos_idx);
+  }
+}
+
+bool MallocHeader::record_malloc_site(const NativeCallStack& stack, size_t size,
+  size_t* bucket_idx, size_t* pos_idx) const {
+  bool ret =  MallocSiteTable::allocation_at(stack, size, bucket_idx, pos_idx);
+
+  // Something went wrong, could be OOM or overflow malloc site table.
+  // We want to keep tracking data under OOM circumstance, so transition to
+  // summary tracking.
+  if (!ret) {
+    MemTracker::transition_to(NMT_summary);
+  }
+  return ret;
+}
+
+bool MallocHeader::get_stack(NativeCallStack& stack) const {
+  return MallocSiteTable::access_stack(stack, _bucket_idx, _pos_idx);
+}
+
+bool MallocTracker::initialize(NMT_TrackingLevel level) {
+  if (level >= NMT_summary) {
+    MallocMemorySummary::initialize();
+  }
+
+  if (level == NMT_detail) {
+    return MallocSiteTable::initialize();
+  }
+  return true;
+}
+
+bool MallocTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) {
+  assert(from != NMT_off, "Can not transition from off state");
+  assert(to != NMT_off, "Can not transition to off state");
+  if (from == NMT_minimal) {
+    MallocMemorySummary::reset();
+  }
+
+  if (to == NMT_detail) {
+    assert(from == NMT_minimal || from == NMT_summary, "Just check");
+    return MallocSiteTable::initialize();
+  } else if (from == NMT_detail) {
+    assert(to == NMT_minimal || to == NMT_summary, "Just check");
+    MallocSiteTable::shutdown();
+  }
+  return true;
+}
+
+// Record a malloc memory allocation
+void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flags,
+  const NativeCallStack& stack, NMT_TrackingLevel level) {
+  void*         memblock;      // the address for user data
+  MallocHeader* header = NULL;
+
+  if (malloc_base == NULL) {
+    return NULL;
+  }
+
+  // Check malloc size, size has to <= MAX_MALLOC_SIZE. This is only possible on 32-bit
+  // systems, when malloc size >= 1GB, but is is safe to assume it won't happen.
+  if (size > MAX_MALLOC_SIZE) {
+    fatal("Should not use malloc for big memory block, use virtual memory instead");
+  }
+  // Uses placement global new operator to initialize malloc header
+  switch(level) {
+    case NMT_off:
+      return malloc_base;
+    case NMT_minimal: {
+      MallocHeader* hdr = ::new (malloc_base) MallocHeader();
+      break;
+    }
+    case NMT_summary: {
+      header = ::new (malloc_base) MallocHeader(size, flags);
+      break;
+    }
+    case NMT_detail: {
+      header = ::new (malloc_base) MallocHeader(size, flags, stack);
+      break;
+    }
+    default:
+      ShouldNotReachHere();
+  }
+  memblock = (void*)((char*)malloc_base + sizeof(MallocHeader));
+
+  // The alignment check: 8 bytes alignment for 32 bit systems.
+  //                      16 bytes alignment for 64-bit systems.
+  assert(((size_t)memblock & (sizeof(size_t) * 2 - 1)) == 0, "Alignment check");
+
+  // Sanity check
+  assert(get_memory_tracking_level(memblock) == level,
+    "Wrong tracking level");
+
+#ifdef ASSERT
+  if (level > NMT_minimal) {
+    // Read back
+    assert(get_size(memblock) == size,   "Wrong size");
+    assert(get_flags(memblock) == flags, "Wrong flags");
+  }
+#endif
+
+  return memblock;
+}
+
+void* MallocTracker::record_free(void* memblock) {
+  // Never turned on
+  if (MemTracker::tracking_level() == NMT_off ||
+      memblock == NULL) {
+    return memblock;
+  }
+  MallocHeader* header = malloc_header(memblock);
+  header->release();
+
+  return (void*)header;
+}
+
+
diff --git a/hotspot/src/share/vm/services/mallocTracker.hpp b/hotspot/src/share/vm/services/mallocTracker.hpp
new file mode 100644
index 0000000..17c5852
--- /dev/null
+++ b/hotspot/src/share/vm/services/mallocTracker.hpp
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_SERVICES_MALLOC_TRACKER_HPP
+#define SHARE_VM_SERVICES_MALLOC_TRACKER_HPP
+
+#if INCLUDE_NMT
+
+#include "memory/allocation.hpp"
+#include "runtime/atomic.hpp"
+#include "services/nmtCommon.hpp"
+#include "utilities/nativeCallStack.hpp"
+
+/*
+ * This counter class counts memory allocation and deallocation,
+ * records total memory allocation size and number of allocations.
+ * The counters are updated atomically.
+ */
+class MemoryCounter VALUE_OBJ_CLASS_SPEC {
+ private:
+  size_t   _count;
+  size_t   _size;
+
+  DEBUG_ONLY(size_t   _peak_count;)
+  DEBUG_ONLY(size_t   _peak_size; )
+
+ public:
+  MemoryCounter() : _count(0), _size(0) {
+    DEBUG_ONLY(_peak_count = 0;)
+    DEBUG_ONLY(_peak_size  = 0;)
+  }
+
+  // Reset counters
+  void reset() {
+    _size  = 0;
+    _count = 0;
+    DEBUG_ONLY(_peak_size = 0;)
+    DEBUG_ONLY(_peak_count = 0;)
+  }
+
+  inline void allocate(size_t sz) {
+    Atomic::add(1, (volatile MemoryCounterType*)&_count);
+    if (sz > 0) {
+      Atomic::add((MemoryCounterType)sz, (volatile MemoryCounterType*)&_size);
+      DEBUG_ONLY(_peak_size = MAX2(_peak_size, _size));
+    }
+    DEBUG_ONLY(_peak_count = MAX2(_peak_count, _count);)
+  }
+
+  inline void deallocate(size_t sz) {
+    assert(_count > 0, "Negative counter");
+    assert(_size >= sz, "Negative size");
+    Atomic::add(-1, (volatile MemoryCounterType*)&_count);
+    if (sz > 0) {
+      Atomic::add(-(MemoryCounterType)sz, (volatile MemoryCounterType*)&_size);
+    }
+  }
+
+  inline void resize(long sz) {
+    if (sz != 0) {
+      Atomic::add((MemoryCounterType)sz, (volatile MemoryCounterType*)&_size);
+      DEBUG_ONLY(_peak_size = MAX2(_size, _peak_size);)
+    }
+  }
+
+  inline size_t count() const { return _count; }
+  inline size_t size()  const { return _size;  }
+  DEBUG_ONLY(inline size_t peak_count() const { return _peak_count; })
+  DEBUG_ONLY(inline size_t peak_size()  const { return _peak_size; })
+
+};
+
+/*
+ * Malloc memory used by a particular subsystem.
+ * It includes the memory acquired through os::malloc()
+ * call and arena's backing memory.
+ */
+class MallocMemory VALUE_OBJ_CLASS_SPEC {
+ private:
+  MemoryCounter _malloc;
+  MemoryCounter _arena;
+
+ public:
+  MallocMemory() { }
+
+  inline void record_malloc(size_t sz) {
+    _malloc.allocate(sz);
+  }
+
+  inline void record_free(size_t sz) {
+    _malloc.deallocate(sz);
+  }
+
+  inline void record_new_arena() {
+    _arena.allocate(0);
+  }
+
+  inline void record_arena_free() {
+    _arena.deallocate(0);
+  }
+
+  inline void record_arena_size_change(long sz) {
+    _arena.resize(sz);
+  }
+
+  void reset() {
+    _malloc.reset();
+    _arena.reset();
+  }
+
+  inline size_t malloc_size()  const { return _malloc.size(); }
+  inline size_t malloc_count() const { return _malloc.count();}
+  inline size_t arena_size()   const { return _arena.size();  }
+  inline size_t arena_count()  const { return _arena.count(); }
+
+  DEBUG_ONLY(inline const MemoryCounter& malloc_counter() const { return _malloc; })
+  DEBUG_ONLY(inline const MemoryCounter& arena_counter()  const { return _arena;  })
+};
+
+class MallocMemorySummary;
+
+// A snapshot of malloc'd memory, includes malloc memory
+// usage by types and memory used by tracking itself.
+class MallocMemorySnapshot : public ResourceObj {
+  friend class MallocMemorySummary;
+
+ private:
+  MallocMemory      _malloc[mt_number_of_types];
+  MemoryCounter     _tracking_header;
+
+
+ public:
+  inline MallocMemory*  by_type(MEMFLAGS flags) {
+    int index = NMTUtil::flag_to_index(flags);
+    return &_malloc[index];
+  }
+
+  inline MallocMemory* by_index(int index) {
+    assert(index >= 0, "Index out of bound");
+    assert(index < mt_number_of_types, "Index out of bound");
+    return &_malloc[index];
+  }
+
+  inline MemoryCounter* malloc_overhead() {
+    return &_tracking_header;
+  }
+
+  // Total malloc'd memory amount
+  size_t total() const;
+  // Total malloc'd memory used by arenas
+  size_t total_arena() const;
+
+  inline size_t thread_count() const {
+    MallocMemorySnapshot* s = const_cast<MallocMemorySnapshot*>(this);
+    return s->by_type(mtThreadStack)->malloc_count();
+  }
+
+  void reset();
+
+  void copy_to(MallocMemorySnapshot* s) {
+    s->_tracking_header = _tracking_header;
+    for (int index = 0; index < mt_number_of_types; index ++) {
+      s->_malloc[index] = _malloc[index];
+    }
+  }
+
+  // Make adjustment by subtracting chunks used by arenas
+  // from total chunks to get total free chunk size
+  void make_adjustment();
+};
+
+/*
+ * This class is for collecting malloc statistics at summary level
+ */
+class MallocMemorySummary : AllStatic {
+ private:
+  // Reserve memory for placement of MallocMemorySnapshot object
+  static size_t _snapshot[CALC_OBJ_SIZE_IN_TYPE(MallocMemorySnapshot, size_t)];
+
+ public:
+   static void initialize();
+
+   static inline void record_malloc(size_t size, MEMFLAGS flag) {
+     as_snapshot()->by_type(flag)->record_malloc(size);
+   }
+
+   static inline void record_free(size_t size, MEMFLAGS flag) {
+     as_snapshot()->by_type(flag)->record_free(size);
+   }
+
+   static inline void record_new_arena(MEMFLAGS flag) {
+     as_snapshot()->by_type(flag)->record_new_arena();
+   }
+
+   static inline void record_arena_free(MEMFLAGS flag) {
+     as_snapshot()->by_type(flag)->record_arena_free();
+   }
+
+   static inline void record_arena_size_change(long size, MEMFLAGS flag) {
+     as_snapshot()->by_type(flag)->record_arena_size_change(size);
+   }
+
+   static void snapshot(MallocMemorySnapshot* s) {
+     as_snapshot()->copy_to(s);
+     s->make_adjustment();
+   }
+
+   // Record memory used by malloc tracking header
+   static inline void record_new_malloc_header(size_t sz) {
+     as_snapshot()->malloc_overhead()->allocate(sz);
+   }
+
+   static inline void record_free_malloc_header(size_t sz) {
+     as_snapshot()->malloc_overhead()->deallocate(sz);
+   }
+
+   // The memory used by malloc tracking headers
+   static inline size_t tracking_overhead() {
+     return as_snapshot()->malloc_overhead()->size();
+   }
+
+   // Reset all counters to zero
+   static void reset() {
+     as_snapshot()->reset();
+   }
+
+  static MallocMemorySnapshot* as_snapshot() {
+    return (MallocMemorySnapshot*)_snapshot;
+  }
+};
+
+
+/*
+ * Malloc tracking header.
+ * To satisfy malloc alignment requirement, NMT uses 2 machine words for tracking purpose,
+ * which ensures 8-bytes alignment on 32-bit systems and 16-bytes on 64-bit systems (Product build).
+ */
+
+class MallocHeader VALUE_OBJ_CLASS_SPEC {
+#ifdef _LP64
+  size_t           _size      : 62;
+  size_t           _level     : 2;
+  size_t           _flags     : 8;
+  size_t           _pos_idx   : 16;
+  size_t           _bucket_idx: 40;
+#define MAX_MALLOCSITE_TABLE_SIZE ((size_t)1 << 40)
+#define MAX_BUCKET_LENGTH         ((size_t)(1 << 16))
+#define MAX_MALLOC_SIZE           (((size_t)1 << 62) - 1)
+#else
+  size_t           _size      : 30;
+  size_t           _level     : 2;
+  size_t           _flags     : 8;
+  size_t           _pos_idx   : 8;
+  size_t           _bucket_idx: 16;
+#define MAX_MALLOCSITE_TABLE_SIZE  ((size_t)(1 << 16))
+#define MAX_BUCKET_LENGTH          ((size_t)(1 << 8))
+// Max malloc size = 1GB - 1 on 32 bit system, such has total 4GB memory
+#define MAX_MALLOC_SIZE            ((size_t)(1 << 30) - 1)
+#endif  // _LP64
+
+ public:
+  // Summary tracking header
+  MallocHeader(size_t size, MEMFLAGS flags) {
+    assert(sizeof(MallocHeader) == sizeof(void*) * 2,
+      "Wrong header size");
+
+    _level = NMT_summary;
+    _flags = flags;
+    set_size(size);
+    MallocMemorySummary::record_malloc(size, flags);
+    MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader));
+  }
+  // Detail tracking header
+  MallocHeader(size_t size, MEMFLAGS flags, const NativeCallStack& stack) {
+    assert(sizeof(MallocHeader) == sizeof(void*) * 2,
+      "Wrong header size");
+
+    _level = NMT_detail;
+    _flags = flags;
+    set_size(size);
+    size_t bucket_idx;
+    size_t pos_idx;
+    if (record_malloc_site(stack, size, &bucket_idx, &pos_idx)) {
+      assert(bucket_idx <= MAX_MALLOCSITE_TABLE_SIZE, "Overflow bucket index");
+      assert(pos_idx <= MAX_BUCKET_LENGTH, "Overflow bucket position index");
+      _bucket_idx = bucket_idx;
+      _pos_idx = pos_idx;
+    }
+    MallocMemorySummary::record_malloc(size, flags);
+    MallocMemorySummary::record_new_malloc_header(sizeof(MallocHeader));
+  }
+  // Minimal tracking header
+  MallocHeader() {
+    assert(sizeof(MallocHeader) == sizeof(void*) * 2,
+      "Wrong header size");
+
+    _level = (unsigned short)NMT_minimal;
+  }
+
+  inline NMT_TrackingLevel tracking_level() const {
+    return (NMT_TrackingLevel)_level;
+  }
+
+  inline size_t   size()  const { return _size; }
+  inline MEMFLAGS flags() const { return (MEMFLAGS)_flags; }
+  bool get_stack(NativeCallStack& stack) const;
+
+  // Cleanup tracking information before the memory is released.
+  void release() const;
+
+ private:
+  inline void set_size(size_t size) {
+    assert(size <= MAX_MALLOC_SIZE, "Malloc size too large, should use virtual memory?");
+    _size = size;
+  }
+  bool record_malloc_site(const NativeCallStack& stack, size_t size,
+    size_t* bucket_idx, size_t* pos_idx) const;
+};
+
+
+// Main class called from MemTracker to track malloc activities
+class MallocTracker : AllStatic {
+ public:
+  // Initialize malloc tracker for specific tracking level
+  static bool initialize(NMT_TrackingLevel level);
+
+  static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
+
+  // malloc tracking header size for specific tracking level
+  static inline size_t malloc_header_size(NMT_TrackingLevel level) {
+    return (level == NMT_off) ? 0 : sizeof(MallocHeader);
+  }
+
+  // Parameter name convention:
+  // memblock :   the beginning address for user data
+  // malloc_base: the beginning address that includes malloc tracking header
+  //
+  // The relationship:
+  // memblock = (char*)malloc_base + sizeof(nmt header)
+  //
+
+  // Record  malloc on specified memory block
+  static void* record_malloc(void* malloc_base, size_t size, MEMFLAGS flags,
+    const NativeCallStack& stack, NMT_TrackingLevel level);
+
+  // Record free on specified memory block
+  static void* record_free(void* memblock);
+
+  // Get tracking level of specified memory block
+  static inline NMT_TrackingLevel get_memory_tracking_level(void* memblock);
+
+
+  // Offset memory address to header address
+  static inline void* get_base(void* memblock);
+  static inline void* get_base(void* memblock, NMT_TrackingLevel level) {
+    if (memblock == NULL || level == NMT_off) return memblock;
+    return (char*)memblock - malloc_header_size(level);
+  }
+
+  // Get memory size
+  static inline size_t get_size(void* memblock) {
+    MallocHeader* header = malloc_header(memblock);
+    assert(header->tracking_level() >= NMT_summary,
+      "Wrong tracking level");
+    return header->size();
+  }
+
+  // Get memory type
+  static inline MEMFLAGS get_flags(void* memblock) {
+    MallocHeader* header = malloc_header(memblock);
+    assert(header->tracking_level() >= NMT_summary,
+      "Wrong tracking level");
+    return header->flags();
+  }
+
+  // Get header size
+  static inline size_t get_header_size(void* memblock) {
+    return (memblock == NULL) ? 0 : sizeof(MallocHeader);
+  }
+
+  static inline void record_new_arena(MEMFLAGS flags) {
+    MallocMemorySummary::record_new_arena(flags);
+  }
+
+  static inline void record_arena_free(MEMFLAGS flags) {
+    MallocMemorySummary::record_arena_free(flags);
+  }
+
+  static inline void record_arena_size_change(int size, MEMFLAGS flags) {
+    MallocMemorySummary::record_arena_size_change(size, flags);
+  }
+ private:
+  static inline MallocHeader* malloc_header(void *memblock) {
+    assert(memblock != NULL, "NULL pointer");
+    MallocHeader* header = (MallocHeader*)((char*)memblock - sizeof(MallocHeader));
+    assert(header->tracking_level() >= NMT_minimal, "Bad header");
+    return header;
+  }
+};
+
+#endif // INCLUDE_NMT
+
+
+#endif //SHARE_VM_SERVICES_MALLOC_TRACKER_HPP
diff --git a/hotspot/src/share/vm/services/memPtr.cpp b/hotspot/src/share/vm/services/mallocTracker.inline.hpp
similarity index 60%
rename from hotspot/src/share/vm/services/memPtr.cpp
rename to hotspot/src/share/vm/services/mallocTracker.inline.hpp
index bc46051..338295b 100644
--- a/hotspot/src/share/vm/services/memPtr.cpp
+++ b/hotspot/src/share/vm/services/mallocTracker.inline.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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
@@ -22,21 +22,22 @@
  *
  */
 
-#include "precompiled.hpp"
-#include "services/memPtr.hpp"
+#ifndef SHARE_VM_SERVICES_MALLOC_TRACKER_INLINE_HPP
+#define SHARE_VM_SERVICES_MALLOC_TRACKER_INLINE_HPP
+
+#include "services/mallocTracker.hpp"
 #include "services/memTracker.hpp"
 
-volatile jint SequenceGenerator::_seq_number = 1;
-volatile unsigned long SequenceGenerator::_generation = 1;
-NOT_PRODUCT(jint SequenceGenerator::_max_seq_number = 1;)
-
-jint SequenceGenerator::next() {
-  jint seq = Atomic::add(1, &_seq_number);
-  if (seq < 0) {
-    MemTracker::shutdown(MemTracker::NMT_sequence_overflow);
-  } else {
-    NOT_PRODUCT(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;)
-  }
-  return seq;
+inline NMT_TrackingLevel MallocTracker::get_memory_tracking_level(void* memblock) {
+  assert(memblock != NULL, "Sanity check");
+  if (MemTracker::tracking_level() == NMT_off) return NMT_off;
+  MallocHeader* header = malloc_header(memblock);
+  return header->tracking_level();
 }
 
+inline void* MallocTracker::get_base(void* memblock){
+  return get_base(memblock, MemTracker::tracking_level());
+}
+
+#endif // SHARE_VM_SERVICES_MALLOC_TRACKER_INLINE_HPP
+
diff --git a/hotspot/src/share/vm/services/management.cpp b/hotspot/src/share/vm/services/management.cpp
index ef18b46..4c88278 100644
--- a/hotspot/src/share/vm/services/management.cpp
+++ b/hotspot/src/share/vm/services/management.cpp
@@ -39,6 +39,7 @@
 #include "runtime/jniHandles.hpp"
 #include "runtime/os.hpp"
 #include "runtime/serviceThread.hpp"
+#include "runtime/thread.inline.hpp"
 #include "services/classLoadingService.hpp"
 #include "services/diagnosticCommand.hpp"
 #include "services/diagnosticFramework.hpp"
@@ -1823,7 +1824,7 @@
               "This flag is not writeable.");
   }
 
-  bool succeed;
+  bool succeed = false;
   if (flag->is_bool()) {
     bool bvalue = (new_value.z == JNI_TRUE ? true : false);
     succeed = CommandLineFlags::boolAtPut(name, &bvalue, Flag::MANAGEMENT);
@@ -1855,6 +1856,9 @@
     }
     ccstr svalue = java_lang_String::as_utf8_string(str);
     succeed = CommandLineFlags::ccstrAtPut(name, &svalue, Flag::MANAGEMENT);
+    if (succeed) {
+      FREE_C_HEAP_ARRAY(char, svalue, mtInternal);
+    }
   }
   assert(succeed, "Setting flag should succeed");
 JVM_END
diff --git a/hotspot/src/share/vm/services/memBaseline.cpp b/hotspot/src/share/vm/services/memBaseline.cpp
index 62e5187..02b4924 100644
--- a/hotspot/src/share/vm/services/memBaseline.cpp
+++ b/hotspot/src/share/vm/services/memBaseline.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -22,471 +22,279 @@
  *
  */
 #include "precompiled.hpp"
+
 #include "memory/allocation.hpp"
 #include "runtime/safepoint.hpp"
 #include "runtime/thread.inline.hpp"
 #include "services/memBaseline.hpp"
 #include "services/memTracker.hpp"
 
+/*
+ * Sizes are sorted in descenting order for reporting
+ */
+int compare_malloc_size(const MallocSite& s1, const MallocSite& s2) {
+  if (s1.size() == s2.size()) {
+    return 0;
+  } else if (s1.size() > s2.size()) {
+    return -1;
+  } else {
+    return 1;
+  }
+}
 
-MemType2Name MemBaseline::MemType2NameMap[NUMBER_OF_MEMORY_TYPE] = {
-  {mtJavaHeap,   "Java Heap"},
-  {mtClass,      "Class"},
-  {mtThreadStack,"Thread Stack"},
-  {mtThread,     "Thread"},
-  {mtCode,       "Code"},
-  {mtGC,         "GC"},
-  {mtCompiler,   "Compiler"},
-  {mtInternal,   "Internal"},
-  {mtOther,      "Other"},
-  {mtSymbol,     "Symbol"},
-  {mtNMT,        "Memory Tracking"},
-  {mtTracing,    "Tracing"},
-  {mtChunk,      "Pooled Free Chunks"},
-  {mtClassShared,"Shared spaces for classes"},
-  {mtTest,       "Test"},
-  {mtNone,       "Unknown"}  // It can happen when type tagging records are lagging
-                             // behind
+
+int compare_virtual_memory_size(const VirtualMemoryAllocationSite& s1,
+  const VirtualMemoryAllocationSite& s2) {
+  if (s1.reserved() == s2.reserved()) {
+    return 0;
+  } else if (s1.reserved() > s2.reserved()) {
+    return -1;
+  } else {
+    return 1;
+  }
+}
+
+// Sort into allocation site addresses order for baseline comparison
+int compare_malloc_site(const MallocSite& s1, const MallocSite& s2) {
+  return s1.call_stack()->compare(*s2.call_stack());
+}
+
+
+int compare_virtual_memory_site(const VirtualMemoryAllocationSite& s1,
+  const VirtualMemoryAllocationSite& s2) {
+  return s1.call_stack()->compare(*s2.call_stack());
+}
+
+/*
+ * Walker to walk malloc allocation site table
+ */
+class MallocAllocationSiteWalker : public MallocSiteWalker {
+ private:
+  SortedLinkedList<MallocSite, compare_malloc_size> _malloc_sites;
+  size_t         _count;
+
+  // Entries in MallocSiteTable with size = 0 and count = 0,
+  // when the malloc site is not longer there.
+ public:
+  MallocAllocationSiteWalker() : _count(0) { }
+
+  inline size_t count() const { return _count; }
+
+  LinkedList<MallocSite>* malloc_sites() {
+    return &_malloc_sites;
+  }
+
+  bool do_malloc_site(const MallocSite* site) {
+    if (site->size() >= MemBaseline::SIZE_THRESHOLD) {
+      if (_malloc_sites.add(*site) != NULL) {
+        _count++;
+        return true;
+      } else {
+        return false;  // OOM
+      }
+    } else {
+      // malloc site does not meet threshold, ignore and continue
+      return true;
+    }
+  }
 };
 
-MemBaseline::MemBaseline() {
-  _baselined = false;
-
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    _malloc_data[index].set_type(MemType2NameMap[index]._flag);
-    _vm_data[index].set_type(MemType2NameMap[index]._flag);
-    _arena_data[index].set_type(MemType2NameMap[index]._flag);
-  }
-
-  _malloc_cs = NULL;
-  _vm_cs = NULL;
-  _vm_map = NULL;
-
-  _number_of_classes = 0;
-  _number_of_threads = 0;
+// Compare virtual memory region's base address
+int compare_virtual_memory_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
+  return r1.compare(r2);
 }
 
+// Walk all virtual memory regions for baselining
+class VirtualMemoryAllocationWalker : public VirtualMemoryWalker {
+ private:
+  SortedLinkedList<ReservedMemoryRegion, compare_virtual_memory_base>
+                _virtual_memory_regions;
+  size_t        _count;
 
-void MemBaseline::clear() {
-  if (_malloc_cs != NULL) {
-    delete _malloc_cs;
-    _malloc_cs = NULL;
-  }
+ public:
+  VirtualMemoryAllocationWalker() : _count(0) { }
 
-  if (_vm_cs != NULL) {
-    delete _vm_cs;
-    _vm_cs = NULL;
-  }
-
-  if (_vm_map != NULL) {
-    delete _vm_map;
-    _vm_map = NULL;
-  }
-
-  reset();
-}
-
-
-void MemBaseline::reset() {
-  _baselined = false;
-  _total_vm_reserved = 0;
-  _total_vm_committed = 0;
-  _total_malloced = 0;
-  _number_of_classes = 0;
-
-  if (_malloc_cs != NULL) _malloc_cs->clear();
-  if (_vm_cs != NULL) _vm_cs->clear();
-  if (_vm_map != NULL) _vm_map->clear();
-
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    _malloc_data[index].clear();
-    _vm_data[index].clear();
-    _arena_data[index].clear();
-  }
-}
-
-MemBaseline::~MemBaseline() {
-  clear();
-}
-
-// baseline malloc'd memory records, generate overall summary and summaries by
-// memory types
-bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) {
-  MemPointerArrayIteratorImpl malloc_itr((MemPointerArray*)malloc_records);
-  MemPointerRecord* malloc_ptr = (MemPointerRecord*)malloc_itr.current();
-  size_t used_arena_size = 0;
-  int index;
-  while (malloc_ptr != NULL) {
-    index = flag2index(FLAGS_TO_MEMORY_TYPE(malloc_ptr->flags()));
-    size_t size = malloc_ptr->size();
-    if (malloc_ptr->is_arena_memory_record()) {
-      // We do have anonymous arenas, they are either used as value objects,
-      // which are embedded inside other objects, or used as stack objects.
-      _arena_data[index].inc(size);
-      used_arena_size += size;
-    } else {
-      _total_malloced += size;
-      _malloc_data[index].inc(size);
-      if (malloc_ptr->is_arena_record()) {
-        // see if arena memory record present
-        MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next();
-        if (next_malloc_ptr != NULL && next_malloc_ptr->is_arena_memory_record()) {
-          assert(next_malloc_ptr->is_memory_record_of_arena(malloc_ptr),
-             "Arena records do not match");
-          size = next_malloc_ptr->size();
-          _arena_data[index].inc(size);
-          used_arena_size += size;
-          malloc_itr.next();
-        }
-      }
-    }
-    malloc_ptr = (MemPointerRecordEx*)malloc_itr.next();
-  }
-
-  // substract used arena size to get size of arena chunk in free list
-  index = flag2index(mtChunk);
-  _malloc_data[index].reduce(used_arena_size);
-  // we really don't know how many chunks in free list, so just set to
-  // 0
-  _malloc_data[index].overwrite_counter(0);
-
-  return true;
-}
-
-// check if there is a safepoint in progress, if so, block the thread
-// for the safepoint
-void MemBaseline::check_safepoint(JavaThread* thr) {
-  if (SafepointSynchronize::is_synchronizing()) {
-    // grab and drop the SR_lock to honor the safepoint protocol
-    MutexLocker ml(thr->SR_lock());
-  }
-}
-
-// baseline mmap'd memory records, generate overall summary and summaries by
-// memory types
-bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) {
-  MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records);
-  VMMemRegion* vm_ptr = (VMMemRegion*)vm_itr.current();
-  int index;
-  while (vm_ptr != NULL) {
-    if (vm_ptr->is_reserved_region()) {
-      index = flag2index(FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()));
-    // we use the number of thread stack to count threads
-      if (IS_MEMORY_TYPE(vm_ptr->flags(), mtThreadStack)) {
-      _number_of_threads ++;
-    }
-      _total_vm_reserved += vm_ptr->size();
-      _vm_data[index].inc(vm_ptr->size(), 0);
-    } else {
-      _total_vm_committed += vm_ptr->size();
-      _vm_data[index].inc(0, vm_ptr->size());
-    }
-    vm_ptr = (VMMemRegion*)vm_itr.next();
-  }
-  return true;
-}
-
-// baseline malloc'd memory by callsites, but only the callsites with memory allocation
-// over 1KB are stored.
-bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) {
-  assert(MemTracker::track_callsite(), "detail tracking is off");
-
-  MemPointerArrayIteratorImpl malloc_itr(const_cast<MemPointerArray*>(malloc_records));
-  MemPointerRecordEx* malloc_ptr = (MemPointerRecordEx*)malloc_itr.current();
-  MallocCallsitePointer malloc_callsite;
-
-  // initailize malloc callsite array
-  if (_malloc_cs == NULL) {
-    _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64);
-    // out of native memory
-    if (_malloc_cs == NULL || _malloc_cs->out_of_memory()) {
-      return false;
-    }
-  } else {
-    _malloc_cs->clear();
-  }
-
-  MemPointerArray* malloc_data = const_cast<MemPointerArray*>(malloc_records);
-
-  // sort into callsite pc order. Details are aggregated by callsites
-  malloc_data->sort((FN_SORT)malloc_sort_by_pc);
-  bool ret = true;
-
-  // baseline memory that is totaled over 1 KB
-  while (malloc_ptr != NULL) {
-    if (!MemPointerRecord::is_arena_memory_record(malloc_ptr->flags())) {
-      // skip thread stacks
-      if (!IS_MEMORY_TYPE(malloc_ptr->flags(), mtThreadStack)) {
-        if (malloc_callsite.addr() != malloc_ptr->pc()) {
-          if ((malloc_callsite.amount()/K) > 0) {
-            if (!_malloc_cs->append(&malloc_callsite)) {
-              ret = false;
-              break;
-            }
-          }
-          malloc_callsite = MallocCallsitePointer(malloc_ptr->pc());
-        }
-        malloc_callsite.inc(malloc_ptr->size());
-      }
-    }
-    malloc_ptr = (MemPointerRecordEx*)malloc_itr.next();
-  }
-
-  // restore to address order. Snapshot malloc data is maintained in memory
-  // address order.
-  malloc_data->sort((FN_SORT)malloc_sort_by_addr);
-
-  if (!ret) {
-              return false;
-            }
-  // deal with last record
-  if (malloc_callsite.addr() != 0 && (malloc_callsite.amount()/K) > 0) {
-    if (!_malloc_cs->append(&malloc_callsite)) {
-      return false;
-    }
-  }
-  return true;
-}
-
-// baseline mmap'd memory by callsites
-bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) {
-  assert(MemTracker::track_callsite(), "detail tracking is off");
-
-  VMCallsitePointer  vm_callsite;
-  VMCallsitePointer* cur_callsite = NULL;
-  MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records);
-  VMMemRegionEx* vm_ptr = (VMMemRegionEx*)vm_itr.current();
-
-  // initialize virtual memory map array
-  if (_vm_map == NULL) {
-    _vm_map = new (std::nothrow) MemPointerArrayImpl<VMMemRegionEx>(vm_records->length());
-   if (_vm_map == NULL || _vm_map->out_of_memory()) {
-     return false;
-   }
-  } else {
-    _vm_map->clear();
-  }
-
-  // initialize virtual memory callsite array
-  if (_vm_cs == NULL) {
-    _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64);
-    if (_vm_cs == NULL || _vm_cs->out_of_memory()) {
-      return false;
-    }
-  } else {
-    _vm_cs->clear();
-  }
-
-  // consolidate virtual memory data
-  VMMemRegionEx*     reserved_rec = NULL;
-  VMMemRegionEx*     committed_rec = NULL;
-
-  // vm_ptr is coming in increasing base address order
-  while (vm_ptr != NULL) {
-    if (vm_ptr->is_reserved_region()) {
-      // consolidate reserved memory regions for virtual memory map.
-      // The criteria for consolidation is:
-      // 1. two adjacent reserved memory regions
-      // 2. belong to the same memory type
-      // 3. reserved from the same callsite
-      if (reserved_rec == NULL ||
-        reserved_rec->base() + reserved_rec->size() != vm_ptr->addr() ||
-        FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) != FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()) ||
-        reserved_rec->pc() != vm_ptr->pc()) {
-        if (!_vm_map->append(vm_ptr)) {
+  bool do_allocation_site(const ReservedMemoryRegion* rgn)  {
+    if (rgn->size() >= MemBaseline::SIZE_THRESHOLD) {
+      if (_virtual_memory_regions.add(*rgn) != NULL) {
+        _count ++;
+        return true;
+      } else {
         return false;
       }
-        // inserted reserved region, we need the pointer to the element in virtual
-        // memory map array.
-        reserved_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1);
-      } else {
-        reserved_rec->expand_region(vm_ptr->addr(), vm_ptr->size());
     }
-
-      if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) {
-      return false;
-    }
-      vm_callsite = VMCallsitePointer(vm_ptr->pc());
-      cur_callsite = &vm_callsite;
-      vm_callsite.inc(vm_ptr->size(), 0);
-    } else {
-      // consolidate committed memory regions for virtual memory map
-      // The criterial is:
-      // 1. two adjacent committed memory regions
-      // 2. committed from the same callsite
-      if (committed_rec == NULL ||
-        committed_rec->base() + committed_rec->size() != vm_ptr->addr() ||
-        committed_rec->pc() != vm_ptr->pc()) {
-        if (!_vm_map->append(vm_ptr)) {
-          return false;
-        }
-        committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1);
-    } else {
-        committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size());
-      }
-      vm_callsite.inc(0, vm_ptr->size());
-    }
-    vm_ptr = (VMMemRegionEx*)vm_itr.next();
+    return true;
   }
-  // deal with last record
-  if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) {
+
+  LinkedList<ReservedMemoryRegion>* virtual_memory_allocations() {
+    return &_virtual_memory_regions;
+  }
+};
+
+
+bool MemBaseline::baseline_summary() {
+  MallocMemorySummary::snapshot(&_malloc_memory_snapshot);
+  VirtualMemorySummary::snapshot(&_virtual_memory_snapshot);
+  return true;
+}
+
+bool MemBaseline::baseline_allocation_sites() {
+  // Malloc allocation sites
+  MallocAllocationSiteWalker malloc_walker;
+  if (!MallocSiteTable::walk_malloc_site(&malloc_walker)) {
     return false;
   }
 
-  // sort it into callsite pc order. Details are aggregated by callsites
-  _vm_cs->sort((FN_SORT)bl_vm_sort_by_pc);
+  _malloc_sites.move(malloc_walker.malloc_sites());
+  // The malloc sites are collected in size order
+  _malloc_sites_order = by_size;
 
-  // walk the array to consolidate record by pc
-  MemPointerArrayIteratorImpl itr(_vm_cs);
-  VMCallsitePointer* callsite_rec = (VMCallsitePointer*)itr.current();
-  VMCallsitePointer* next_rec = (VMCallsitePointer*)itr.next();
-  while (next_rec != NULL) {
-    assert(callsite_rec != NULL, "Sanity check");
-    if (next_rec->addr() == callsite_rec->addr()) {
-      callsite_rec->inc(next_rec->reserved_amount(), next_rec->committed_amount());
-      itr.remove();
-      next_rec = (VMCallsitePointer*)itr.current();
-    } else {
-      callsite_rec = next_rec;
-      next_rec = (VMCallsitePointer*)itr.next();
-    }
+  // Virtual memory allocation sites
+  VirtualMemoryAllocationWalker virtual_memory_walker;
+  if (!VirtualMemoryTracker::walk_virtual_memory(&virtual_memory_walker)) {
+    return false;
+  }
+
+  // Virtual memory allocations are collected in call stack order
+  _virtual_memory_allocations.move(virtual_memory_walker.virtual_memory_allocations());
+
+  if (!aggregate_virtual_memory_allocation_sites()) {
+    return false;
+  }
+  // Virtual memory allocation sites are aggregrated in call stack order
+  _virtual_memory_sites_order = by_address;
+
+  return true;
+}
+
+bool MemBaseline::baseline(bool summaryOnly) {
+  reset();
+
+  _class_count = InstanceKlass::number_of_instance_classes();
+
+  if (!baseline_summary()) {
+    return false;
+  }
+
+  _baseline_type = Summary_baselined;
+
+  // baseline details
+  if (!summaryOnly &&
+      MemTracker::tracking_level() == NMT_detail) {
+    baseline_allocation_sites();
+    _baseline_type = Detail_baselined;
   }
 
   return true;
 }
 
-// baseline a snapshot. If summary_only = false, memory usages aggregated by
-// callsites are also baselined.
-// The method call can be lengthy, especially when detail tracking info is
-// requested. So the method checks for safepoint explicitly.
-bool MemBaseline::baseline(MemSnapshot& snapshot, bool summary_only) {
-  Thread* THREAD = Thread::current();
-  assert(THREAD->is_Java_thread(), "must be a JavaThread");
-  MutexLocker snapshot_locker(snapshot._lock);
-  reset();
-  _baselined = baseline_malloc_summary(snapshot._alloc_ptrs);
-  if (_baselined) {
-    check_safepoint((JavaThread*)THREAD);
-    _baselined = baseline_vm_summary(snapshot._vm_ptrs);
-  }
-  _number_of_classes = snapshot.number_of_classes();
+int compare_allocation_site(const VirtualMemoryAllocationSite& s1,
+  const VirtualMemoryAllocationSite& s2) {
+  return s1.call_stack()->compare(*s2.call_stack());
+}
 
-  if (!summary_only && MemTracker::track_callsite() && _baselined) {
-    check_safepoint((JavaThread*)THREAD);
-    _baselined =  baseline_malloc_details(snapshot._alloc_ptrs);
-    if (_baselined) {
-      check_safepoint((JavaThread*)THREAD);
-      _baselined =  baseline_vm_details(snapshot._vm_ptrs);
+bool MemBaseline::aggregate_virtual_memory_allocation_sites() {
+  SortedLinkedList<VirtualMemoryAllocationSite, compare_allocation_site> allocation_sites;
+
+  VirtualMemoryAllocationIterator itr = virtual_memory_allocations();
+  const ReservedMemoryRegion* rgn;
+  VirtualMemoryAllocationSite* site;
+  while ((rgn = itr.next()) != NULL) {
+    VirtualMemoryAllocationSite tmp(*rgn->call_stack());
+    site = allocation_sites.find(tmp);
+    if (site == NULL) {
+      LinkedListNode<VirtualMemoryAllocationSite>* node =
+        allocation_sites.add(tmp);
+      if (node == NULL) return false;
+      site = node->data();
     }
-  }
-  return _baselined;
-}
-
-
-int MemBaseline::flag2index(MEMFLAGS flag) const {
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    if (MemType2NameMap[index]._flag == flag) {
-      return index;
-    }
-  }
-  assert(false, "no type");
-  return -1;
-}
-
-const char* MemBaseline::type2name(MEMFLAGS type) {
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    if (MemType2NameMap[index]._flag == type) {
-      return MemType2NameMap[index]._name;
-    }
-  }
-  assert(false, err_msg("bad type %x", type));
-  return NULL;
-}
-
-
-MemBaseline& MemBaseline::operator=(const MemBaseline& other) {
-  _total_malloced = other._total_malloced;
-  _total_vm_reserved = other._total_vm_reserved;
-  _total_vm_committed = other._total_vm_committed;
-
-  _baselined = other._baselined;
-  _number_of_classes = other._number_of_classes;
-
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    _malloc_data[index] = other._malloc_data[index];
-    _vm_data[index] = other._vm_data[index];
-    _arena_data[index] = other._arena_data[index];
+    site->reserve_memory(rgn->size());
+    site->commit_memory(rgn->committed_size());
   }
 
-  if (MemTracker::track_callsite()) {
-    assert(_malloc_cs != NULL && _vm_cs != NULL, "out of memory");
-    assert(other._malloc_cs != NULL && other._vm_cs != NULL,
-           "not properly baselined");
-    _malloc_cs->clear();
-    _vm_cs->clear();
-    int index;
-    for (index = 0; index < other._malloc_cs->length(); index ++) {
-      _malloc_cs->append(other._malloc_cs->at(index));
-    }
+  _virtual_memory_sites.move(&allocation_sites);
+  return true;
+}
 
-    for (index = 0; index < other._vm_cs->length(); index ++) {
-      _vm_cs->append(other._vm_cs->at(index));
-    }
+MallocSiteIterator MemBaseline::malloc_sites(SortingOrder order) {
+  assert(!_malloc_sites.is_empty(), "Not detail baseline");
+  switch(order) {
+    case by_size:
+      malloc_sites_to_size_order();
+      break;
+    case by_site:
+      malloc_sites_to_allocation_site_order();
+      break;
+    case by_address:
+    default:
+      ShouldNotReachHere();
   }
-  return *this;
+  return MallocSiteIterator(_malloc_sites.head());
 }
 
-/* compare functions for sorting */
-
-// sort snapshot malloc'd records in callsite pc order
-int MemBaseline::malloc_sort_by_pc(const void* p1, const void* p2) {
-  assert(MemTracker::track_callsite(),"Just check");
-  const MemPointerRecordEx* mp1 = (const MemPointerRecordEx*)p1;
-  const MemPointerRecordEx* mp2 = (const MemPointerRecordEx*)p2;
-  return UNSIGNED_COMPARE(mp1->pc(), mp2->pc());
-}
-
-// sort baselined malloc'd records in size order
-int MemBaseline::bl_malloc_sort_by_size(const void* p1, const void* p2) {
-  assert(MemTracker::is_on(), "Just check");
-  const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1;
-  const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2;
-  return UNSIGNED_COMPARE(mp2->amount(), mp1->amount());
-}
-
-// sort baselined malloc'd records in callsite pc order
-int MemBaseline::bl_malloc_sort_by_pc(const void* p1, const void* p2) {
-  assert(MemTracker::is_on(), "Just check");
-  const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1;
-  const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2;
-  return UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
+VirtualMemorySiteIterator MemBaseline::virtual_memory_sites(SortingOrder order) {
+  assert(!_virtual_memory_sites.is_empty(), "Not detail baseline");
+  switch(order) {
+    case by_size:
+      virtual_memory_sites_to_size_order();
+      break;
+    case by_site:
+      virtual_memory_sites_to_reservation_site_order();
+      break;
+    case by_address:
+    default:
+      ShouldNotReachHere();
+  }
+  return VirtualMemorySiteIterator(_virtual_memory_sites.head());
 }
 
 
-// sort baselined mmap'd records in size (reserved size) order
-int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) {
-  assert(MemTracker::is_on(), "Just check");
-  const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1;
-  const VMCallsitePointer* mp2 = (const VMCallsitePointer*)p2;
-  return UNSIGNED_COMPARE(mp2->reserved_amount(), mp1->reserved_amount());
+// Sorting allocations sites in different orders
+void MemBaseline::malloc_sites_to_size_order() {
+  if (_malloc_sites_order != by_size) {
+    SortedLinkedList<MallocSite, compare_malloc_size> tmp;
+
+    // Add malloc sites to sorted linked list to sort into size order
+    tmp.move(&_malloc_sites);
+    _malloc_sites.set_head(tmp.head());
+    tmp.set_head(NULL);
+    _malloc_sites_order = by_size;
+  }
 }
 
-// sort baselined mmap'd records in callsite pc order
-int MemBaseline::bl_vm_sort_by_pc(const void* p1, const void* p2) {
-  assert(MemTracker::is_on(), "Just check");
-  const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1;
-  const VMCallsitePointer* mp2 = (const VMCallsitePointer*)p2;
-  return UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
+void MemBaseline::malloc_sites_to_allocation_site_order() {
+  if (_malloc_sites_order != by_site) {
+    SortedLinkedList<MallocSite, compare_malloc_site> tmp;
+    // Add malloc sites to sorted linked list to sort into site (address) order
+    tmp.move(&_malloc_sites);
+    _malloc_sites.set_head(tmp.head());
+    tmp.set_head(NULL);
+    _malloc_sites_order = by_site;
+  }
 }
 
+void MemBaseline::virtual_memory_sites_to_size_order() {
+  if (_virtual_memory_sites_order != by_size) {
+    SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_size> tmp;
 
-// sort snapshot malloc'd records in memory block address order
-int MemBaseline::malloc_sort_by_addr(const void* p1, const void* p2) {
-  assert(MemTracker::is_on(), "Just check");
-  const MemPointerRecord* mp1 = (const MemPointerRecord*)p1;
-  const MemPointerRecord* mp2 = (const MemPointerRecord*)p2;
-  int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
-  assert(p1 == p2 || delta != 0, "dup pointer");
-  return delta;
+    tmp.move(&_virtual_memory_sites);
+
+    _virtual_memory_sites.set_head(tmp.head());
+    tmp.set_head(NULL);
+    _virtual_memory_sites_order = by_size;
+  }
+}
+
+void MemBaseline::virtual_memory_sites_to_reservation_site_order() {
+  if (_virtual_memory_sites_order != by_size) {
+    SortedLinkedList<VirtualMemoryAllocationSite, compare_virtual_memory_site> tmp;
+
+    tmp.move(&_virtual_memory_sites);
+
+    _virtual_memory_sites.set_head(tmp.head());
+    tmp.set_head(NULL);
+
+    _virtual_memory_sites_order = by_size;
+  }
 }
 
diff --git a/hotspot/src/share/vm/services/memBaseline.hpp b/hotspot/src/share/vm/services/memBaseline.hpp
index 864c6cc..8272da4 100644
--- a/hotspot/src/share/vm/services/memBaseline.hpp
+++ b/hotspot/src/share/vm/services/memBaseline.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -25,425 +25,181 @@
 #ifndef SHARE_VM_SERVICES_MEM_BASELINE_HPP
 #define SHARE_VM_SERVICES_MEM_BASELINE_HPP
 
+#if INCLUDE_NMT
+
 #include "memory/allocation.hpp"
 #include "runtime/mutex.hpp"
-#include "services/memPtr.hpp"
-#include "services/memSnapshot.hpp"
+#include "services/mallocSiteTable.hpp"
+#include "services/mallocTracker.hpp"
+#include "services/nmtCommon.hpp"
+#include "services/virtualMemoryTracker.hpp"
+#include "utilities/linkedlist.hpp"
 
-// compare unsigned number
-#define UNSIGNED_COMPARE(a, b)  ((a > b) ? 1 : ((a == b) ? 0 : -1))
+typedef LinkedListIterator<MallocSite>                   MallocSiteIterator;
+typedef LinkedListIterator<VirtualMemoryAllocationSite>  VirtualMemorySiteIterator;
+typedef LinkedListIterator<ReservedMemoryRegion>         VirtualMemoryAllocationIterator;
 
 /*
- * MallocCallsitePointer and VMCallsitePointer are used
- * to baseline memory blocks with their callsite information.
- * They are only available when detail tracking is turned
- * on.
- */
-
-/* baselined malloc record aggregated by callsite */
-class MallocCallsitePointer : public MemPointer {
- private:
-  size_t    _count;   // number of malloc invocation from this callsite
-  size_t    _amount;  // total amount of memory malloc-ed from this callsite
-
- public:
-  MallocCallsitePointer() {
-    _count = 0;
-    _amount = 0;
-  }
-
-  MallocCallsitePointer(address pc) : MemPointer(pc) {
-    _count = 0;
-    _amount = 0;
-  }
-
-  MallocCallsitePointer& operator=(const MallocCallsitePointer& p) {
-    MemPointer::operator=(p);
-    _count = p.count();
-    _amount = p.amount();
-    return *this;
-  }
-
-  inline void inc(size_t size) {
-    _count ++;
-    _amount += size;
-  };
-
-  inline size_t count() const {
-    return _count;
-  }
-
-  inline size_t amount() const {
-    return _amount;
-  }
-};
-
-// baselined virtual memory record aggregated by callsite
-class VMCallsitePointer : public MemPointer {
- private:
-  size_t     _count;              // number of invocation from this callsite
-  size_t     _reserved_amount;    // total reserved amount
-  size_t     _committed_amount;   // total committed amount
-
- public:
-  VMCallsitePointer() {
-    _count = 0;
-    _reserved_amount = 0;
-    _committed_amount = 0;
-  }
-
-  VMCallsitePointer(address pc) : MemPointer(pc) {
-    _count = 0;
-    _reserved_amount = 0;
-    _committed_amount = 0;
-  }
-
-  VMCallsitePointer& operator=(const VMCallsitePointer& p) {
-    MemPointer::operator=(p);
-    _count = p.count();
-    _reserved_amount = p.reserved_amount();
-    _committed_amount = p.committed_amount();
-    return *this;
-  }
-
-  inline void inc(size_t reserved, size_t committed) {
-    _count ++;
-    _reserved_amount += reserved;
-    _committed_amount += committed;
-  }
-
-  inline size_t count() const {
-    return _count;
-  }
-
-  inline size_t reserved_amount() const {
-    return _reserved_amount;
-  }
-
-  inline size_t committed_amount() const {
-    return _committed_amount;
-  }
-};
-
-// maps a memory type flag to readable name
-typedef struct _memType2Name {
-  MEMFLAGS     _flag;
-  const char*  _name;
-} MemType2Name;
-
-
-// This class aggregates malloc'd records by memory type
-class MallocMem VALUE_OBJ_CLASS_SPEC {
- private:
-  MEMFLAGS       _type;
-
-  size_t         _count;
-  size_t         _amount;
-
- public:
-  MallocMem() {
-    _type = mtNone;
-    _count = 0;
-    _amount = 0;
-  }
-
-  MallocMem(MEMFLAGS flags) {
-    assert(HAS_VALID_MEMORY_TYPE(flags), "no type");
-    _type = FLAGS_TO_MEMORY_TYPE(flags);
-    _count = 0;
-    _amount = 0;
-  }
-
-  inline void set_type(MEMFLAGS flag) {
-    _type = flag;
-  }
-
-  inline void clear() {
-    _count = 0;
-    _amount = 0;
-    _type = mtNone;
-  }
-
-  MallocMem& operator=(const MallocMem& m) {
-    assert(_type == m.type(), "different type");
-    _count = m.count();
-    _amount = m.amount();
-    return *this;
-  }
-
-  inline void inc(size_t amt) {
-    _amount += amt;
-    _count ++;
-  }
-
-  inline void reduce(size_t amt) {
-    assert(_amount >= amt, "Just check");
-    _amount -= amt;
-  }
-
-  inline void overwrite_counter(size_t count) {
-    _count = count;
-  }
-
-  inline MEMFLAGS type() const {
-    return _type;
-  }
-
-  inline bool is_type(MEMFLAGS flags) const {
-    return FLAGS_TO_MEMORY_TYPE(flags) == _type;
-  }
-
-  inline size_t count() const {
-    return _count;
-  }
-
-  inline size_t amount() const {
-    return _amount;
-  }
-};
-
-// This class records live arena's memory usage
-class ArenaMem : public MallocMem {
- public:
-  ArenaMem(MEMFLAGS typeflag): MallocMem(typeflag) {
-  }
-  ArenaMem() { }
-};
-
-// This class aggregates virtual memory by its memory type
-class VMMem VALUE_OBJ_CLASS_SPEC {
- private:
-  MEMFLAGS       _type;
-
-  size_t         _count;
-  size_t         _reserved_amount;
-  size_t         _committed_amount;
-
- public:
-  VMMem() {
-    _type = mtNone;
-    _count = 0;
-    _reserved_amount = 0;
-    _committed_amount = 0;
-  }
-
-  VMMem(MEMFLAGS flags) {
-    assert(HAS_VALID_MEMORY_TYPE(flags), "no type");
-    _type = FLAGS_TO_MEMORY_TYPE(flags);
-    _count = 0;
-    _reserved_amount = 0;
-    _committed_amount = 0;
-  }
-
-  inline void clear() {
-    _type = mtNone;
-    _count = 0;
-    _reserved_amount = 0;
-    _committed_amount = 0;
-  }
-
-  inline void set_type(MEMFLAGS flags) {
-    _type = FLAGS_TO_MEMORY_TYPE(flags);
-  }
-
-  VMMem& operator=(const VMMem& m) {
-    assert(_type == m.type(), "different type");
-
-    _count = m.count();
-    _reserved_amount = m.reserved_amount();
-    _committed_amount = m.committed_amount();
-    return *this;
-  }
-
-
-  inline MEMFLAGS type() const {
-    return _type;
-  }
-
-  inline bool is_type(MEMFLAGS flags) const {
-    return FLAGS_TO_MEMORY_TYPE(flags) == _type;
-  }
-
-  inline void inc(size_t reserved_amt, size_t committed_amt) {
-    _reserved_amount += reserved_amt;
-    _committed_amount += committed_amt;
-    _count ++;
-  }
-
-  inline size_t count() const {
-    return _count;
-  }
-
-  inline size_t reserved_amount() const {
-    return _reserved_amount;
-  }
-
-  inline size_t committed_amount() const {
-    return _committed_amount;
-  }
-};
-
-
-
-#define NUMBER_OF_MEMORY_TYPE    (mt_number_of_types + 1)
-
-class BaselineReporter;
-class BaselineComparisonReporter;
-
-/*
- * This class baselines current memory snapshot.
- * A memory baseline summarizes memory usage by memory type,
- * aggregates memory usage by callsites when detail tracking
- * is on.
+ * Baseline a memory snapshot
  */
 class MemBaseline VALUE_OBJ_CLASS_SPEC {
-  friend class BaselineReporter;
-  friend class BaselineComparisonReporter;
+ public:
+  enum BaselineThreshold {
+    SIZE_THRESHOLD = K        // Only allocation size over this threshold will be baselined.
+  };
+
+  enum BaselineType {
+    Not_baselined,
+    Summary_baselined,
+    Detail_baselined
+  };
+
+  enum SortingOrder {
+    by_address,   // by memory address
+    by_size,      // by memory size
+    by_site       // by call site where the memory is allocated from
+  };
 
  private:
-  // overall summaries
-  size_t        _total_malloced;
-  size_t        _total_vm_reserved;
-  size_t        _total_vm_committed;
-  size_t        _number_of_classes;
-  size_t        _number_of_threads;
+  // Summary information
+  MallocMemorySnapshot   _malloc_memory_snapshot;
+  VirtualMemorySnapshot  _virtual_memory_snapshot;
 
-  // if it has properly baselined
-  bool          _baselined;
+  size_t               _class_count;
 
-  // we categorize memory into three categories within the memory type
-  MallocMem     _malloc_data[NUMBER_OF_MEMORY_TYPE];
-  VMMem         _vm_data[NUMBER_OF_MEMORY_TYPE];
-  ArenaMem      _arena_data[NUMBER_OF_MEMORY_TYPE];
+  // Allocation sites information
+  // Malloc allocation sites
+  LinkedListImpl<MallocSite>                  _malloc_sites;
 
-  // memory records that aggregate memory usage by callsites.
-  // only available when detail tracking is on.
-  MemPointerArray*  _malloc_cs;
-  MemPointerArray*  _vm_cs;
-  // virtual memory map
-  MemPointerArray*  _vm_map;
+  // All virtual memory allocations
+  LinkedListImpl<ReservedMemoryRegion>        _virtual_memory_allocations;
 
- private:
-  static MemType2Name  MemType2NameMap[NUMBER_OF_MEMORY_TYPE];
+  // Virtual memory allocations by allocation sites, always in by_address
+  // order
+  LinkedListImpl<VirtualMemoryAllocationSite> _virtual_memory_sites;
 
- private:
-  // should not use copy constructor
-  MemBaseline(MemBaseline& copy) { ShouldNotReachHere(); }
+  SortingOrder         _malloc_sites_order;
+  SortingOrder         _virtual_memory_sites_order;
 
-  // check and block at a safepoint
-  static inline void check_safepoint(JavaThread* thr);
+  BaselineType         _baseline_type;
 
  public:
   // create a memory baseline
-  MemBaseline();
-
-  ~MemBaseline();
-
-  inline bool baselined() const {
-    return _baselined;
+  MemBaseline():
+    _baseline_type(Not_baselined),
+    _class_count(0) {
   }
 
-  MemBaseline& operator=(const MemBaseline& other);
+  ~MemBaseline() {
+    reset();
+  }
+
+  bool baseline(bool summaryOnly = true);
+
+  BaselineType baseline_type() const { return _baseline_type; }
+
+  MallocMemorySnapshot* malloc_memory_snapshot() {
+    return &_malloc_memory_snapshot;
+  }
+
+  VirtualMemorySnapshot* virtual_memory_snapshot() {
+    return &_virtual_memory_snapshot;
+  }
+
+  MallocSiteIterator malloc_sites(SortingOrder order);
+  VirtualMemorySiteIterator virtual_memory_sites(SortingOrder order);
+
+  // Virtual memory allocation iterator always returns in virtual memory
+  // base address order.
+  VirtualMemoryAllocationIterator virtual_memory_allocations() {
+    assert(!_virtual_memory_allocations.is_empty(), "Not detail baseline");
+    return VirtualMemoryAllocationIterator(_virtual_memory_allocations.head());
+  }
+
+  // Total reserved memory = total malloc'd memory + total reserved virtual
+  // memory
+  size_t total_reserved_memory() const {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    size_t amount = _malloc_memory_snapshot.total() +
+           _virtual_memory_snapshot.total_reserved();
+    return amount;
+  }
+
+  // Total committed memory = total malloc'd memory + total committed
+  // virtual memory
+  size_t total_committed_memory() const {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    size_t amount = _malloc_memory_snapshot.total() +
+           _virtual_memory_snapshot.total_committed();
+    return amount;
+  }
+
+  size_t total_arena_memory() const {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    return _malloc_memory_snapshot.total_arena();
+  }
+
+  size_t malloc_tracking_overhead() const {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    MemBaseline* bl = const_cast<MemBaseline*>(this);
+    return bl->_malloc_memory_snapshot.malloc_overhead()->size();
+  }
+
+  MallocMemory* malloc_memory(MEMFLAGS flag) {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    return _malloc_memory_snapshot.by_type(flag);
+  }
+
+  VirtualMemory* virtual_memory(MEMFLAGS flag) {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    return _virtual_memory_snapshot.by_type(flag);
+  }
+
+
+  size_t class_count() const {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    return _class_count;
+  }
+
+  size_t thread_count() const {
+    assert(baseline_type() != Not_baselined, "Not yet baselined");
+    return _malloc_memory_snapshot.thread_count();
+  }
 
   // reset the baseline for reuse
-  void clear();
+  void reset() {
+    _baseline_type = Not_baselined;
+    _malloc_memory_snapshot.reset();
+    _virtual_memory_snapshot.reset();
+    _class_count  = 0;
 
-  // baseline the snapshot
-  bool baseline(MemSnapshot& snapshot, bool summary_only = true);
-
-  bool baseline(const MemPointerArray* malloc_records,
-                const MemPointerArray* vm_records,
-                bool summary_only = true);
-
-  // total malloc'd memory of specified memory type
-  inline size_t malloc_amount(MEMFLAGS flag) const {
-    return _malloc_data[flag2index(flag)].amount();
+    _malloc_sites.clear();
+    _virtual_memory_sites.clear();
+    _virtual_memory_allocations.clear();
   }
-  // number of malloc'd memory blocks of specified memory type
-  inline size_t malloc_count(MEMFLAGS flag) const {
-    return _malloc_data[flag2index(flag)].count();
-  }
-  // total memory used by arenas of specified memory type
-  inline size_t arena_amount(MEMFLAGS flag) const {
-    return _arena_data[flag2index(flag)].amount();
-  }
-  // number of arenas of specified memory type
-  inline size_t arena_count(MEMFLAGS flag) const {
-    return _arena_data[flag2index(flag)].count();
-  }
-  // total reserved memory of specified memory type
-  inline size_t reserved_amount(MEMFLAGS flag) const {
-    return _vm_data[flag2index(flag)].reserved_amount();
-  }
-  // total committed memory of specified memory type
-  inline size_t committed_amount(MEMFLAGS flag) const {
-    return _vm_data[flag2index(flag)].committed_amount();
-  }
-  // total memory (malloc'd + mmap'd + arena) of specified
-  // memory type
-  inline size_t total_amount(MEMFLAGS flag) const {
-    int index = flag2index(flag);
-    return _malloc_data[index].amount() +
-           _vm_data[index].reserved_amount() +
-           _arena_data[index].amount();
-  }
-
-  /* overall summaries */
-
-  // total malloc'd memory in snapshot
-  inline size_t total_malloc_amount() const {
-    return _total_malloced;
-  }
-  // total mmap'd memory in snapshot
-  inline size_t total_reserved_amount() const {
-    return _total_vm_reserved;
-  }
-  // total committed memory in snapshot
-  inline size_t total_committed_amount() const {
-    return _total_vm_committed;
-  }
-  // number of loaded classes
-  inline size_t number_of_classes() const {
-    return _number_of_classes;
-  }
-  // number of running threads
-  inline size_t number_of_threads() const {
-    return _number_of_threads;
-  }
-  // lookup human readable name of a memory type
-  static const char* type2name(MEMFLAGS type);
 
  private:
-  // convert memory flag to the index to mapping table
-  int         flag2index(MEMFLAGS flag) const;
+  // Baseline summary information
+  bool baseline_summary();
 
-  // reset baseline values
-  void reset();
+  // Baseline allocation sites (detail tracking only)
+  bool baseline_allocation_sites();
 
-  // summarize the records in global snapshot
-  bool baseline_malloc_summary(const MemPointerArray* malloc_records);
-  bool baseline_vm_summary(const MemPointerArray* vm_records);
-  bool baseline_malloc_details(const MemPointerArray* malloc_records);
-  bool baseline_vm_details(const MemPointerArray* vm_records);
+  // Aggregate virtual memory allocation by allocation sites
+  bool aggregate_virtual_memory_allocation_sites();
 
-  // print a line of malloc'd memory aggregated by callsite
-  void print_malloc_callsite(outputStream* st, address pc, size_t size,
-    size_t count, int diff_amt, int diff_count) const;
-  // print a line of mmap'd memory aggregated by callsite
-  void print_vm_callsite(outputStream* st, address pc, size_t rsz,
-    size_t csz, int diff_rsz, int diff_csz) const;
+  // Sorting allocation sites in different orders
+  // Sort allocation sites in size order
+  void malloc_sites_to_size_order();
+  // Sort allocation sites in call site address order
+  void malloc_sites_to_allocation_site_order();
 
-  // sorting functions for raw records
-  static int malloc_sort_by_pc(const void* p1, const void* p2);
-  static int malloc_sort_by_addr(const void* p1, const void* p2);
-
- private:
-  // sorting functions for baselined records
-  static int bl_malloc_sort_by_size(const void* p1, const void* p2);
-  static int bl_vm_sort_by_size(const void* p1, const void* p2);
-  static int bl_malloc_sort_by_pc(const void* p1, const void* p2);
-  static int bl_vm_sort_by_pc(const void* p1, const void* p2);
+  // Sort allocation sites in reserved size order
+  void virtual_memory_sites_to_size_order();
+  // Sort allocation sites in call site address order
+  void virtual_memory_sites_to_reservation_site_order();
 };
 
+#endif // INCLUDE_NMT
 
 #endif // SHARE_VM_SERVICES_MEM_BASELINE_HPP
diff --git a/hotspot/src/share/vm/services/memPtr.hpp b/hotspot/src/share/vm/services/memPtr.hpp
deleted file mode 100644
index c54f093..0000000
--- a/hotspot/src/share/vm/services/memPtr.hpp
+++ /dev/null
@@ -1,510 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-#ifndef SHARE_VM_SERVICES_MEM_PTR_HPP
-#define SHARE_VM_SERVICES_MEM_PTR_HPP
-
-#include "memory/allocation.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/os.hpp"
-#include "runtime/safepoint.hpp"
-
-/*
- * global sequence generator that generates sequence numbers to serialize
- * memory records.
- */
-class SequenceGenerator : AllStatic {
- public:
-  static jint next();
-
-  // peek last sequence number
-  static jint peek() {
-    return _seq_number;
-  }
-
-  // reset sequence number
-  static void reset() {
-    assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
-    _seq_number = 1;
-    _generation ++;
-  };
-
-  static unsigned long current_generation() { return _generation; }
-  NOT_PRODUCT(static jint max_seq_num() { return _max_seq_number; })
-
- private:
-  static volatile jint             _seq_number;
-  static volatile unsigned long    _generation;
-  NOT_PRODUCT(static jint          _max_seq_number; )
-};
-
-/*
- * followings are the classes that are used to hold memory activity records in different stages.
- *   MemPointer
- *     |--------MemPointerRecord
- *                     |
- *                     |----MemPointerRecordEx
- *                     |           |
- *                     |           |-------SeqMemPointerRecordEx
- *                     |
- *                     |----SeqMemPointerRecord
- *                     |
- *                     |----VMMemRegion
- *                               |
- *                               |-----VMMemRegionEx
- *
- *
- *  prefix 'Seq' - sequenced, the record contains a sequence number
- *  surfix 'Ex'  - extension, the record contains a caller's pc
- *
- *  per-thread recorder : SeqMemPointerRecord(Ex)
- *  snapshot staging    : SeqMemPointerRecord(Ex)
- *  snapshot            : MemPointerRecord(Ex) and VMMemRegion(Ex)
- *
- */
-
-/*
- * class that wraps an address to a memory block,
- * the memory pointer either points to a malloc'd
- * memory block, or a mmap'd memory block
- */
-class MemPointer VALUE_OBJ_CLASS_SPEC {
- public:
-  MemPointer(): _addr(0) { }
-  MemPointer(address addr): _addr(addr) { }
-
-  MemPointer(const MemPointer& copy_from) {
-    _addr = copy_from.addr();
-  }
-
-  inline address addr() const {
-    return _addr;
-  }
-
-  inline operator address() const {
-    return addr();
-  }
-
-  inline bool operator == (const MemPointer& other) const {
-    return addr() == other.addr();
-  }
-
-  inline MemPointer& operator = (const MemPointer& other) {
-    _addr = other.addr();
-    return *this;
-  }
-
- protected:
-  inline void set_addr(address addr) { _addr = addr; }
-
- protected:
-  // memory address
-  address    _addr;
-};
-
-/* MemPointerRecord records an activityand associated
- * attributes on a memory block.
- */
-class MemPointerRecord : public MemPointer {
- private:
-  MEMFLAGS       _flags;
-  size_t         _size;
-
-public:
-  /* extension of MemoryType enum
-   * see share/vm/memory/allocation.hpp for details.
-   *
-   * The tag values are associated to sorting orders, so be
-   * careful if changes are needed.
-   * The allocation records should be sorted ahead of tagging
-   * records, which in turn ahead of deallocation records
-   */
-  enum MemPointerTags {
-    tag_alloc            = 0x0001, // malloc or reserve record
-    tag_commit           = 0x0002, // commit record
-    tag_type             = 0x0003, // tag virtual memory to a memory type
-    tag_uncommit         = 0x0004, // uncommit record
-    tag_release          = 0x0005, // free or release record
-    tag_size             = 0x0006, // arena size
-    tag_masks            = 0x0007, // all tag bits
-    vmBit                = 0x0008
-  };
-
-  /* helper functions to interpret the tagging flags */
-
-  inline static bool is_allocation_record(MEMFLAGS flags) {
-    return (flags & tag_masks) == tag_alloc;
-  }
-
-  inline static bool is_deallocation_record(MEMFLAGS flags) {
-    return (flags & tag_masks) == tag_release;
-  }
-
-  inline static bool is_arena_record(MEMFLAGS flags) {
-    return (flags & (otArena | tag_size)) == otArena;
-  }
-
-  inline static bool is_arena_memory_record(MEMFLAGS flags) {
-    return (flags & (otArena | tag_size)) == (otArena | tag_size);
-  }
-
-  inline static bool is_virtual_memory_record(MEMFLAGS flags) {
-    return (flags & vmBit) != 0;
-  }
-
-  inline static bool is_virtual_memory_reserve_record(MEMFLAGS flags) {
-    return (flags & 0x0F) == (tag_alloc | vmBit);
-  }
-
-  inline static bool is_virtual_memory_commit_record(MEMFLAGS flags) {
-    return (flags & 0x0F) == (tag_commit | vmBit);
-  }
-
-  inline static bool is_virtual_memory_uncommit_record(MEMFLAGS flags) {
-    return (flags & 0x0F) == (tag_uncommit | vmBit);
-  }
-
-  inline static bool is_virtual_memory_release_record(MEMFLAGS flags) {
-    return (flags & 0x0F) == (tag_release | vmBit);
-  }
-
-  inline static bool is_virtual_memory_type_record(MEMFLAGS flags) {
-    return (flags & 0x0F) == (tag_type | vmBit);
-  }
-
-  /* tagging flags */
-  inline static MEMFLAGS malloc_tag()                 { return tag_alloc;   }
-  inline static MEMFLAGS free_tag()                   { return tag_release; }
-  inline static MEMFLAGS arena_size_tag()             { return tag_size | otArena; }
-  inline static MEMFLAGS virtual_memory_tag()         { return vmBit; }
-  inline static MEMFLAGS virtual_memory_reserve_tag() { return (tag_alloc | vmBit); }
-  inline static MEMFLAGS virtual_memory_commit_tag()  { return (tag_commit | vmBit); }
-  inline static MEMFLAGS virtual_memory_uncommit_tag(){ return (tag_uncommit | vmBit); }
-  inline static MEMFLAGS virtual_memory_release_tag() { return (tag_release | vmBit); }
-  inline static MEMFLAGS virtual_memory_type_tag()    { return (tag_type | vmBit); }
-
- public:
-  MemPointerRecord(): _size(0), _flags(mtNone) { }
-
-  MemPointerRecord(address addr, MEMFLAGS memflags, size_t size = 0):
-      MemPointer(addr), _flags(memflags), _size(size) { }
-
-  MemPointerRecord(const MemPointerRecord& copy_from):
-    MemPointer(copy_from), _flags(copy_from.flags()),
-    _size(copy_from.size()) {
-  }
-
-  /* MemPointerRecord is not sequenced, it always return
-   * 0 to indicate non-sequenced
-   */
-  virtual jint seq() const               { return 0; }
-
-  inline size_t   size()  const          { return _size; }
-  inline void set_size(size_t size)      { _size = size; }
-
-  inline MEMFLAGS flags() const          { return _flags; }
-  inline void set_flags(MEMFLAGS flags)  { _flags = flags; }
-
-  MemPointerRecord& operator= (const MemPointerRecord& ptr) {
-    MemPointer::operator=(ptr);
-    _flags = ptr.flags();
-#ifdef ASSERT
-    if (IS_ARENA_OBJ(_flags)) {
-      assert(!is_vm_pointer(), "wrong flags");
-      assert((_flags & ot_masks) == otArena, "wrong flags");
-    }
-#endif
-    _size = ptr.size();
-    return *this;
-  }
-
-  // if the pointer represents a malloc-ed memory address
-  inline bool is_malloced_pointer() const {
-    return !is_vm_pointer();
-  }
-
-  // if the pointer represents a virtual memory address
-  inline bool is_vm_pointer() const {
-    return is_virtual_memory_record(_flags);
-  }
-
-  // if this record records a 'malloc' or virtual memory
-  // 'reserve' call
-  inline bool is_allocation_record() const {
-    return is_allocation_record(_flags);
-  }
-
-  // if this record records a size information of an arena
-  inline bool is_arena_memory_record() const {
-    return is_arena_memory_record(_flags);
-  }
-
-  // if this pointer represents an address to an arena object
-  inline bool is_arena_record() const {
-    return is_arena_record(_flags);
-  }
-
-  // if this record represents a size information of specific arena
-  inline bool is_memory_record_of_arena(const MemPointerRecord* arena_rc) {
-    assert(is_arena_memory_record(), "not size record");
-    assert(arena_rc->is_arena_record(), "not arena record");
-    return (arena_rc->addr() + sizeof(void*)) == addr();
-  }
-
-  // if this record records a 'free' or virtual memory 'free' call
-  inline bool is_deallocation_record() const {
-    return is_deallocation_record(_flags);
-  }
-
-  // if this record records a virtual memory 'commit' call
-  inline bool is_commit_record() const {
-    return is_virtual_memory_commit_record(_flags);
-  }
-
-  // if this record records a virtual memory 'uncommit' call
-  inline bool is_uncommit_record() const {
-    return is_virtual_memory_uncommit_record(_flags);
-  }
-
-  // if this record is a tagging record of a virtual memory block
-  inline bool is_type_tagging_record() const {
-    return is_virtual_memory_type_record(_flags);
-  }
-
-  // if the two memory pointer records actually represent the same
-  // memory block
-  inline bool is_same_region(const MemPointerRecord* other) const {
-    return (addr() == other->addr() && size() == other->size());
-  }
-
-  // if this memory region fully contains another one
-  inline bool contains_region(const MemPointerRecord* other) const {
-    return contains_region(other->addr(), other->size());
-  }
-
-  // if this memory region fully contains specified memory range
-  inline bool contains_region(address add, size_t sz) const {
-    return (addr() <= add && addr() + size() >= add + sz);
-  }
-
-  inline bool contains_address(address add) const {
-    return (addr() <= add && addr() + size() > add);
-  }
-
-  // if this memory region overlaps another region
-  inline bool overlaps_region(const MemPointerRecord* other) const {
-    assert(other != NULL, "Just check");
-    assert(size() > 0 && other->size() > 0, "empty range");
-    return contains_address(other->addr()) ||
-           contains_address(other->addr() + other->size() - 1) || // exclude end address
-           other->contains_address(addr()) ||
-           other->contains_address(addr() + size() - 1); // exclude end address
-  }
-
-};
-
-// MemPointerRecordEx also records callsite pc, from where
-// the memory block is allocated
-class MemPointerRecordEx : public MemPointerRecord {
- private:
-  address      _pc;  // callsite pc
-
- public:
-  MemPointerRecordEx(): _pc(0) { }
-
-  MemPointerRecordEx(address addr, MEMFLAGS memflags, size_t size = 0, address pc = 0):
-    MemPointerRecord(addr, memflags, size), _pc(pc) {}
-
-  MemPointerRecordEx(const MemPointerRecordEx& copy_from):
-    MemPointerRecord(copy_from), _pc(copy_from.pc()) {}
-
-  inline address pc() const { return _pc; }
-
-  void init(const MemPointerRecordEx* mpe) {
-    MemPointerRecord::operator=(*mpe);
-    _pc = mpe->pc();
-  }
-
-  void init(const MemPointerRecord* mp) {
-    MemPointerRecord::operator=(*mp);
-    _pc = 0;
-  }
-};
-
-// a virtual memory region. The region can represent a reserved
-// virtual memory region or a committed memory region
-class VMMemRegion : public MemPointerRecord {
-public:
-  VMMemRegion() { }
-
-  void init(const MemPointerRecord* mp) {
-    assert(mp->is_vm_pointer(), "Sanity check");
-    _addr = mp->addr();
-      set_size(mp->size());
-    set_flags(mp->flags());
-  }
-
-  VMMemRegion& operator=(const VMMemRegion& other) {
-    MemPointerRecord::operator=(other);
-    return *this;
-  }
-
-  inline bool is_reserved_region() const {
-    return is_allocation_record();
-  }
-
-  inline bool is_committed_region() const {
-    return is_commit_record();
-  }
-
-  /* base address of this virtual memory range */
-  inline address base() const {
-    return addr();
-  }
-
-  /* tag this virtual memory range to the specified memory type */
-  inline void tag(MEMFLAGS f) {
-    set_flags(flags() | (f & mt_masks));
-  }
-
-  // expand this region to also cover specified range.
-  // The range has to be on either end of the memory region.
-  void expand_region(address addr, size_t sz) {
-    if (addr < base()) {
-      assert(addr + sz == base(), "Sanity check");
-      _addr = addr;
-      set_size(size() + sz);
-    } else {
-      assert(base() + size() == addr, "Sanity check");
-      set_size(size() + sz);
-    }
-  }
-
-  // exclude the specified address range from this region.
-  // The excluded memory range has to be on either end of this memory
-  // region.
-  inline void exclude_region(address add, size_t sz) {
-    assert(is_reserved_region() || is_committed_region(), "Sanity check");
-    assert(addr() != NULL && size() != 0, "Sanity check");
-    assert(add >= addr() && add < addr() + size(), "Sanity check");
-    assert(add == addr() || (add + sz) == (addr() + size()),
-      "exclude in the middle");
-    if (add == addr()) {
-      set_addr(add + sz);
-      set_size(size() - sz);
-    } else {
-      set_size(size() - sz);
-    }
-  }
-};
-
-class VMMemRegionEx : public VMMemRegion {
- private:
-  jint   _seq;  // sequence number
-
- public:
-  VMMemRegionEx(): _pc(0) { }
-
-  void init(const MemPointerRecordEx* mpe) {
-    VMMemRegion::init(mpe);
-    _pc = mpe->pc();
-  }
-
-  void init(const MemPointerRecord* mpe) {
-    VMMemRegion::init(mpe);
-    _pc = 0;
-  }
-
-  VMMemRegionEx& operator=(const VMMemRegionEx& other) {
-    VMMemRegion::operator=(other);
-    _pc = other.pc();
-    return *this;
-  }
-
-  inline address pc() const { return _pc; }
- private:
-  address   _pc;
-};
-
-/*
- * Sequenced memory record
- */
-class SeqMemPointerRecord : public MemPointerRecord {
- private:
-   jint _seq;  // sequence number
-
- public:
-  SeqMemPointerRecord(): _seq(0){ }
-
-  SeqMemPointerRecord(address addr, MEMFLAGS flags, size_t size, jint seq)
-    : MemPointerRecord(addr, flags, size), _seq(seq)  {
-  }
-
-  SeqMemPointerRecord(const SeqMemPointerRecord& copy_from)
-    : MemPointerRecord(copy_from) {
-    _seq = copy_from.seq();
-  }
-
-  SeqMemPointerRecord& operator= (const SeqMemPointerRecord& ptr) {
-    MemPointerRecord::operator=(ptr);
-    _seq = ptr.seq();
-    return *this;
-  }
-
-  inline jint seq() const {
-    return _seq;
-  }
-};
-
-
-
-class SeqMemPointerRecordEx : public MemPointerRecordEx {
- private:
-  jint    _seq;  // sequence number
-
- public:
-  SeqMemPointerRecordEx(): _seq(0) { }
-
-  SeqMemPointerRecordEx(address addr, MEMFLAGS flags, size_t size,
-    jint seq, address pc):
-    MemPointerRecordEx(addr, flags, size, pc), _seq(seq)  {
-  }
-
-  SeqMemPointerRecordEx(const SeqMemPointerRecordEx& copy_from)
-    : MemPointerRecordEx(copy_from) {
-    _seq = copy_from.seq();
-  }
-
-  SeqMemPointerRecordEx& operator= (const SeqMemPointerRecordEx& ptr) {
-    MemPointerRecordEx::operator=(ptr);
-    _seq = ptr.seq();
-    return *this;
-  }
-
-  inline jint seq() const {
-    return _seq;
-  }
-};
-
-#endif // SHARE_VM_SERVICES_MEM_PTR_HPP
diff --git a/hotspot/src/share/vm/services/memPtrArray.hpp b/hotspot/src/share/vm/services/memPtrArray.hpp
deleted file mode 100644
index b3e48f6..0000000
--- a/hotspot/src/share/vm/services/memPtrArray.hpp
+++ /dev/null
@@ -1,306 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-#ifndef SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP
-#define SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP
-
-#include "memory/allocation.hpp"
-#include "services/memPtr.hpp"
-
-class MemPtr;
-class MemRecorder;
-class ArenaInfo;
-class MemSnapshot;
-
-extern "C" {
-  typedef int (*FN_SORT)(const void *, const void *);
-}
-
-
-// Memory pointer array interface. This array is used by NMT to hold
-// various memory block information.
-// The memory pointer arrays are usually walked with their iterators.
-
-class MemPointerArray : public CHeapObj<mtNMT> {
- public:
-  virtual ~MemPointerArray() { }
-
-  // return true if it can not allocate storage for the data
-  virtual bool out_of_memory() const = 0;
-  virtual bool is_empty() const = 0;
-  virtual bool is_full() = 0;
-  virtual int  length() const = 0;
-  virtual void clear() = 0;
-  virtual bool append(MemPointer* ptr) = 0;
-  virtual bool insert_at(MemPointer* ptr, int pos) = 0;
-  virtual bool remove_at(int pos) = 0;
-  virtual MemPointer* at(int index) const = 0;
-  virtual void sort(FN_SORT fn) = 0;
-  virtual size_t instance_size() const = 0;
-  virtual bool shrink() = 0;
-
-  NOT_PRODUCT(virtual int capacity() const = 0;)
-};
-
-// Iterator interface
-class MemPointerArrayIterator VALUE_OBJ_CLASS_SPEC {
- public:
-  // return the pointer at current position
-  virtual MemPointer* current() const = 0;
-  // return the next pointer and advance current position
-  virtual MemPointer* next() = 0;
-  // return next pointer without advancing current position
-  virtual MemPointer* peek_next() const = 0;
-  // return previous pointer without changing current position
-  virtual MemPointer* peek_prev() const = 0;
-  // remove the pointer at current position
-  virtual void        remove() = 0;
-  // insert the pointer at current position
-  virtual bool        insert(MemPointer* ptr) = 0;
-  // insert specified element after current position and
-  // move current position to newly inserted position
-  virtual bool        insert_after(MemPointer* ptr) = 0;
-};
-
-// implementation class
-class MemPointerArrayIteratorImpl : public MemPointerArrayIterator {
- protected:
-  MemPointerArray*  _array;
-  int               _pos;
-
- public:
-  MemPointerArrayIteratorImpl(MemPointerArray* arr) {
-    assert(arr != NULL, "Parameter check");
-    _array = arr;
-    _pos = 0;
-  }
-
-  virtual MemPointer* current() const {
-    if (_pos < _array->length()) {
-      return _array->at(_pos);
-    }
-    return NULL;
-  }
-
-  virtual MemPointer* next() {
-    if (_pos + 1 < _array->length()) {
-      return _array->at(++_pos);
-    }
-    _pos = _array->length();
-    return NULL;
-  }
-
-  virtual MemPointer* peek_next() const {
-    if (_pos + 1 < _array->length()) {
-      return _array->at(_pos + 1);
-    }
-    return NULL;
-  }
-
-  virtual MemPointer* peek_prev() const {
-    if (_pos > 0) {
-      return _array->at(_pos - 1);
-    }
-    return NULL;
-  }
-
-  virtual void remove() {
-    if (_pos < _array->length()) {
-      _array->remove_at(_pos);
-    }
-  }
-
-  virtual bool insert(MemPointer* ptr) {
-    return _array->insert_at(ptr, _pos);
-  }
-
-  virtual bool insert_after(MemPointer* ptr) {
-    if (_array->insert_at(ptr, _pos + 1)) {
-      _pos ++;
-      return true;
-    }
-    return false;
-  }
-};
-
-
-
-// Memory pointer array implementation.
-// This implementation implements expandable array
-#define DEFAULT_PTR_ARRAY_SIZE 1024
-
-template <class E> class MemPointerArrayImpl : public MemPointerArray {
- private:
-  int                   _max_size;
-  int                   _size;
-  bool                  _init_elements;
-  E*                    _data;
-
- public:
-  MemPointerArrayImpl(int initial_size = DEFAULT_PTR_ARRAY_SIZE, bool init_elements = true):
-   _max_size(initial_size), _size(0), _init_elements(init_elements) {
-    _data = (E*)raw_allocate(sizeof(E), initial_size);
-    if (_init_elements) {
-      for (int index = 0; index < _max_size; index ++) {
-        ::new ((void*)&_data[index]) E();
-      }
-    }
-  }
-
-  virtual ~MemPointerArrayImpl() {
-    if (_data != NULL) {
-      raw_free(_data);
-    }
-  }
-
- public:
-  bool out_of_memory() const {
-    return (_data == NULL);
-  }
-
-  size_t instance_size() const {
-    return sizeof(MemPointerArrayImpl<E>) + _max_size * sizeof(E);
-  }
-
-  bool is_empty() const {
-    assert(_data != NULL, "Just check");
-    return _size == 0;
-  }
-
-  bool is_full() {
-    assert(_data != NULL, "Just check");
-    if (_size < _max_size) {
-      return false;
-    } else {
-      return !expand_array();
-    }
-  }
-
-  int length() const {
-    assert(_data != NULL, "Just check");
-    return _size;
-  }
-
-  NOT_PRODUCT(int capacity() const { return _max_size; })
-
-  void clear() {
-    assert(_data != NULL, "Just check");
-    _size = 0;
-  }
-
-  bool append(MemPointer* ptr) {
-    assert(_data != NULL, "Just check");
-    if (is_full()) {
-      return false;
-    }
-    _data[_size ++] = *(E*)ptr;
-    return true;
-  }
-
-  bool insert_at(MemPointer* ptr, int pos) {
-    assert(_data != NULL, "Just check");
-    if (is_full()) {
-      return false;
-    }
-    for (int index = _size; index > pos; index --) {
-      _data[index] = _data[index - 1];
-    }
-    _data[pos] = *(E*)ptr;
-    _size ++;
-    return true;
-  }
-
-  bool remove_at(int pos) {
-    assert(_data != NULL, "Just check");
-    if (_size <= pos && pos >= 0) {
-      return false;
-    }
-    -- _size;
-
-    for (int index = pos; index < _size; index ++) {
-      _data[index] = _data[index + 1];
-    }
-    return true;
-  }
-
-  MemPointer* at(int index) const {
-    assert(_data != NULL, "Just check");
-    assert(index >= 0 && index < _size, "illegal index");
-    return &_data[index];
-  }
-
-  bool shrink() {
-    float used = ((float)_size) / ((float)_max_size);
-    if (used < 0.40) {
-      E* old_ptr = _data;
-      int new_size = ((_max_size) / (2 * DEFAULT_PTR_ARRAY_SIZE) + 1) * DEFAULT_PTR_ARRAY_SIZE;
-      _data = (E*)raw_reallocate(_data, sizeof(E), new_size);
-      if (_data == NULL) {
-        _data = old_ptr;
-        return false;
-      } else {
-        _max_size = new_size;
-        return true;
-      }
-    }
-    return false;
-  }
-
-  void sort(FN_SORT fn) {
-    assert(_data != NULL, "Just check");
-    qsort((void*)_data, _size, sizeof(E), fn);
-  }
-
- private:
-  bool  expand_array() {
-    assert(_data != NULL, "Not yet allocated");
-    E* old_ptr = _data;
-    if ((_data = (E*)raw_reallocate((void*)_data, sizeof(E),
-      _max_size + DEFAULT_PTR_ARRAY_SIZE)) == NULL) {
-      _data = old_ptr;
-      return false;
-    } else {
-      _max_size += DEFAULT_PTR_ARRAY_SIZE;
-      if (_init_elements) {
-        for (int index = _size; index < _max_size; index ++) {
-          ::new ((void*)&_data[index]) E();
-        }
-      }
-      return true;
-    }
-  }
-
-  void* raw_allocate(size_t elementSize, int items) {
-    return os::malloc(elementSize * items, mtNMT);
-  }
-
-  void* raw_reallocate(void* ptr, size_t elementSize, int items) {
-    return os::realloc(ptr, elementSize * items, mtNMT);
-  }
-
-  void  raw_free(void* ptr) {
-    os::free(ptr, mtNMT);
-  }
-};
-
-#endif // SHARE_VM_UTILITIES_MEM_PTR_ARRAY_HPP
diff --git a/hotspot/src/share/vm/services/memRecorder.cpp b/hotspot/src/share/vm/services/memRecorder.cpp
deleted file mode 100644
index afe7bd2..0000000
--- a/hotspot/src/share/vm/services/memRecorder.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-#include "precompiled.hpp"
-
-#include "runtime/atomic.hpp"
-#include "services/memBaseline.hpp"
-#include "services/memRecorder.hpp"
-#include "services/memPtr.hpp"
-#include "services/memTracker.hpp"
-
-MemPointer* SequencedRecordIterator::next_record() {
-  MemPointerRecord* itr_cur = (MemPointerRecord*)_itr.current();
-  if (itr_cur == NULL)  {
-    return itr_cur;
-  }
-
-  MemPointerRecord* itr_next = (MemPointerRecord*)_itr.next();
-
-  // don't collapse virtual memory records
-  while (itr_next != NULL && !itr_cur->is_vm_pointer() &&
-    !itr_next->is_vm_pointer() &&
-    same_kind(itr_cur, itr_next)) {
-    itr_cur = itr_next;
-    itr_next = (MemPointerRecord*)_itr.next();
-  }
-
-  return itr_cur;
-}
-
-
-volatile jint MemRecorder::_instance_count = 0;
-
-MemRecorder::MemRecorder() {
-  assert(MemTracker::is_on(), "Native memory tracking is off");
-  Atomic::inc(&_instance_count);
-  set_generation();
-
-  if (MemTracker::track_callsite()) {
-    _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecordEx,
-        DEFAULT_RECORDER_PTR_ARRAY_SIZE>();
-  } else {
-    _pointer_records = new (std::nothrow)FixedSizeMemPointerArray<SeqMemPointerRecord,
-        DEFAULT_RECORDER_PTR_ARRAY_SIZE>();
-  }
-  _next = NULL;
-
-
-  if (_pointer_records != NULL) {
-    // recode itself
-    address pc = CURRENT_PC;
-    record((address)this, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder),
-        sizeof(MemRecorder), SequenceGenerator::next(), pc);
-    record((address)_pointer_records, (MemPointerRecord::malloc_tag()|mtNMT|otNMTRecorder),
-        _pointer_records->instance_size(), SequenceGenerator::next(), pc);
-  }
-}
-
-MemRecorder::~MemRecorder() {
-  if (_pointer_records != NULL) {
-    if (MemTracker::is_on()) {
-      MemTracker::record_free((address)_pointer_records, mtNMT);
-      MemTracker::record_free((address)this, mtNMT);
-    }
-    delete _pointer_records;
-  }
-  // delete all linked recorders
-  while (_next != NULL) {
-    MemRecorder* tmp = _next;
-    _next = _next->next();
-    tmp->set_next(NULL);
-    delete tmp;
-  }
-  Atomic::dec(&_instance_count);
-}
-
-// Sorting order:
-//   1. memory block address
-//   2. mem pointer record tags
-//   3. sequence number
-int MemRecorder::sort_record_fn(const void* e1, const void* e2) {
-  const MemPointerRecord* p1 = (const MemPointerRecord*)e1;
-  const MemPointerRecord* p2 = (const MemPointerRecord*)e2;
-  int delta = UNSIGNED_COMPARE(p1->addr(), p2->addr());
-  if (delta == 0) {
-    int df = UNSIGNED_COMPARE((p1->flags() & MemPointerRecord::tag_masks),
-                              (p2->flags() & MemPointerRecord::tag_masks));
-    if (df == 0) {
-      assert(p1->seq() != p2->seq(), "dup seq");
-      return p1->seq() - p2->seq();
-    } else {
-      return df;
-    }
-  } else {
-    return delta;
-  }
-}
-
-bool MemRecorder::record(address p, MEMFLAGS flags, size_t size, jint seq, address pc) {
-  assert(seq > 0, "No sequence number");
-#ifdef ASSERT
-  if (MemPointerRecord::is_virtual_memory_record(flags)) {
-    assert((flags & MemPointerRecord::tag_masks) != 0, "bad virtual memory record");
-  } else {
-    assert((flags & MemPointerRecord::tag_masks) == MemPointerRecord::malloc_tag() ||
-           (flags & MemPointerRecord::tag_masks) == MemPointerRecord::free_tag() ||
-           IS_ARENA_OBJ(flags),
-           "bad malloc record");
-  }
-  // a recorder should only hold records within the same generation
-  unsigned long cur_generation = SequenceGenerator::current_generation();
-  assert(cur_generation == _generation,
-         "this thread did not enter sync point");
-#endif
-
-  if (MemTracker::track_callsite()) {
-    SeqMemPointerRecordEx ap(p, flags, size, seq, pc);
-    debug_only(check_dup_seq(ap.seq());)
-    return _pointer_records->append(&ap);
-  } else {
-    SeqMemPointerRecord ap(p, flags, size, seq);
-    debug_only(check_dup_seq(ap.seq());)
-    return _pointer_records->append(&ap);
-  }
-}
-
-  // iterator for alloc pointers
-SequencedRecordIterator MemRecorder::pointer_itr() {
-  assert(_pointer_records != NULL, "just check");
-  _pointer_records->sort((FN_SORT)sort_record_fn);
-  return SequencedRecordIterator(_pointer_records);
-}
-
-
-void MemRecorder::set_generation() {
-  _generation = SequenceGenerator::current_generation();
-}
-
-#ifdef ASSERT
-
-void MemRecorder::check_dup_seq(jint seq) const {
-  MemPointerArrayIteratorImpl itr(_pointer_records);
-  MemPointerRecord* rc = (MemPointerRecord*)itr.current();
-  while (rc != NULL) {
-    assert(rc->seq() != seq, "dup seq");
-    rc = (MemPointerRecord*)itr.next();
-  }
-}
-
-#endif
diff --git a/hotspot/src/share/vm/services/memRecorder.hpp b/hotspot/src/share/vm/services/memRecorder.hpp
deleted file mode 100644
index 4329dad..0000000
--- a/hotspot/src/share/vm/services/memRecorder.hpp
+++ /dev/null
@@ -1,271 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-#ifndef SHARE_VM_SERVICES_MEM_RECORDER_HPP
-#define SHARE_VM_SERVICES_MEM_RECORDER_HPP
-
-#include "memory/allocation.hpp"
-#include "runtime/os.hpp"
-#include "services/memPtrArray.hpp"
-
-class MemSnapshot;
-class MemTracker;
-class MemTrackWorker;
-
-// Fixed size memory pointer array implementation
-template <class E, int SIZE> class FixedSizeMemPointerArray :
-  public MemPointerArray {
-  // This implementation is for memory recorder only
-  friend class MemRecorder;
-
- private:
-  E      _data[SIZE];
-  int    _size;
-
- protected:
-  FixedSizeMemPointerArray(bool init_elements = false):
-   _size(0){
-    if (init_elements) {
-      for (int index = 0; index < SIZE; index ++) {
-        ::new ((void*)&_data[index]) E();
-      }
-    }
-  }
-
-  void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
-    // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder'
-    // to avoid recursion
-    return os::malloc(size, (mtNMT | otNMTRecorder));
-  }
-
-  void* operator new(size_t size) throw() {
-    assert(false, "use nothrow version");
-    return NULL;
-  }
-
-  void operator delete(void* p) {
-    os::free(p, (mtNMT | otNMTRecorder));
-  }
-
-  // instance size
-  inline size_t instance_size() const {
-    return sizeof(FixedSizeMemPointerArray<E, SIZE>);
-  }
-
-  NOT_PRODUCT(int capacity() const { return SIZE; })
-
- public:
-  // implementation of public interface
-  bool out_of_memory() const { return false; }
-  bool is_empty()      const { return _size == 0; }
-  bool is_full()             { return length() >= SIZE; }
-  int  length()        const { return _size; }
-
-  void clear() {
-    _size = 0;
-  }
-
-  bool append(MemPointer* ptr) {
-    if (is_full()) return false;
-    _data[_size ++] = *(E*)ptr;
-    return true;
-  }
-
-  virtual bool insert_at(MemPointer* p, int pos) {
-    assert(false, "append only");
-    return false;
-  }
-
-  virtual bool remove_at(int pos) {
-    assert(false, "not supported");
-    return false;
-  }
-
-  MemPointer* at(int index) const {
-    assert(index >= 0 && index < length(),
-      "parameter check");
-    return ((E*)&_data[index]);
-  }
-
-  void sort(FN_SORT fn) {
-    qsort((void*)_data, _size, sizeof(E), fn);
-  }
-
-  bool shrink() {
-    return false;
-  }
-};
-
-
-// This iterator requires pre-sorted MemPointerArray, which is sorted by:
-//  1. address
-//  2. allocation type
-//  3. sequence number
-// During the array walking, iterator collapses pointers with the same
-// address and allocation type, and only returns the one with highest
-// sequence number.
-//
-// This is read-only iterator, update methods are asserted.
-class SequencedRecordIterator : public MemPointerArrayIterator {
- private:
-   MemPointerArrayIteratorImpl _itr;
-   MemPointer*                 _cur;
-
- public:
-  SequencedRecordIterator(const MemPointerArray* arr):
-    _itr(const_cast<MemPointerArray*>(arr)) {
-    _cur = next_record();
-  }
-
-  SequencedRecordIterator(const SequencedRecordIterator& itr):
-    _itr(itr._itr) {
-    _cur = next_record();
-  }
-
-  // return the pointer at current position
-  virtual MemPointer* current() const {
-    return _cur;
-  };
-
-  // return the next pointer and advance current position
-  virtual MemPointer* next() {
-    _cur = next_record();
-    return _cur;
-  }
-
-  // return the next pointer without advancing current position
-  virtual MemPointer* peek_next() const {
-    assert(false, "not implemented");
-    return NULL;
-
-  }
-  // return the previous pointer without changing current position
-  virtual MemPointer* peek_prev() const {
-    assert(false, "not implemented");
-    return NULL;
-  }
-
-  // remove the pointer at current position
-  virtual void remove() {
-    assert(false, "read-only iterator");
-  };
-  // insert the pointer at current position
-  virtual bool insert(MemPointer* ptr) {
-    assert(false, "read-only iterator");
-    return false;
-  }
-
-  virtual bool insert_after(MemPointer* ptr) {
-    assert(false, "read-only iterator");
-    return false;
-  }
- private:
-  // collapse the 'same kind' of records, and return this 'kind' of
-  // record with highest sequence number
-  MemPointer* next_record();
-
-  // Test if the two records are the same kind: the same memory block and allocation
-  // type.
-  inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const {
-    assert(!p1->is_vm_pointer() && !p2->is_vm_pointer(), "malloc pointer only");
-    return (p1->addr() == p2->addr() &&
-      (p1->flags() &MemPointerRecord::tag_masks) ==
-      (p2->flags() & MemPointerRecord::tag_masks));
-  }
-};
-
-
-
-#define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512
-
-class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
-  friend class MemSnapshot;
-  friend class MemTracker;
-  friend class MemTrackWorker;
-  friend class GenerationData;
-
- protected:
-  // the array that holds memory records
-  MemPointerArray*         _pointer_records;
-
- private:
-  // used for linked list
-  MemRecorder*             _next;
-  // active recorder can only record a certain generation data
-  unsigned long            _generation;
-
- protected:
-  _NOINLINE_ MemRecorder();
-  ~MemRecorder();
-
-  // record a memory operation
-  bool record(address addr, MEMFLAGS flags, size_t size, jint seq, address caller_pc = 0);
-
-  // linked list support
-  inline void set_next(MemRecorder* rec) {
-    _next = rec;
-  }
-
-  inline MemRecorder* next() const {
-    return _next;
-  }
-
-  // if the recorder is full
-  inline bool is_full() const {
-    assert(_pointer_records != NULL, "just check");
-    return _pointer_records->is_full();
-  }
-
-  // if running out of memory when initializing recorder's internal
-  // data
-  inline bool out_of_memory() const {
-    return (_pointer_records == NULL ||
-      _pointer_records->out_of_memory());
-  }
-
-  inline void clear() {
-    assert(_pointer_records != NULL, "Just check");
-    _pointer_records->clear();
-  }
-
-  SequencedRecordIterator pointer_itr();
-
-  // return the generation of this recorder which it belongs to
-  unsigned long get_generation() const { return _generation; }
- protected:
-  // number of MemRecorder instance
-  static volatile jint _instance_count;
-
- private:
-  // sorting function, sort records into following order
-  // 1. memory address
-  // 2. allocation type
-  // 3. sequence number
-  static int sort_record_fn(const void* e1, const void* e2);
-
-  debug_only(void check_dup_seq(jint seq) const;)
-  void set_generation();
-};
-
-#endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP
diff --git a/hotspot/src/share/vm/services/memReporter.cpp b/hotspot/src/share/vm/services/memReporter.cpp
index 305693d..0269619 100644
--- a/hotspot/src/share/vm/services/memReporter.cpp
+++ b/hotspot/src/share/vm/services/memReporter.cpp
@@ -22,618 +22,595 @@
  *
  */
 #include "precompiled.hpp"
-#include "classfile/systemDictionary.hpp"
-#include "runtime/os.hpp"
+
+#include "memory/allocation.hpp"
+#include "services/mallocTracker.hpp"
 #include "services/memReporter.hpp"
-#include "services/memPtrArray.hpp"
-#include "services/memTracker.hpp"
+#include "services/virtualMemoryTracker.hpp"
+#include "utilities/globalDefinitions.hpp"
 
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
+size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const {
+  return malloc->malloc_size() + malloc->arena_size() + vm->reserved();
+}
 
-const char* BaselineOutputer::memory_unit(size_t scale) {
-  switch(scale) {
-    case K: return "KB";
-    case M: return "MB";
-    case G: return "GB";
+size_t MemReporterBase::committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const {
+  return malloc->malloc_size() + malloc->arena_size() + vm->committed();
+}
+
+void MemReporterBase::print_total(size_t reserved, size_t committed) const {
+  const char* scale = current_scale();
+  output()->print("reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s",
+    amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
+}
+
+void MemReporterBase::print_malloc(size_t amount, size_t count) const {
+  const char* scale = current_scale();
+  outputStream* out = output();
+  out->print("(malloc=" SIZE_FORMAT "%s",
+    amount_in_current_scale(amount), scale);
+
+  if (count > 0) {
+    out->print(" #" SIZE_FORMAT "", count);
   }
-  ShouldNotReachHere();
-  return NULL;
+
+  out->print(")");
+}
+
+void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) const {
+  const char* scale = current_scale();
+  output()->print("(mmap: reserved=" SIZE_FORMAT "%s, committed=" SIZE_FORMAT "%s)",
+    amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale);
+}
+
+void MemReporterBase::print_malloc_line(size_t amount, size_t count) const {
+  output()->print("%28s", " ");
+  print_malloc(amount, count);
+  output()->print_cr(" ");
+}
+
+void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committed) const {
+  output()->print("%28s", " ");
+  print_virtual_memory(reserved, committed);
+  output()->print_cr(" ");
+}
+
+void MemReporterBase::print_arena_line(size_t amount, size_t count) const {
+  const char* scale = current_scale();
+  output()->print_cr("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", " ",
+    amount_in_current_scale(amount), scale, count);
+}
+
+void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const {
+  const char* scale = current_scale();
+  output()->print("[" PTR_FORMAT " - " PTR_FORMAT "] %s " SIZE_FORMAT "%s",
+    p2i(base), p2i(base + size), type, amount_in_current_scale(size), scale);
 }
 
 
-void BaselineReporter::report_baseline(const MemBaseline& baseline, bool summary_only) {
-  assert(MemTracker::is_on(), "Native memory tracking is off");
-  _outputer.start(scale());
-  _outputer.total_usage(
-    amount_in_current_scale(baseline.total_malloc_amount() + baseline.total_reserved_amount()),
-    amount_in_current_scale(baseline.total_malloc_amount() + baseline.total_committed_amount()));
+void MemSummaryReporter::report() {
+  const char* scale = current_scale();
+  outputStream* out = output();
+  size_t total_reserved_amount = _malloc_snapshot->total() +
+    _vm_snapshot->total_reserved();
+  size_t total_committed_amount = _malloc_snapshot->total() +
+    _vm_snapshot->total_committed();
 
-  _outputer.num_of_classes(baseline.number_of_classes());
-  _outputer.num_of_threads(baseline.number_of_threads());
+  // Overall total
+  out->print_cr("\nNative Memory Tracking:\n");
+  out->print("Total: ");
+  print_total(total_reserved_amount, total_committed_amount);
+  out->print("\n");
 
-  report_summaries(baseline);
-  if (!summary_only && MemTracker::track_callsite()) {
-    report_virtual_memory_map(baseline);
-    report_callsites(baseline);
+  // Summary by memory type
+  for (int index = 0; index < mt_number_of_types; index ++) {
+    MEMFLAGS flag = NMTUtil::index_to_flag(index);
+    // thread stack is reported as part of thread category
+    if (flag == mtThreadStack) continue;
+    MallocMemory* malloc_memory = _malloc_snapshot->by_type(flag);
+    VirtualMemory* virtual_memory = _vm_snapshot->by_type(flag);
+
+    report_summary_of_type(flag, malloc_memory, virtual_memory);
   }
-  _outputer.done();
 }
 
-void BaselineReporter::report_summaries(const MemBaseline& baseline) {
-  _outputer.start_category_summary();
-  MEMFLAGS type;
+void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag,
+  MallocMemory*  malloc_memory, VirtualMemory* virtual_memory) {
 
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    type = MemBaseline::MemType2NameMap[index]._flag;
-    _outputer.category_summary(type,
-      amount_in_current_scale(baseline.reserved_amount(type)),
-      amount_in_current_scale(baseline.committed_amount(type)),
-      amount_in_current_scale(baseline.malloc_amount(type)),
-      baseline.malloc_count(type),
-      amount_in_current_scale(baseline.arena_amount(type)),
-      baseline.arena_count(type));
+  size_t reserved_amount  = reserved_total (malloc_memory, virtual_memory);
+  size_t committed_amount = committed_total(malloc_memory, virtual_memory);
+
+  // Count thread's native stack in "Thread" category
+  if (flag == mtThread) {
+    const VirtualMemory* thread_stack_usage =
+      (const VirtualMemory*)_vm_snapshot->by_type(mtThreadStack);
+    reserved_amount  += thread_stack_usage->reserved();
+    committed_amount += thread_stack_usage->committed();
+  } else if (flag == mtNMT) {
+    // Count malloc headers in "NMT" category
+    reserved_amount  += _malloc_snapshot->malloc_overhead()->size();
+    committed_amount += _malloc_snapshot->malloc_overhead()->size();
   }
 
-  _outputer.done_category_summary();
-}
+  if (amount_in_current_scale(reserved_amount) > 0) {
+    outputStream* out   = output();
+    const char*   scale = current_scale();
+    out->print("-%26s (", NMTUtil::flag_to_name(flag));
+    print_total(reserved_amount, committed_amount);
+    out->print_cr(")");
 
-void BaselineReporter::report_virtual_memory_map(const MemBaseline& baseline) {
-  _outputer.start_virtual_memory_map();
-  MemBaseline* pBL = const_cast<MemBaseline*>(&baseline);
-  MemPointerArrayIteratorImpl itr = MemPointerArrayIteratorImpl(pBL->_vm_map);
-  VMMemRegionEx* rgn = (VMMemRegionEx*)itr.current();
-  while (rgn != NULL) {
-    if (rgn->is_reserved_region()) {
-      _outputer.reserved_memory_region(FLAGS_TO_MEMORY_TYPE(rgn->flags()),
-        rgn->base(), rgn->base() + rgn->size(), amount_in_current_scale(rgn->size()), rgn->pc());
-    } else {
-      _outputer.committed_memory_region(rgn->base(), rgn->base() + rgn->size(),
-        amount_in_current_scale(rgn->size()), rgn->pc());
+    if (flag == mtClass) {
+      // report class count
+      out->print_cr("%27s (classes #" SIZE_FORMAT ")", " ", _class_count);
+    } else if (flag == mtThread) {
+      // report thread count
+      out->print_cr("%27s (thread #" SIZE_FORMAT ")", " ", _malloc_snapshot->thread_count());
+      const VirtualMemory* thread_stack_usage =
+       _vm_snapshot->by_type(mtThreadStack);
+      out->print("%27s (stack: ", " ");
+      print_total(thread_stack_usage->reserved(), thread_stack_usage->committed());
+      out->print_cr(")");
     }
-    rgn = (VMMemRegionEx*)itr.next();
-  }
 
-  _outputer.done_virtual_memory_map();
+     // report malloc'd memory
+    if (amount_in_current_scale(malloc_memory->malloc_size()) > 0) {
+      // We don't know how many arena chunks are in used, so don't report the count
+      size_t count = (flag == mtChunk) ? 0 : malloc_memory->malloc_count();
+      print_malloc_line(malloc_memory->malloc_size(), count);
+    }
+
+    if (amount_in_current_scale(virtual_memory->reserved()) > 0) {
+      print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed());
+    }
+
+    if (amount_in_current_scale(malloc_memory->arena_size()) > 0) {
+      print_arena_line(malloc_memory->arena_size(), malloc_memory->arena_count());
+    }
+
+    if (flag == mtNMT &&
+      amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()) > 0) {
+      out->print_cr("%27s (tracking overhead=" SIZE_FORMAT "%s)", " ",
+        amount_in_current_scale(_malloc_snapshot->malloc_overhead()->size()), scale);
+    }
+
+    out->print_cr(" ");
+  }
 }
 
-void BaselineReporter::report_callsites(const MemBaseline& baseline) {
-  _outputer.start_callsite();
-  MemBaseline* pBL = const_cast<MemBaseline*>(&baseline);
+void MemDetailReporter::report_detail() {
+  // Start detail report
+  outputStream* out = output();
+  out->print_cr("Details:\n");
 
-  pBL->_malloc_cs->sort((FN_SORT)MemBaseline::bl_malloc_sort_by_size);
-  pBL->_vm_cs->sort((FN_SORT)MemBaseline::bl_vm_sort_by_size);
-
-  // walk malloc callsites
-  MemPointerArrayIteratorImpl malloc_itr(pBL->_malloc_cs);
-  MallocCallsitePointer*      malloc_callsite =
-                  (MallocCallsitePointer*)malloc_itr.current();
-  while (malloc_callsite != NULL) {
-    _outputer.malloc_callsite(malloc_callsite->addr(),
-        amount_in_current_scale(malloc_callsite->amount()), malloc_callsite->count());
-    malloc_callsite = (MallocCallsitePointer*)malloc_itr.next();
-  }
-
-  // walk virtual memory callsite
-  MemPointerArrayIteratorImpl vm_itr(pBL->_vm_cs);
-  VMCallsitePointer*          vm_callsite = (VMCallsitePointer*)vm_itr.current();
-  while (vm_callsite != NULL) {
-    _outputer.virtual_memory_callsite(vm_callsite->addr(),
-      amount_in_current_scale(vm_callsite->reserved_amount()),
-      amount_in_current_scale(vm_callsite->committed_amount()));
-    vm_callsite = (VMCallsitePointer*)vm_itr.next();
-  }
-  pBL->_malloc_cs->sort((FN_SORT)MemBaseline::bl_malloc_sort_by_pc);
-  pBL->_vm_cs->sort((FN_SORT)MemBaseline::bl_vm_sort_by_pc);
-  _outputer.done_callsite();
+  report_malloc_sites();
+  report_virtual_memory_allocation_sites();
 }
 
-void BaselineReporter::diff_baselines(const MemBaseline& cur, const MemBaseline& prev,
-  bool summary_only) {
-  assert(MemTracker::is_on(), "Native memory tracking is off");
-  _outputer.start(scale());
-  size_t total_reserved = cur.total_malloc_amount() + cur.total_reserved_amount();
-  size_t total_committed = cur.total_malloc_amount() + cur.total_committed_amount();
+void MemDetailReporter::report_malloc_sites() {
+  MallocSiteIterator         malloc_itr = _baseline.malloc_sites(MemBaseline::by_size);
+  if (malloc_itr.is_empty()) return;
 
-  _outputer.diff_total_usage(
-    amount_in_current_scale(total_reserved), amount_in_current_scale(total_committed),
-    diff_in_current_scale(total_reserved,  (prev.total_malloc_amount() + prev.total_reserved_amount())),
-    diff_in_current_scale(total_committed, (prev.total_committed_amount() + prev.total_malloc_amount())));
+  outputStream* out = output();
 
-  _outputer.diff_num_of_classes(cur.number_of_classes(),
-       diff(cur.number_of_classes(), prev.number_of_classes()));
-  _outputer.diff_num_of_threads(cur.number_of_threads(),
-       diff(cur.number_of_threads(), prev.number_of_threads()));
+  const MallocSite* malloc_site;
+  while ((malloc_site = malloc_itr.next()) != NULL) {
+    // Don't report if size is too small
+    if (amount_in_current_scale(malloc_site->size()) == 0)
+      continue;
 
-  diff_summaries(cur, prev);
-  if (!summary_only && MemTracker::track_callsite()) {
-    diff_callsites(cur, prev);
+    const NativeCallStack* stack = malloc_site->call_stack();
+    stack->print_on(out);
+    out->print("%29s", " ");
+    print_malloc(malloc_site->size(), malloc_site->count());
+    out->print_cr("\n");
   }
-  _outputer.done();
 }
 
-void BaselineReporter::diff_summaries(const MemBaseline& cur, const MemBaseline& prev) {
-  _outputer.start_category_summary();
-  MEMFLAGS type;
+void MemDetailReporter::report_virtual_memory_allocation_sites()  {
+  VirtualMemorySiteIterator  virtual_memory_itr =
+    _baseline.virtual_memory_sites(MemBaseline::by_size);
 
-  for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
-    type = MemBaseline::MemType2NameMap[index]._flag;
-    _outputer.diff_category_summary(type,
-      amount_in_current_scale(cur.reserved_amount(type)),
-      amount_in_current_scale(cur.committed_amount(type)),
-      amount_in_current_scale(cur.malloc_amount(type)),
-      cur.malloc_count(type),
-      amount_in_current_scale(cur.arena_amount(type)),
-      cur.arena_count(type),
-      diff_in_current_scale(cur.reserved_amount(type), prev.reserved_amount(type)),
-      diff_in_current_scale(cur.committed_amount(type), prev.committed_amount(type)),
-      diff_in_current_scale(cur.malloc_amount(type), prev.malloc_amount(type)),
-      diff(cur.malloc_count(type), prev.malloc_count(type)),
-      diff_in_current_scale(cur.arena_amount(type), prev.arena_amount(type)),
-      diff(cur.arena_count(type), prev.arena_count(type)));
+  if (virtual_memory_itr.is_empty()) return;
+
+  outputStream* out = output();
+  const VirtualMemoryAllocationSite*  virtual_memory_site;
+
+  while ((virtual_memory_site = virtual_memory_itr.next()) != NULL) {
+    // Don't report if size is too small
+    if (amount_in_current_scale(virtual_memory_site->reserved()) == 0)
+      continue;
+
+    const NativeCallStack* stack = virtual_memory_site->call_stack();
+    stack->print_on(out);
+    out->print("%28s (", " ");
+    print_total(virtual_memory_site->reserved(), virtual_memory_site->committed());
+    out->print_cr(")\n");
   }
-
-  _outputer.done_category_summary();
 }
 
-void BaselineReporter::diff_callsites(const MemBaseline& cur, const MemBaseline& prev) {
-  _outputer.start_callsite();
-  MemBaseline* pBL_cur = const_cast<MemBaseline*>(&cur);
-  MemBaseline* pBL_prev = const_cast<MemBaseline*>(&prev);
 
-  // walk malloc callsites
-  MemPointerArrayIteratorImpl cur_malloc_itr(pBL_cur->_malloc_cs);
-  MemPointerArrayIteratorImpl prev_malloc_itr(pBL_prev->_malloc_cs);
+void MemDetailReporter::report_virtual_memory_map() {
+  // Virtual memory map always in base address order
+  VirtualMemoryAllocationIterator itr = _baseline.virtual_memory_allocations();
+  const ReservedMemoryRegion* rgn;
 
-  MallocCallsitePointer*      cur_malloc_callsite =
-                  (MallocCallsitePointer*)cur_malloc_itr.current();
-  MallocCallsitePointer*      prev_malloc_callsite =
-                  (MallocCallsitePointer*)prev_malloc_itr.current();
+  output()->print_cr("Virtual memory map:");
+  while ((rgn = itr.next()) != NULL) {
+    report_virtual_memory_region(rgn);
+  }
+}
 
-  while (cur_malloc_callsite != NULL || prev_malloc_callsite != NULL) {
-    if (prev_malloc_callsite == NULL) {
-      assert(cur_malloc_callsite != NULL, "sanity check");
-      // this is a new callsite
-      _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
-        amount_in_current_scale(cur_malloc_callsite->amount()),
-        cur_malloc_callsite->count(),
-        diff_in_current_scale(cur_malloc_callsite->amount(), 0),
-        diff(cur_malloc_callsite->count(), 0));
-      cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next();
-    } else if (cur_malloc_callsite == NULL) {
-      assert(prev_malloc_callsite != NULL, "Sanity check");
-      // this callsite is already gone
-      _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(),
-        0, 0,
-        diff_in_current_scale(0, prev_malloc_callsite->amount()),
-        diff(0, prev_malloc_callsite->count()));
-      prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next();
+void MemDetailReporter::report_virtual_memory_region(const ReservedMemoryRegion* reserved_rgn) {
+  assert(reserved_rgn != NULL, "NULL pointer");
+
+  // Don't report if size is too small
+  if (amount_in_current_scale(reserved_rgn->size()) == 0) return;
+
+  outputStream* out = output();
+  const char* scale = current_scale();
+  const NativeCallStack*  stack = reserved_rgn->call_stack();
+  bool all_committed = reserved_rgn->all_committed();
+  const char* region_type = (all_committed ? "reserved and committed" : "reserved");
+  out->print_cr(" ");
+  print_virtual_memory_region(region_type, reserved_rgn->base(), reserved_rgn->size());
+  out->print(" for %s", NMTUtil::flag_to_name(reserved_rgn->flag()));
+  if (stack->is_empty()) {
+    out->print_cr(" ");
+  } else {
+    out->print_cr(" from");
+    stack->print_on(out, 4);
+  }
+
+  if (all_committed) return;
+
+  CommittedRegionIterator itr = reserved_rgn->iterate_committed_regions();
+  const CommittedMemoryRegion* committed_rgn;
+  while ((committed_rgn = itr.next()) != NULL) {
+    // Don't report if size is too small
+    if (amount_in_current_scale(committed_rgn->size()) == 0) continue;
+    stack = committed_rgn->call_stack();
+    out->print("\n\t");
+    print_virtual_memory_region("committed", committed_rgn->base(), committed_rgn->size());
+    if (stack->is_empty()) {
+      out->print_cr(" ");
     } else {
-      assert(cur_malloc_callsite  != NULL,  "Sanity check");
-      assert(prev_malloc_callsite != NULL,  "Sanity check");
-      if (cur_malloc_callsite->addr() < prev_malloc_callsite->addr()) {
-        // this is a new callsite
-        _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
-          amount_in_current_scale(cur_malloc_callsite->amount()),
-          cur_malloc_callsite->count(),
-          diff_in_current_scale(cur_malloc_callsite->amount(), 0),
-          diff(cur_malloc_callsite->count(), 0));
-          cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next();
-      } else if (cur_malloc_callsite->addr() > prev_malloc_callsite->addr()) {
-        // this callsite is already gone
-        _outputer.diff_malloc_callsite(prev_malloc_callsite->addr(),
-          0, 0,
-          diff_in_current_scale(0, prev_malloc_callsite->amount()),
-          diff(0, prev_malloc_callsite->count()));
-        prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next();
+      out->print_cr(" from");
+      stack->print_on(out, 12);
+    }
+  }
+}
+
+void MemSummaryDiffReporter::report_diff() {
+  const char* scale = current_scale();
+  outputStream* out = output();
+  out->print_cr("\nNative Memory Tracking:\n");
+
+  // Overall diff
+  out->print("Total: ");
+  print_virtual_memory_diff(_current_baseline.total_reserved_memory(),
+    _current_baseline.total_committed_memory(), _early_baseline.total_reserved_memory(),
+    _early_baseline.total_committed_memory());
+
+  out->print_cr("\n");
+
+  // Summary diff by memory type
+  for (int index = 0; index < mt_number_of_types; index ++) {
+    MEMFLAGS flag = NMTUtil::index_to_flag(index);
+    // thread stack is reported as part of thread category
+    if (flag == mtThreadStack) continue;
+    diff_summary_of_type(flag, _early_baseline.malloc_memory(flag),
+      _early_baseline.virtual_memory(flag), _current_baseline.malloc_memory(flag),
+      _current_baseline.virtual_memory(flag));
+  }
+}
+
+void MemSummaryDiffReporter::print_malloc_diff(size_t current_amount, size_t current_count,
+    size_t early_amount, size_t early_count) const {
+  const char* scale = current_scale();
+  outputStream* out = output();
+
+  out->print("malloc=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale);
+  long amount_diff = diff_in_current_scale(current_amount, early_amount);
+  if (amount_diff != 0) {
+    out->print(" %+ld%s", amount_diff, scale);
+  }
+  if (current_count > 0) {
+    out->print(" #" SIZE_FORMAT "", current_count);
+    if (current_count != early_count) {
+      out->print(" %+d", (int)(current_count - early_count));
+    }
+  }
+}
+
+void MemSummaryDiffReporter::print_arena_diff(size_t current_amount, size_t current_count,
+  size_t early_amount, size_t early_count) const {
+  const char* scale = current_scale();
+  outputStream* out = output();
+  out->print("arena=" SIZE_FORMAT "%s", amount_in_current_scale(current_amount), scale);
+  if (diff_in_current_scale(current_amount, early_amount) != 0) {
+    out->print(" %+ld", diff_in_current_scale(current_amount, early_amount));
+  }
+
+  out->print(" #" SIZE_FORMAT "", current_count);
+  if (current_count != early_count) {
+    out->print(" %+d", (int)(current_count - early_count));
+  }
+}
+
+void MemSummaryDiffReporter::print_virtual_memory_diff(size_t current_reserved, size_t current_committed,
+    size_t early_reserved, size_t early_committed) const {
+  const char* scale = current_scale();
+  outputStream* out = output();
+  out->print("reserved=" SIZE_FORMAT "%s", amount_in_current_scale(current_reserved), scale);
+  long reserved_diff = diff_in_current_scale(current_reserved, early_reserved);
+  if (reserved_diff != 0) {
+    out->print(" %+ld%s", reserved_diff, scale);
+  }
+
+  out->print(", committed=" SIZE_FORMAT "%s", amount_in_current_scale(current_committed), scale);
+  long committed_diff = diff_in_current_scale(current_committed, early_committed);
+  if (committed_diff != 0) {
+    out->print(" %+ld%s", committed_diff, scale);
+  }
+}
+
+
+void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, const MallocMemory* early_malloc,
+  const VirtualMemory* early_vm, const MallocMemory* current_malloc,
+  const VirtualMemory* current_vm) const {
+
+  outputStream* out = output();
+  const char* scale = current_scale();
+
+  // Total reserved and committed memory in current baseline
+  size_t current_reserved_amount  = reserved_total (current_malloc, current_vm);
+  size_t current_committed_amount = committed_total(current_malloc, current_vm);
+
+  // Total reserved and committed memory in early baseline
+  size_t early_reserved_amount  = reserved_total(early_malloc, early_vm);
+  size_t early_committed_amount = committed_total(early_malloc, early_vm);
+
+  // Adjust virtual memory total
+  if (flag == mtThread) {
+    const VirtualMemory* early_thread_stack_usage =
+      _early_baseline.virtual_memory(mtThreadStack);
+    const VirtualMemory* current_thread_stack_usage =
+      _current_baseline.virtual_memory(mtThreadStack);
+
+    early_reserved_amount  += early_thread_stack_usage->reserved();
+    early_committed_amount += early_thread_stack_usage->committed();
+
+    current_reserved_amount  += current_thread_stack_usage->reserved();
+    current_committed_amount += current_thread_stack_usage->committed();
+  } else if (flag == mtNMT) {
+    early_reserved_amount  += _early_baseline.malloc_tracking_overhead();
+    early_committed_amount += _early_baseline.malloc_tracking_overhead();
+
+    current_reserved_amount  += _current_baseline.malloc_tracking_overhead();
+    current_committed_amount += _current_baseline.malloc_tracking_overhead();
+  }
+
+  if (amount_in_current_scale(current_reserved_amount) > 0 ||
+      diff_in_current_scale(current_reserved_amount, early_reserved_amount) != 0) {
+
+    // print summary line
+    out->print("-%26s (", NMTUtil::flag_to_name(flag));
+    print_virtual_memory_diff(current_reserved_amount, current_committed_amount,
+      early_reserved_amount, early_committed_amount);
+    out->print_cr(")");
+
+    // detail lines
+    if (flag == mtClass) {
+      // report class count
+      out->print("%27s (classes #" SIZE_FORMAT "", " ", _current_baseline.class_count());
+      int class_count_diff = (int)(_current_baseline.class_count() -
+        _early_baseline.class_count());
+      if (_current_baseline.class_count() != _early_baseline.class_count()) {
+        out->print(" %+d", (int)(_current_baseline.class_count() - _early_baseline.class_count()));
+      }
+      out->print_cr(")");
+    } else if (flag == mtThread) {
+      // report thread count
+      out->print("%27s (thread #" SIZE_FORMAT "", " ", _current_baseline.thread_count());
+      int thread_count_diff = (int)(_current_baseline.thread_count() -
+          _early_baseline.thread_count());
+      if (thread_count_diff != 0) {
+        out->print(" %+d", thread_count_diff);
+      }
+      out->print_cr(")");
+
+      // report thread stack
+      const VirtualMemory* current_thread_stack =
+          _current_baseline.virtual_memory(mtThreadStack);
+      const VirtualMemory* early_thread_stack =
+        _early_baseline.virtual_memory(mtThreadStack);
+
+      out->print("%27s (stack: ", " ");
+      print_virtual_memory_diff(current_thread_stack->reserved(), current_thread_stack->committed(),
+        early_thread_stack->reserved(), early_thread_stack->committed());
+      out->print_cr(")");
+    }
+
+    // Report malloc'd memory
+    size_t current_malloc_amount = current_malloc->malloc_size();
+    size_t early_malloc_amount   = early_malloc->malloc_size();
+    if (amount_in_current_scale(current_malloc_amount) > 0 ||
+        diff_in_current_scale(current_malloc_amount, early_malloc_amount) != 0) {
+      out->print("%28s(", " ");
+      print_malloc_diff(current_malloc_amount, (flag == mtChunk) ? 0 : current_malloc->malloc_count(),
+        early_malloc_amount, early_malloc->malloc_count());
+      out->print_cr(")");
+    }
+
+    // Report virtual memory
+    if (amount_in_current_scale(current_vm->reserved()) > 0 ||
+        diff_in_current_scale(current_vm->reserved(), early_vm->reserved()) != 0) {
+      out->print("%27s (mmap: ", " ");
+      print_virtual_memory_diff(current_vm->reserved(), current_vm->committed(),
+        early_vm->reserved(), early_vm->committed());
+      out->print_cr(")");
+    }
+
+    // Report arena memory
+    if (amount_in_current_scale(current_malloc->arena_size()) > 0 ||
+        diff_in_current_scale(current_malloc->arena_size(), early_malloc->arena_size()) != 0) {
+      out->print("%28s(", " ");
+      print_arena_diff(current_malloc->arena_size(), current_malloc->arena_count(),
+        early_malloc->arena_size(), early_malloc->arena_count());
+      out->print_cr(")");
+    }
+
+    // Report native memory tracking overhead
+    if (flag == mtNMT) {
+      size_t current_tracking_overhead = amount_in_current_scale(_current_baseline.malloc_tracking_overhead());
+      size_t early_tracking_overhead   = amount_in_current_scale(_early_baseline.malloc_tracking_overhead());
+
+      out->print("%27s (tracking overhead=" SIZE_FORMAT "%s", " ",
+        amount_in_current_scale(_current_baseline.malloc_tracking_overhead()), scale);
+
+      long overhead_diff = diff_in_current_scale(_current_baseline.malloc_tracking_overhead(),
+           _early_baseline.malloc_tracking_overhead());
+      if (overhead_diff != 0) {
+        out->print(" %+ld%s", overhead_diff, scale);
+      }
+      out->print_cr(")");
+    }
+    out->print_cr(" ");
+  }
+}
+
+void MemDetailDiffReporter::report_diff() {
+  MemSummaryDiffReporter::report_diff();
+  diff_malloc_sites();
+  diff_virtual_memory_sites();
+}
+
+void MemDetailDiffReporter::diff_malloc_sites() const {
+  MallocSiteIterator early_itr = _early_baseline.malloc_sites(MemBaseline::by_site);
+  MallocSiteIterator current_itr = _current_baseline.malloc_sites(MemBaseline::by_site);
+
+  const MallocSite* early_site   = early_itr.next();
+  const MallocSite* current_site = current_itr.next();
+
+  while (early_site != NULL || current_site != NULL) {
+    if (early_site == NULL) {
+      new_malloc_site(current_site);
+      current_site = current_itr.next();
+    } else if (current_site == NULL) {
+      old_malloc_site(early_site);
+      early_site = early_itr.next();
+    } else {
+      int compVal = current_site->call_stack()->compare(*early_site->call_stack());
+      if (compVal < 0) {
+        new_malloc_site(current_site);
+        current_site = current_itr.next();
+      } else if (compVal > 0) {
+        old_malloc_site(early_site);
+        early_site = early_itr.next();
       } else {
-        // the same callsite
-        _outputer.diff_malloc_callsite(cur_malloc_callsite->addr(),
-          amount_in_current_scale(cur_malloc_callsite->amount()),
-          cur_malloc_callsite->count(),
-          diff_in_current_scale(cur_malloc_callsite->amount(), prev_malloc_callsite->amount()),
-          diff(cur_malloc_callsite->count(), prev_malloc_callsite->count()));
-        cur_malloc_callsite = (MallocCallsitePointer*)cur_malloc_itr.next();
-        prev_malloc_callsite = (MallocCallsitePointer*)prev_malloc_itr.next();
+        diff_malloc_site(early_site, current_site);
+        early_site   = early_itr.next();
+        current_site = current_itr.next();
       }
     }
   }
-
-  // walk virtual memory callsite
-  MemPointerArrayIteratorImpl cur_vm_itr(pBL_cur->_vm_cs);
-  MemPointerArrayIteratorImpl prev_vm_itr(pBL_prev->_vm_cs);
-  VMCallsitePointer*          cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.current();
-  VMCallsitePointer*          prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.current();
-  while (cur_vm_callsite != NULL || prev_vm_callsite != NULL) {
-    if (prev_vm_callsite == NULL || cur_vm_callsite->addr() < prev_vm_callsite->addr()) {
-      // this is a new callsite
-      _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(),
-        amount_in_current_scale(cur_vm_callsite->reserved_amount()),
-        amount_in_current_scale(cur_vm_callsite->committed_amount()),
-        diff_in_current_scale(cur_vm_callsite->reserved_amount(), 0),
-        diff_in_current_scale(cur_vm_callsite->committed_amount(), 0));
-      cur_vm_callsite = (VMCallsitePointer*)cur_vm_itr.next();
-    } else if (cur_vm_callsite == NULL || cur_vm_callsite->addr() > prev_vm_callsite->addr()) {
-      // this callsite is already gone
-      _outputer.diff_virtual_memory_callsite(prev_vm_callsite->addr(),
-        amount_in_current_scale(0),
-        amount_in_current_scale(0),
-        diff_in_current_scale(0, prev_vm_callsite->reserved_amount()),
-        diff_in_current_scale(0, prev_vm_callsite->committed_amount()));
-      prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next();
-    } else { // the same callsite
-      _outputer.diff_virtual_memory_callsite(cur_vm_callsite->addr(),
-        amount_in_current_scale(cur_vm_callsite->reserved_amount()),
-        amount_in_current_scale(cur_vm_callsite->committed_amount()),
-        diff_in_current_scale(cur_vm_callsite->reserved_amount(), prev_vm_callsite->reserved_amount()),
-        diff_in_current_scale(cur_vm_callsite->committed_amount(), prev_vm_callsite->committed_amount()));
-      cur_vm_callsite  = (VMCallsitePointer*)cur_vm_itr.next();
-      prev_vm_callsite = (VMCallsitePointer*)prev_vm_itr.next();
-    }
-  }
-
-  _outputer.done_callsite();
 }
 
-size_t BaselineReporter::amount_in_current_scale(size_t amt) const {
-  return (size_t)(((float)amt/(float)_scale) + 0.5);
-}
+void MemDetailDiffReporter::diff_virtual_memory_sites() const {
+  VirtualMemorySiteIterator early_itr = _early_baseline.virtual_memory_sites(MemBaseline::by_site);
+  VirtualMemorySiteIterator current_itr = _current_baseline.virtual_memory_sites(MemBaseline::by_site);
 
-int BaselineReporter::diff_in_current_scale(size_t value1, size_t value2) const {
-  return (int)(((float)value1 - (float)value2)/((float)_scale) + 0.5);
-}
+  const VirtualMemoryAllocationSite* early_site   = early_itr.next();
+  const VirtualMemoryAllocationSite* current_site = current_itr.next();
 
-int BaselineReporter::diff(size_t value1, size_t value2) const {
-  return ((int)value1 - (int)value2);
-}
-
-void BaselineTTYOutputer::start(size_t scale, bool report_diff) {
-  _scale = scale;
-  _output->print_cr(" ");
-  _output->print_cr("Native Memory Tracking:");
-  _output->print_cr(" ");
-}
-
-void BaselineTTYOutputer::done() {
-
-}
-
-void BaselineTTYOutputer::total_usage(size_t total_reserved, size_t total_committed) {
-  const char* unit = memory_unit(_scale);
-  _output->print_cr("Total:  reserved=%d%s,  committed=%d%s",
-    total_reserved, unit, total_committed, unit);
-}
-
-void BaselineTTYOutputer::start_category_summary() {
-  _output->print_cr(" ");
-}
-
-/**
- * report a summary of memory type
- */
-void BaselineTTYOutputer::category_summary(MEMFLAGS type,
-  size_t reserved_amt, size_t committed_amt, size_t malloc_amt,
-  size_t malloc_count, size_t arena_amt, size_t arena_count) {
-
-  // we report mtThreadStack under mtThread category
-  if (type == mtThreadStack) {
-    assert(malloc_amt == 0 && malloc_count == 0 && arena_amt == 0,
-      "Just check");
-    _thread_stack_reserved = reserved_amt;
-    _thread_stack_committed = committed_amt;
-  } else {
-    const char* unit = memory_unit(_scale);
-    size_t total_reserved = (reserved_amt + malloc_amt + arena_amt);
-    size_t total_committed = (committed_amt + malloc_amt + arena_amt);
-    if (type == mtThread) {
-      total_reserved += _thread_stack_reserved;
-      total_committed += _thread_stack_committed;
-    }
-
-    if (total_reserved > 0) {
-      _output->print_cr("-%26s (reserved=%d%s, committed=%d%s)",
-        MemBaseline::type2name(type), total_reserved, unit,
-        total_committed, unit);
-
-      if (type == mtClass) {
-        _output->print_cr("%27s (classes #%d)", " ", _num_of_classes);
-      } else if (type == mtThread) {
-        _output->print_cr("%27s (thread #%d)", " ", _num_of_threads);
-        _output->print_cr("%27s (stack: reserved=%d%s, committed=%d%s)", " ",
-          _thread_stack_reserved, unit, _thread_stack_committed, unit);
-      }
-
-      if (malloc_amt > 0) {
-        if (type != mtChunk) {
-          _output->print_cr("%27s (malloc=%d%s, #%d)", " ", malloc_amt, unit,
-            malloc_count);
-        } else {
-          _output->print_cr("%27s (malloc=%d%s)", " ", malloc_amt, unit);
-        }
-      }
-
-      if (reserved_amt > 0) {
-        _output->print_cr("%27s (mmap: reserved=%d%s, committed=%d%s)",
-          " ", reserved_amt, unit, committed_amt, unit);
-      }
-
-      if (arena_amt > 0) {
-        _output->print_cr("%27s (arena=%d%s, #%d)", " ", arena_amt, unit, arena_count);
-      }
-
-      _output->print_cr(" ");
-    }
-  }
-}
-
-void BaselineTTYOutputer::done_category_summary() {
-  _output->print_cr(" ");
-}
-
-
-void BaselineTTYOutputer::start_virtual_memory_map() {
-  _output->print_cr("Virtual memory map:");
-}
-
-void BaselineTTYOutputer::reserved_memory_region(MEMFLAGS type, address base, address end,
-                                                 size_t size, address pc) {
-  const char* unit = memory_unit(_scale);
-  char buf[128];
-  int  offset;
-  _output->print_cr(" ");
-  _output->print_cr("[" PTR_FORMAT " - " PTR_FORMAT "] reserved %d%s for %s", base, end, size, unit,
-            MemBaseline::type2name(type));
-  if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-      _output->print_cr("\t\tfrom [%s+0x%x]", buf, offset);
-  }
-}
-
-void BaselineTTYOutputer::committed_memory_region(address base, address end, size_t size, address pc) {
-  const char* unit = memory_unit(_scale);
-  char buf[128];
-  int  offset;
-  _output->print("\t[" PTR_FORMAT " - " PTR_FORMAT "] committed %d%s", base, end, size, unit);
-  if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-      _output->print_cr(" from [%s+0x%x]", buf, offset);
-  }
-}
-
-void BaselineTTYOutputer::done_virtual_memory_map() {
-  _output->print_cr(" ");
-}
-
-
-
-void BaselineTTYOutputer::start_callsite() {
-  _output->print_cr("Details:");
-  _output->print_cr(" ");
-}
-
-void BaselineTTYOutputer::done_callsite() {
-  _output->print_cr(" ");
-}
-
-void BaselineTTYOutputer::malloc_callsite(address pc, size_t malloc_amt,
-  size_t malloc_count) {
-  if (malloc_amt > 0) {
-    const char* unit = memory_unit(_scale);
-    char buf[128];
-    int  offset;
-    if (pc == 0) {
-      _output->print("[BOOTSTRAP]%18s", " ");
-    } else if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-      _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
-      _output->print("%28s", " ");
+  while (early_site != NULL || current_site != NULL) {
+    if (early_site == NULL) {
+      new_virtual_memory_site(current_site);
+      current_site = current_itr.next();
+    } else if (current_site == NULL) {
+      old_virtual_memory_site(early_site);
+      early_site = early_itr.next();
     } else {
-      _output->print("[" PTR_FORMAT "]%18s", pc, " ");
+      int compVal = current_site->call_stack()->compare(*early_site->call_stack());
+      if (compVal < 0) {
+        new_virtual_memory_site(current_site);
+        current_site = current_itr.next();
+      } else if (compVal > 0) {
+        old_virtual_memory_site(early_site);
+        early_site = early_itr.next();
+      } else {
+        diff_virtual_memory_site(early_site, current_site);
+        early_site   = early_itr.next();
+        current_site = current_itr.next();
+      }
     }
-
-    _output->print_cr("(malloc=%d%s #%d)", malloc_amt, unit, malloc_count);
-    _output->print_cr(" ");
   }
 }
 
-void BaselineTTYOutputer::virtual_memory_callsite(address pc, size_t reserved_amt,
-  size_t committed_amt) {
-  if (reserved_amt > 0) {
-    const char* unit = memory_unit(_scale);
-    char buf[128];
-    int  offset;
-    if (pc == 0) {
-      _output->print("[BOOTSTRAP]%18s", " ");
-    } else if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-      _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
-      _output->print("%28s", " ");
-    } else {
-      _output->print("[" PTR_FORMAT "]%18s", pc, " ");
-    }
 
-    _output->print_cr("(mmap: reserved=%d%s, committed=%d%s)",
-      reserved_amt, unit, committed_amt, unit);
-    _output->print_cr(" ");
-  }
+void MemDetailDiffReporter::new_malloc_site(const MallocSite* malloc_site) const {
+  diff_malloc_site(malloc_site->call_stack(), malloc_site->size(), malloc_site->count(),
+    0, 0);
 }
 
-void BaselineTTYOutputer::diff_total_usage(size_t total_reserved,
-  size_t total_committed, int reserved_diff, int committed_diff) {
-  const char* unit = memory_unit(_scale);
-  _output->print_cr("Total:  reserved=%d%s  %+d%s, committed=%d%s %+d%s",
-    total_reserved, unit, reserved_diff, unit, total_committed, unit,
-    committed_diff, unit);
+void MemDetailDiffReporter::old_malloc_site(const MallocSite* malloc_site) const {
+  diff_malloc_site(malloc_site->call_stack(), 0, 0, malloc_site->size(),
+    malloc_site->count());
 }
 
-void BaselineTTYOutputer::diff_category_summary(MEMFLAGS type,
-  size_t cur_reserved_amt, size_t cur_committed_amt,
-  size_t cur_malloc_amt, size_t cur_malloc_count,
-  size_t cur_arena_amt, size_t cur_arena_count,
-  int reserved_diff, int committed_diff, int malloc_diff,
-  int malloc_count_diff, int arena_diff, int arena_count_diff) {
+void MemDetailDiffReporter::diff_malloc_site(const MallocSite* early,
+  const MallocSite* current)  const {
+  diff_malloc_site(current->call_stack(), current->size(), current->count(),
+    early->size(), early->count());
+}
 
-  if (type == mtThreadStack) {
-    assert(cur_malloc_amt == 0 && cur_malloc_count == 0 &&
-      cur_arena_amt == 0, "Just check");
-    _thread_stack_reserved = cur_reserved_amt;
-    _thread_stack_committed = cur_committed_amt;
-    _thread_stack_reserved_diff = reserved_diff;
-    _thread_stack_committed_diff = committed_diff;
-  } else {
-    const char* unit = memory_unit(_scale);
-    size_t total_reserved = (cur_reserved_amt + cur_malloc_amt + cur_arena_amt);
-    // nothing to report in this category
-    if (total_reserved == 0) {
+void MemDetailDiffReporter::diff_malloc_site(const NativeCallStack* stack, size_t current_size,
+  size_t current_count, size_t early_size, size_t early_count) const {
+  outputStream* out = output();
+
+  assert(stack != NULL, "NULL stack");
+
+  if (diff_in_current_scale(current_size, early_size) == 0) {
       return;
-    }
-    int    diff_reserved = (reserved_diff + malloc_diff + arena_diff);
-
-    // category summary
-    _output->print("-%26s (reserved=%d%s", MemBaseline::type2name(type),
-      total_reserved, unit);
-
-    if (diff_reserved != 0) {
-      _output->print(" %+d%s", diff_reserved, unit);
-    }
-
-    size_t total_committed = cur_committed_amt + cur_malloc_amt + cur_arena_amt;
-    _output->print(", committed=%d%s", total_committed, unit);
-
-    int total_committed_diff = committed_diff + malloc_diff + arena_diff;
-    if (total_committed_diff != 0) {
-      _output->print(" %+d%s", total_committed_diff, unit);
-    }
-
-    _output->print_cr(")");
-
-    // special cases
-    if (type == mtClass) {
-      _output->print("%27s (classes #%d", " ", _num_of_classes);
-      if (_num_of_classes_diff != 0) {
-        _output->print(" %+d", _num_of_classes_diff);
-      }
-      _output->print_cr(")");
-    } else if (type == mtThread) {
-      // thread count
-      _output->print("%27s (thread #%d", " ", _num_of_threads);
-      if (_num_of_threads_diff != 0) {
-        _output->print_cr(" %+d)", _num_of_threads_diff);
-      } else {
-        _output->print_cr(")");
-      }
-      _output->print("%27s (stack: reserved=%d%s", " ", _thread_stack_reserved, unit);
-      if (_thread_stack_reserved_diff != 0) {
-        _output->print(" %+d%s", _thread_stack_reserved_diff, unit);
-      }
-
-      _output->print(", committed=%d%s", _thread_stack_committed, unit);
-      if (_thread_stack_committed_diff != 0) {
-        _output->print(" %+d%s",_thread_stack_committed_diff, unit);
-      }
-
-      _output->print_cr(")");
-    }
-
-    // malloc'd memory
-    if (cur_malloc_amt > 0) {
-      _output->print("%27s (malloc=%d%s", " ", cur_malloc_amt, unit);
-      if (malloc_diff != 0) {
-        _output->print(" %+d%s", malloc_diff, unit);
-      }
-      if (type != mtChunk) {
-        _output->print(", #%d", cur_malloc_count);
-        if (malloc_count_diff) {
-          _output->print(" %+d", malloc_count_diff);
-        }
-      }
-      _output->print_cr(")");
-    }
-
-    // mmap'd memory
-    if (cur_reserved_amt > 0) {
-      _output->print("%27s (mmap: reserved=%d%s", " ", cur_reserved_amt, unit);
-      if (reserved_diff != 0) {
-        _output->print(" %+d%s", reserved_diff, unit);
-      }
-
-      _output->print(", committed=%d%s", cur_committed_amt, unit);
-      if (committed_diff != 0) {
-        _output->print(" %+d%s", committed_diff, unit);
-      }
-      _output->print_cr(")");
-    }
-
-    // arena memory
-    if (cur_arena_amt > 0) {
-      _output->print("%27s (arena=%d%s", " ", cur_arena_amt, unit);
-      if (arena_diff != 0) {
-        _output->print(" %+d%s", arena_diff, unit);
-      }
-      _output->print(", #%d", cur_arena_count);
-      if (arena_count_diff != 0) {
-        _output->print(" %+d", arena_count_diff);
-      }
-      _output->print_cr(")");
-    }
-
-    _output->print_cr(" ");
   }
+
+  stack->print_on(out);
+  out->print("%28s (", " ");
+  print_malloc_diff(current_size, current_count,
+    early_size, early_count);
+
+  out->print_cr(")\n");
 }
 
-void BaselineTTYOutputer::diff_malloc_callsite(address pc,
-    size_t cur_malloc_amt, size_t cur_malloc_count,
-    int malloc_diff, int malloc_count_diff) {
-  if (malloc_diff != 0) {
-    const char* unit = memory_unit(_scale);
-    char buf[128];
-    int  offset;
-    if (pc == 0) {
-      _output->print_cr("[BOOTSTRAP]%18s", " ");
-    } else {
-      if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-        _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
-        _output->print("%28s", " ");
-      } else {
-        _output->print("[" PTR_FORMAT "]%18s", pc, " ");
-      }
-    }
 
-    _output->print("(malloc=%d%s", cur_malloc_amt, unit);
-    if (malloc_diff != 0) {
-      _output->print(" %+d%s", malloc_diff, unit);
-    }
-    _output->print(", #%d", cur_malloc_count);
-    if (malloc_count_diff != 0) {
-      _output->print(" %+d", malloc_count_diff);
-    }
-    _output->print_cr(")");
-    _output->print_cr(" ");
-  }
+void MemDetailDiffReporter::new_virtual_memory_site(const VirtualMemoryAllocationSite* site) const {
+  diff_virtual_memory_site(site->call_stack(), site->reserved(), site->committed(), 0, 0);
 }
 
-void BaselineTTYOutputer::diff_virtual_memory_callsite(address pc,
-    size_t cur_reserved_amt, size_t cur_committed_amt,
-    int reserved_diff, int committed_diff) {
-  if (reserved_diff != 0 || committed_diff != 0) {
-    const char* unit = memory_unit(_scale);
-    char buf[64];
-    int  offset;
-    if (pc == 0) {
-      _output->print_cr("[BOOSTRAP]%18s", " ");
-    } else {
-      if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
-        _output->print_cr("[" PTR_FORMAT "] %s+0x%x", pc, buf, offset);
-        _output->print("%28s", " ");
-      } else {
-        _output->print("[" PTR_FORMAT "]%18s", pc, " ");
-      }
-    }
-
-    _output->print("(mmap: reserved=%d%s", cur_reserved_amt, unit);
-    if (reserved_diff != 0) {
-      _output->print(" %+d%s", reserved_diff, unit);
-    }
-    _output->print(", committed=%d%s", cur_committed_amt, unit);
-    if (committed_diff != 0) {
-      _output->print(" %+d%s", committed_diff, unit);
-    }
-    _output->print_cr(")");
-    _output->print_cr(" ");
-  }
+void MemDetailDiffReporter::old_virtual_memory_site(const VirtualMemoryAllocationSite* site) const {
+  diff_virtual_memory_site(site->call_stack(), 0, 0, site->reserved(), site->committed());
 }
+
+void MemDetailDiffReporter::diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
+  const VirtualMemoryAllocationSite* current) const {
+  diff_virtual_memory_site(current->call_stack(), current->reserved(), current->committed(),
+    early->reserved(), early->committed());
+}
+
+void MemDetailDiffReporter::diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
+  size_t current_committed, size_t early_reserved, size_t early_committed) const  {
+  outputStream* out = output();
+
+  // no change
+  if (diff_in_current_scale(current_reserved, early_reserved) == 0 &&
+      diff_in_current_scale(current_committed, early_committed) == 0) {
+    return;
+  }
+
+  stack->print_on(out);
+  out->print("%28s (mmap: ", " ");
+  print_virtual_memory_diff(current_reserved, current_committed,
+    early_reserved, early_committed);
+
+  out->print_cr(")\n");
+ }
+
diff --git a/hotspot/src/share/vm/services/memReporter.hpp b/hotspot/src/share/vm/services/memReporter.hpp
index 805559b..239fb94 100644
--- a/hotspot/src/share/vm/services/memReporter.hpp
+++ b/hotspot/src/share/vm/services/memReporter.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -25,262 +25,217 @@
 #ifndef SHARE_VM_SERVICES_MEM_REPORTER_HPP
 #define SHARE_VM_SERVICES_MEM_REPORTER_HPP
 
-#include "runtime/mutexLocker.hpp"
-#include "services/memBaseline.hpp"
-#include "services/memTracker.hpp"
-#include "utilities/ostream.hpp"
-#include "utilities/macros.hpp"
-
 #if INCLUDE_NMT
 
+#include "oops/instanceKlass.hpp"
+#include "services/memBaseline.hpp"
+#include "services/nmtCommon.hpp"
+#include "services/mallocTracker.hpp"
+#include "services/virtualMemoryTracker.hpp"
+
 /*
- * MemBaselineReporter reports data to this outputer class,
- * ReportOutputer is responsible for format, store and redirect
- * the data to the final destination.
- */
-class BaselineOutputer : public StackObj {
+ * Base class that provides helpers
+*/
+class MemReporterBase : public StackObj {
+ private:
+  size_t        _scale;  // report in this scale
+  outputStream* _output; // destination
+
  public:
-  // start to report memory usage in specified scale.
-  // if report_diff = true, the reporter reports baseline comparison
-  // information.
+  MemReporterBase(outputStream* out = NULL, size_t scale = K)
+    : _scale(scale) {
+    _output = (out == NULL) ? tty : out;
+  }
 
-  virtual void start(size_t scale, bool report_diff = false) = 0;
-  // Done reporting
-  virtual void done() = 0;
+ protected:
+  inline outputStream* output() const {
+    return _output;
+  }
+  // Current reporting scale
+  inline const char* current_scale() const {
+    return NMTUtil::scale_name(_scale);
+  }
+  // Convert memory amount in bytes to current reporting scale
+  inline size_t amount_in_current_scale(size_t amount) const {
+    return NMTUtil::amount_in_scale(amount, _scale);
+  }
 
-  /* report baseline summary information */
-  virtual void total_usage(size_t total_reserved,
-                           size_t total_committed) = 0;
-  virtual void num_of_classes(size_t classes) = 0;
-  virtual void num_of_threads(size_t threads) = 0;
+  // Convert diff amount in bytes to current reporting scale
+  inline long diff_in_current_scale(size_t s1, size_t s2) const {
+    long amount = (long)(s1 - s2);
+    long scale = (long)_scale;
+    amount = (amount > 0) ? (amount + scale / 2) : (amount - scale / 2);
+    return amount / scale;
+  }
 
-  virtual void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) = 0;
-
-  /* report baseline summary comparison */
-  virtual void diff_total_usage(size_t total_reserved,
-                                size_t total_committed,
-                                int reserved_diff,
-                                int committed_diff) = 0;
-  virtual void diff_num_of_classes(size_t classes, int diff) = 0;
-  virtual void diff_num_of_threads(size_t threads, int diff) = 0;
-
-  virtual void diff_thread_info(size_t stack_reserved, size_t stack_committed,
-        int stack_reserved_diff, int stack_committed_diff) = 0;
+  // Helper functions
+  // Calculate total reserved and committed amount
+  size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const;
+  size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const;
 
 
-  /*
-   * memory summary by memory types.
-   * for each memory type, following summaries are reported:
-   *  - reserved amount, committed amount
-   *  - malloc'd amount, malloc count
-   *  - arena amount, arena count
-   */
+  // Print summary total, malloc and virtual memory
+  void print_total(size_t reserved, size_t committed) const;
+  void print_malloc(size_t amount, size_t count) const;
+  void print_virtual_memory(size_t reserved, size_t committed) const;
 
-  // start reporting memory summary by memory type
-  virtual void start_category_summary() = 0;
+  void print_malloc_line(size_t amount, size_t count) const;
+  void print_virtual_memory_line(size_t reserved, size_t committed) const;
+  void print_arena_line(size_t amount, size_t count) const;
 
-  virtual void category_summary(MEMFLAGS type, size_t reserved_amt,
-                                size_t committed_amt,
-                                size_t malloc_amt, size_t malloc_count,
-                                size_t arena_amt, size_t arena_count) = 0;
-
-  virtual void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt,
-                                size_t cur_committed_amt,
-                                size_t cur_malloc_amt, size_t cur_malloc_count,
-                                size_t cur_arena_amt, size_t cur_arena_count,
-                                int reserved_diff, int committed_diff, int malloc_diff,
-                                int malloc_count_diff, int arena_diff,
-                                int arena_count_diff) = 0;
-
-  virtual void done_category_summary() = 0;
-
-  virtual void start_virtual_memory_map() = 0;
-  virtual void reserved_memory_region(MEMFLAGS type, address base, address end, size_t size, address pc) = 0;
-  virtual void committed_memory_region(address base, address end, size_t size, address pc) = 0;
-  virtual void done_virtual_memory_map() = 0;
-
-  /*
-   *  Report callsite information
-   */
-  virtual void start_callsite() = 0;
-  virtual void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count) = 0;
-  virtual void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt) = 0;
-
-  virtual void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count,
-              int malloc_diff, int malloc_count_diff) = 0;
-  virtual void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt,
-              int reserved_diff, int committed_diff) = 0;
-
-  virtual void done_callsite() = 0;
-
-  // return current scale in "KB", "MB" or "GB"
-  static const char* memory_unit(size_t scale);
+  void print_virtual_memory_region(const char* type, address base, size_t size) const;
 };
 
 /*
- * This class reports processed data from a baseline or
- * the changes between the two baseline.
+ * The class is for generating summary tracking report.
  */
-class BaselineReporter : public StackObj {
+class MemSummaryReporter : public MemReporterBase {
  private:
-  BaselineOutputer&  _outputer;
-  size_t             _scale;
+  MallocMemorySnapshot*   _malloc_snapshot;
+  VirtualMemorySnapshot*  _vm_snapshot;
+  size_t                  _class_count;
 
  public:
-  // construct a reporter that reports memory usage
-  // in specified scale
-  BaselineReporter(BaselineOutputer& outputer, size_t scale = K):
-    _outputer(outputer) {
-    _scale = scale;
+  // Report summary tracking data from global snapshots directly.
+  // This constructor is used for final reporting and hs_err reporting.
+  MemSummaryReporter(MallocMemorySnapshot* malloc_snapshot,
+    VirtualMemorySnapshot* vm_snapshot, outputStream* output,
+    size_t class_count = 0, size_t scale = K) :
+    MemReporterBase(output, scale),
+    _malloc_snapshot(malloc_snapshot),
+    _vm_snapshot(vm_snapshot) {
+    if (class_count == 0) {
+      _class_count = InstanceKlass::number_of_instance_classes();
+    } else {
+      _class_count = class_count;
+    }
   }
-  virtual void report_baseline(const MemBaseline& baseline, bool summary_only = false);
-  virtual void diff_baselines(const MemBaseline& cur, const MemBaseline& prev,
-                              bool summary_only = false);
+  // This constructor is for normal reporting from a recent baseline.
+  MemSummaryReporter(MemBaseline& baseline, outputStream* output,
+    size_t scale = K) : MemReporterBase(output, scale),
+    _malloc_snapshot(baseline.malloc_memory_snapshot()),
+    _vm_snapshot(baseline.virtual_memory_snapshot()),
+    _class_count(baseline.class_count()) { }
 
-  void set_scale(size_t scale);
-  size_t scale() const { return _scale; }
 
+  // Generate summary report
+  virtual void report();
  private:
-  void report_summaries(const MemBaseline& baseline);
-  void report_virtual_memory_map(const MemBaseline& baseline);
-  void report_callsites(const MemBaseline& baseline);
-
-  void diff_summaries(const MemBaseline& cur, const MemBaseline& prev);
-  void diff_callsites(const MemBaseline& cur, const MemBaseline& prev);
-
-  // calculate memory size in current memory scale
-  size_t amount_in_current_scale(size_t amt) const;
-  // diff two unsigned values in current memory scale
-  int    diff_in_current_scale(size_t value1, size_t value2) const;
-  // diff two unsigned value
-  int    diff(size_t value1, size_t value2) const;
+  // Report summary for each memory type
+  void report_summary_of_type(MEMFLAGS type, MallocMemory* malloc_memory,
+    VirtualMemory* virtual_memory);
 };
 
 /*
- * tty output implementation. Native memory tracking
- * DCmd uses this outputer.
+ * The class is for generating detail tracking report.
  */
-class BaselineTTYOutputer : public BaselineOutputer {
+class MemDetailReporter : public MemSummaryReporter {
  private:
-  size_t         _scale;
-
-  size_t         _num_of_classes;
-  size_t         _num_of_threads;
-  size_t         _thread_stack_reserved;
-  size_t         _thread_stack_committed;
-
-  int            _num_of_classes_diff;
-  int            _num_of_threads_diff;
-  int            _thread_stack_reserved_diff;
-  int            _thread_stack_committed_diff;
-
-  outputStream*  _output;
+  MemBaseline&   _baseline;
 
  public:
-  BaselineTTYOutputer(outputStream* st) {
-    _scale = K;
-    _num_of_classes = 0;
-    _num_of_threads = 0;
-    _thread_stack_reserved = 0;
-    _thread_stack_committed = 0;
-    _num_of_classes_diff = 0;
-    _num_of_threads_diff = 0;
-    _thread_stack_reserved_diff = 0;
-    _thread_stack_committed_diff = 0;
-    _output = st;
+  MemDetailReporter(MemBaseline& baseline, outputStream* output, size_t scale = K) :
+    MemSummaryReporter(baseline, output, scale),
+     _baseline(baseline) { }
+
+  // Generate detail report.
+  // The report contains summary and detail sections.
+  virtual void report() {
+    MemSummaryReporter::report();
+    report_virtual_memory_map();
+    report_detail();
   }
 
-  // begin reporting memory usage in specified scale
-  void start(size_t scale, bool report_diff = false);
-  // done reporting
-  void done();
+ private:
+  // Report detail tracking data.
+  void report_detail();
+  // Report virtual memory map
+  void report_virtual_memory_map();
+  // Report malloc allocation sites
+  void report_malloc_sites();
+  // Report virtual memory reservation sites
+  void report_virtual_memory_allocation_sites();
 
-  // total memory usage
-  void total_usage(size_t total_reserved,
-                   size_t total_committed);
-  // report total loaded classes
-  void num_of_classes(size_t classes) {
-    _num_of_classes = classes;
-  }
-
-  void num_of_threads(size_t threads) {
-    _num_of_threads = threads;
-  }
-
-  void thread_info(size_t stack_reserved_amt, size_t stack_committed_amt) {
-    _thread_stack_reserved = stack_reserved_amt;
-    _thread_stack_committed = stack_committed_amt;
-  }
-
-  void diff_total_usage(size_t total_reserved,
-                        size_t total_committed,
-                        int reserved_diff,
-                        int committed_diff);
-
-  void diff_num_of_classes(size_t classes, int diff) {
-    _num_of_classes = classes;
-    _num_of_classes_diff = diff;
-  }
-
-  void diff_num_of_threads(size_t threads, int diff) {
-    _num_of_threads = threads;
-    _num_of_threads_diff = diff;
-  }
-
-  void diff_thread_info(size_t stack_reserved_amt, size_t stack_committed_amt,
-               int stack_reserved_diff, int stack_committed_diff) {
-    _thread_stack_reserved = stack_reserved_amt;
-    _thread_stack_committed = stack_committed_amt;
-    _thread_stack_reserved_diff = stack_reserved_diff;
-    _thread_stack_committed_diff = stack_committed_diff;
-  }
-
-  /*
-   * Report memory summary categoriuzed by memory types.
-   * For each memory type, following summaries are reported:
-   *  - reserved amount, committed amount
-   *  - malloc-ed amount, malloc count
-   *  - arena amount, arena count
-   */
-  // start reporting memory summary by memory type
-  void start_category_summary();
-  void category_summary(MEMFLAGS type, size_t reserved_amt, size_t committed_amt,
-                               size_t malloc_amt, size_t malloc_count,
-                               size_t arena_amt, size_t arena_count);
-
-  void diff_category_summary(MEMFLAGS type, size_t cur_reserved_amt,
-                          size_t cur_committed_amt,
-                          size_t cur_malloc_amt, size_t cur_malloc_count,
-                          size_t cur_arena_amt, size_t cur_arena_count,
-                          int reserved_diff, int committed_diff, int malloc_diff,
-                          int malloc_count_diff, int arena_diff,
-                          int arena_count_diff);
-
-  void done_category_summary();
-
-  // virtual memory map
-  void start_virtual_memory_map();
-  void reserved_memory_region(MEMFLAGS type, address base, address end, size_t size, address pc);
-  void committed_memory_region(address base, address end, size_t size, address pc);
-  void done_virtual_memory_map();
-
-
-  /*
-   *  Report callsite information
-   */
-  void start_callsite();
-  void malloc_callsite(address pc, size_t malloc_amt, size_t malloc_count);
-  void virtual_memory_callsite(address pc, size_t reserved_amt, size_t committed_amt);
-
-  void diff_malloc_callsite(address pc, size_t cur_malloc_amt, size_t cur_malloc_count,
-              int malloc_diff, int malloc_count_diff);
-  void diff_virtual_memory_callsite(address pc, size_t cur_reserved_amt, size_t cur_committed_amt,
-              int reserved_diff, int committed_diff);
-
-  void done_callsite();
+  // Report a virtual memory region
+  void report_virtual_memory_region(const ReservedMemoryRegion* rgn);
 };
 
+/*
+ * The class is for generating summary comparison report.
+ * It compares current memory baseline against an early baseline.
+ */
+class MemSummaryDiffReporter : public MemReporterBase {
+ protected:
+  MemBaseline&      _early_baseline;
+  MemBaseline&      _current_baseline;
+
+ public:
+  MemSummaryDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline,
+    outputStream* output, size_t scale = K) : MemReporterBase(output, scale),
+    _early_baseline(early_baseline), _current_baseline(current_baseline) {
+    assert(early_baseline.baseline_type()   != MemBaseline::Not_baselined, "Not baselined");
+    assert(current_baseline.baseline_type() != MemBaseline::Not_baselined, "Not baselined");
+  }
+
+  // Generate summary comparison report
+  virtual void report_diff();
+
+ private:
+  // report the comparison of each memory type
+  void diff_summary_of_type(MEMFLAGS type,
+    const MallocMemory* early_malloc, const VirtualMemory* early_vm,
+    const MallocMemory* current_malloc, const VirtualMemory* current_vm) const;
+
+ protected:
+  void print_malloc_diff(size_t current_amount, size_t current_count,
+    size_t early_amount, size_t early_count) const;
+  void print_virtual_memory_diff(size_t current_reserved, size_t current_committed,
+    size_t early_reserved, size_t early_committed) const;
+  void print_arena_diff(size_t current_amount, size_t current_count,
+    size_t early_amount, size_t early_count) const;
+};
+
+/*
+ * The class is for generating detail comparison report.
+ * It compares current memory baseline against an early baseline,
+ * both baselines have to be detail baseline.
+ */
+class MemDetailDiffReporter : public MemSummaryDiffReporter {
+ public:
+  MemDetailDiffReporter(MemBaseline& early_baseline, MemBaseline& current_baseline,
+    outputStream* output, size_t scale = K) :
+    MemSummaryDiffReporter(early_baseline, current_baseline, output, scale) { }
+
+  // Generate detail comparison report
+  virtual void report_diff();
+
+  // Malloc allocation site comparison
+  void diff_malloc_sites() const;
+  // Virutal memory reservation site comparison
+  void diff_virtual_memory_sites() const;
+
+  // New malloc allocation site in recent baseline
+  void new_malloc_site (const MallocSite* site) const;
+  // The malloc allocation site is not in recent baseline
+  void old_malloc_site (const MallocSite* site) const;
+  // Compare malloc allocation site, it is in both baselines
+  void diff_malloc_site(const MallocSite* early, const MallocSite* current)  const;
+
+  // New virtual memory allocation site in recent baseline
+  void new_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const;
+  // The virtual memory allocation site is not in recent baseline
+  void old_virtual_memory_site (const VirtualMemoryAllocationSite* callsite) const;
+  // Compare virtual memory allocation site, it is in both baseline
+  void diff_virtual_memory_site(const VirtualMemoryAllocationSite* early,
+                                const VirtualMemoryAllocationSite* current)  const;
+
+  void diff_malloc_site(const NativeCallStack* stack, size_t current_size,
+    size_t currrent_count, size_t early_size, size_t early_count) const;
+  void diff_virtual_memory_site(const NativeCallStack* stack, size_t current_reserved,
+    size_t current_committed, size_t early_reserved, size_t early_committed) const;
+};
 
 #endif // INCLUDE_NMT
 
-#endif // SHARE_VM_SERVICES_MEM_REPORTER_HPP
+#endif
+
diff --git a/hotspot/src/share/vm/services/memSnapshot.cpp b/hotspot/src/share/vm/services/memSnapshot.cpp
deleted file mode 100644
index 8f5ca4f..0000000
--- a/hotspot/src/share/vm/services/memSnapshot.cpp
+++ /dev/null
@@ -1,748 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "utilities/decoder.hpp"
-#include "services/memBaseline.hpp"
-#include "services/memPtr.hpp"
-#include "services/memPtrArray.hpp"
-#include "services/memSnapshot.hpp"
-#include "services/memTracker.hpp"
-
-PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
-
-#ifdef ASSERT
-
-void decode_pointer_record(MemPointerRecord* rec) {
-  tty->print("Pointer: [" PTR_FORMAT " - " PTR_FORMAT  "] size = %d bytes", rec->addr(),
-    rec->addr() + rec->size(), (int)rec->size());
-  tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags())));
-  if (rec->is_vm_pointer()) {
-    if (rec->is_allocation_record()) {
-      tty->print_cr(" (reserve)");
-    } else if (rec->is_commit_record()) {
-      tty->print_cr(" (commit)");
-    } else if (rec->is_uncommit_record()) {
-      tty->print_cr(" (uncommit)");
-    } else if (rec->is_deallocation_record()) {
-      tty->print_cr(" (release)");
-    } else {
-      tty->print_cr(" (tag)");
-    }
-  } else {
-    if (rec->is_arena_memory_record()) {
-      tty->print_cr(" (arena size)");
-    } else if (rec->is_allocation_record()) {
-      tty->print_cr(" (malloc)");
-    } else {
-      tty->print_cr(" (free)");
-    }
-  }
-  if (MemTracker::track_callsite()) {
-    char buf[1024];
-    address pc = ((MemPointerRecordEx*)rec)->pc();
-    if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) {
-      tty->print_cr("\tfrom %s", buf);
-    } else {
-      tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc);
-    }
-  }
-}
-
-void decode_vm_region_record(VMMemRegion* rec) {
-  tty->print("VM Region [" PTR_FORMAT " - " PTR_FORMAT "]", rec->addr(),
-    rec->addr() + rec->size());
-  tty->print(" type = %s", MemBaseline::type2name(FLAGS_TO_MEMORY_TYPE(rec->flags())));
-  if (rec->is_allocation_record()) {
-    tty->print_cr(" (reserved)");
-  } else if (rec->is_commit_record()) {
-    tty->print_cr(" (committed)");
-  } else {
-    ShouldNotReachHere();
-  }
-  if (MemTracker::track_callsite()) {
-    char buf[1024];
-    address pc = ((VMMemRegionEx*)rec)->pc();
-    if (pc != NULL && os::dll_address_to_function_name(pc, buf, sizeof(buf), NULL)) {
-      tty->print_cr("\tfrom %s", buf);
-    } else {
-      tty->print_cr("\tcould not decode pc = " PTR_FORMAT "", pc);
-    }
-
-  }
-}
-
-#endif
-
-
-bool VMMemPointerIterator::insert_record(MemPointerRecord* rec) {
-  VMMemRegionEx new_rec;
-  assert(rec->is_allocation_record() || rec->is_commit_record(),
-    "Sanity check");
-  if (MemTracker::track_callsite()) {
-    new_rec.init((MemPointerRecordEx*)rec);
-  } else {
-    new_rec.init(rec);
-  }
-  return insert(&new_rec);
-}
-
-bool VMMemPointerIterator::insert_record_after(MemPointerRecord* rec) {
-  VMMemRegionEx new_rec;
-  assert(rec->is_allocation_record() || rec->is_commit_record(),
-    "Sanity check");
-  if (MemTracker::track_callsite()) {
-    new_rec.init((MemPointerRecordEx*)rec);
-  } else {
-    new_rec.init(rec);
-  }
-  return insert_after(&new_rec);
-}
-
-// we don't consolidate reserved regions, since they may be categorized
-// in different types.
-bool VMMemPointerIterator::add_reserved_region(MemPointerRecord* rec) {
-  assert(rec->is_allocation_record(), "Sanity check");
-  VMMemRegion* reserved_region = (VMMemRegion*)current();
-
-  // we don't have anything yet
-  if (reserved_region == NULL) {
-    return insert_record(rec);
-  }
-
-  assert(reserved_region->is_reserved_region(), "Sanity check");
-  // duplicated records
-  if (reserved_region->is_same_region(rec)) {
-    return true;
-  }
-  // Overlapping stack regions indicate that a JNI thread failed to
-  // detach from the VM before exiting. This leaks the JavaThread object.
-  if (CheckJNICalls)  {
-      guarantee(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) != mtThreadStack ||
-         !reserved_region->overlaps_region(rec),
-         "Attached JNI thread exited without being detached");
-  }
-  // otherwise, we should not have overlapping reserved regions
-  assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack ||
-    reserved_region->base() > rec->addr(), "Just check: locate()");
-  assert(FLAGS_TO_MEMORY_TYPE(reserved_region->flags()) == mtThreadStack ||
-    !reserved_region->overlaps_region(rec), "overlapping reserved regions");
-
-  return insert_record(rec);
-}
-
-// we do consolidate committed regions
-bool VMMemPointerIterator::add_committed_region(MemPointerRecord* rec) {
-  assert(rec->is_commit_record(), "Sanity check");
-  VMMemRegion* reserved_rgn = (VMMemRegion*)current();
-  assert(reserved_rgn->is_reserved_region() && reserved_rgn->contains_region(rec),
-    "Sanity check");
-
-  // thread's native stack is always marked as "committed", ignore
-  // the "commit" operation for creating stack guard pages
-  if (FLAGS_TO_MEMORY_TYPE(reserved_rgn->flags()) == mtThreadStack &&
-      FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) {
-    return true;
-  }
-
-  // if the reserved region has any committed regions
-  VMMemRegion* committed_rgn  = (VMMemRegion*)next();
-  while (committed_rgn != NULL && committed_rgn->is_committed_region()) {
-    // duplicated commit records
-    if(committed_rgn->contains_region(rec)) {
-      return true;
-    } else if (committed_rgn->overlaps_region(rec)) {
-      // overlaps front part
-      if (rec->addr() < committed_rgn->addr()) {
-        committed_rgn->expand_region(rec->addr(),
-          committed_rgn->addr() - rec->addr());
-      } else {
-        // overlaps tail part
-        address committed_rgn_end = committed_rgn->addr() +
-              committed_rgn->size();
-        assert(committed_rgn_end < rec->addr() + rec->size(),
-             "overlap tail part");
-        committed_rgn->expand_region(committed_rgn_end,
-          (rec->addr() + rec->size()) - committed_rgn_end);
-      }
-    } else if (committed_rgn->base() + committed_rgn->size() == rec->addr()) {
-      // adjunct each other
-      committed_rgn->expand_region(rec->addr(), rec->size());
-      VMMemRegion* next_reg = (VMMemRegion*)next();
-      // see if we can consolidate next committed region
-      if (next_reg != NULL && next_reg->is_committed_region() &&
-        next_reg->base() == committed_rgn->base() + committed_rgn->size()) {
-          committed_rgn->expand_region(next_reg->base(), next_reg->size());
-          // delete merged region
-          remove();
-      }
-      return true;
-    } else if (committed_rgn->base() > rec->addr()) {
-      // found the location, insert this committed region
-      return insert_record(rec);
-    }
-    committed_rgn = (VMMemRegion*)next();
-  }
-  return insert_record(rec);
-}
-
-bool VMMemPointerIterator::remove_uncommitted_region(MemPointerRecord* rec) {
-  assert(rec->is_uncommit_record(), "sanity check");
-  VMMemRegion* cur;
-  cur = (VMMemRegion*)current();
-  assert(cur->is_reserved_region() && cur->contains_region(rec),
-    "Sanity check");
-  // thread's native stack is always marked as "committed", ignore
-  // the "commit" operation for creating stack guard pages
-  if (FLAGS_TO_MEMORY_TYPE(cur->flags()) == mtThreadStack &&
-      FLAGS_TO_MEMORY_TYPE(rec->flags()) != mtThreadStack) {
-    return true;
-  }
-
-  cur = (VMMemRegion*)next();
-  while (cur != NULL && cur->is_committed_region()) {
-    // region already uncommitted, must be due to duplicated record
-    if (cur->addr() >= rec->addr() + rec->size()) {
-      break;
-    } else if (cur->contains_region(rec)) {
-      // uncommit whole region
-      if (cur->is_same_region(rec)) {
-        remove();
-        break;
-      } else if (rec->addr() == cur->addr() ||
-        rec->addr() + rec->size() == cur->addr() + cur->size()) {
-        // uncommitted from either end of current memory region.
-        cur->exclude_region(rec->addr(), rec->size());
-        break;
-      } else { // split the committed region and release the middle
-        address high_addr = cur->addr() + cur->size();
-        size_t sz = high_addr - rec->addr();
-        cur->exclude_region(rec->addr(), sz);
-        sz = high_addr - (rec->addr() + rec->size());
-        if (MemTracker::track_callsite()) {
-          MemPointerRecordEx tmp(rec->addr() + rec->size(), cur->flags(), sz,
-             ((VMMemRegionEx*)cur)->pc());
-          return insert_record_after(&tmp);
-        } else {
-          MemPointerRecord tmp(rec->addr() + rec->size(), cur->flags(), sz);
-          return insert_record_after(&tmp);
-        }
-      }
-    }
-    cur = (VMMemRegion*)next();
-  }
-
-  // we may not find committed record due to duplicated records
-  return true;
-}
-
-bool VMMemPointerIterator::remove_released_region(MemPointerRecord* rec) {
-  assert(rec->is_deallocation_record(), "Sanity check");
-  VMMemRegion* cur = (VMMemRegion*)current();
-  assert(cur->is_reserved_region() && cur->contains_region(rec),
-    "Sanity check");
-  if (rec->is_same_region(cur)) {
-
-    // In snapshot, the virtual memory records are sorted in following orders:
-    // 1. virtual memory's base address
-    // 2. virtual memory reservation record, followed by commit records within this reservation.
-    //    The commit records are also in base address order.
-    // When a reserved region is released, we want to remove the reservation record and all
-    // commit records following it.
-#ifdef ASSERT
-    address low_addr = cur->addr();
-    address high_addr = low_addr + cur->size();
-#endif
-    // remove virtual memory reservation record
-    remove();
-    // remove committed regions within above reservation
-    VMMemRegion* next_region = (VMMemRegion*)current();
-    while (next_region != NULL && next_region->is_committed_region()) {
-      assert(next_region->addr() >= low_addr &&
-             next_region->addr() + next_region->size() <= high_addr,
-            "Range check");
-      remove();
-      next_region = (VMMemRegion*)current();
-    }
-  } else if (rec->addr() == cur->addr() ||
-    rec->addr() + rec->size() == cur->addr() + cur->size()) {
-    // released region is at either end of this region
-    cur->exclude_region(rec->addr(), rec->size());
-    assert(check_reserved_region(), "Integrity check");
-  } else { // split the reserved region and release the middle
-    address high_addr = cur->addr() + cur->size();
-    size_t sz = high_addr - rec->addr();
-    cur->exclude_region(rec->addr(), sz);
-    sz = high_addr - rec->addr() - rec->size();
-    if (MemTracker::track_callsite()) {
-      MemPointerRecordEx tmp(rec->addr() + rec->size(), cur->flags(), sz,
-        ((VMMemRegionEx*)cur)->pc());
-      bool ret = insert_reserved_region(&tmp);
-      assert(!ret || check_reserved_region(), "Integrity check");
-      return ret;
-    } else {
-      MemPointerRecord tmp(rec->addr() + rec->size(), cur->flags(), sz);
-      bool ret = insert_reserved_region(&tmp);
-      assert(!ret || check_reserved_region(), "Integrity check");
-      return ret;
-    }
-  }
-  return true;
-}
-
-bool VMMemPointerIterator::insert_reserved_region(MemPointerRecord* rec) {
-  // skip all 'commit' records associated with previous reserved region
-  VMMemRegion* p = (VMMemRegion*)next();
-  while (p != NULL && p->is_committed_region() &&
-         p->base() + p->size() < rec->addr()) {
-    p = (VMMemRegion*)next();
-  }
-  return insert_record(rec);
-}
-
-bool VMMemPointerIterator::split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size) {
-  assert(rgn->contains_region(new_rgn_addr, new_rgn_size), "Not fully contained");
-  address pc = (MemTracker::track_callsite() ? ((VMMemRegionEx*)rgn)->pc() : NULL);
-  if (rgn->base() == new_rgn_addr) { // new region is at the beginning of the region
-    size_t sz = rgn->size() - new_rgn_size;
-    // the original region becomes 'new' region
-    rgn->exclude_region(new_rgn_addr + new_rgn_size, sz);
-     // remaining becomes next region
-    MemPointerRecordEx next_rgn(new_rgn_addr + new_rgn_size, rgn->flags(), sz, pc);
-    return insert_reserved_region(&next_rgn);
-  } else if (rgn->base() + rgn->size() == new_rgn_addr + new_rgn_size) {
-    rgn->exclude_region(new_rgn_addr, new_rgn_size);
-    MemPointerRecordEx next_rgn(new_rgn_addr, rgn->flags(), new_rgn_size, pc);
-    return insert_reserved_region(&next_rgn);
-  } else {
-    // the orginal region will be split into three
-    address rgn_high_addr = rgn->base() + rgn->size();
-    // first region
-    rgn->exclude_region(new_rgn_addr, (rgn_high_addr - new_rgn_addr));
-    // the second region is the new region
-    MemPointerRecordEx new_rgn(new_rgn_addr, rgn->flags(), new_rgn_size, pc);
-    if (!insert_reserved_region(&new_rgn)) return false;
-    // the remaining region
-    MemPointerRecordEx rem_rgn(new_rgn_addr + new_rgn_size, rgn->flags(),
-      rgn_high_addr - (new_rgn_addr + new_rgn_size), pc);
-    return insert_reserved_region(&rem_rgn);
-  }
-}
-
-static int sort_in_seq_order(const void* p1, const void* p2) {
-  assert(p1 != NULL && p2 != NULL, "Sanity check");
-  const MemPointerRecord* mp1 = (MemPointerRecord*)p1;
-  const MemPointerRecord* mp2 = (MemPointerRecord*)p2;
-  return (mp1->seq() - mp2->seq());
-}
-
-bool StagingArea::init() {
-  if (MemTracker::track_callsite()) {
-    _malloc_data = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecordEx>();
-    _vm_data = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecordEx>();
-  } else {
-    _malloc_data = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecord>();
-    _vm_data = new (std::nothrow)MemPointerArrayImpl<SeqMemPointerRecord>();
-  }
-
-  if (_malloc_data != NULL && _vm_data != NULL &&
-      !_malloc_data->out_of_memory() &&
-      !_vm_data->out_of_memory()) {
-    return true;
-  } else {
-    if (_malloc_data != NULL) delete _malloc_data;
-    if (_vm_data != NULL) delete _vm_data;
-    _malloc_data = NULL;
-    _vm_data = NULL;
-    return false;
-  }
-}
-
-
-VMRecordIterator StagingArea::virtual_memory_record_walker() {
-  MemPointerArray* arr = vm_data();
-  // sort into seq number order
-  arr->sort((FN_SORT)sort_in_seq_order);
-  return VMRecordIterator(arr);
-}
-
-
-MemSnapshot::MemSnapshot() {
-  if (MemTracker::track_callsite()) {
-    _alloc_ptrs = new (std::nothrow) MemPointerArrayImpl<MemPointerRecordEx>();
-    _vm_ptrs = new (std::nothrow)MemPointerArrayImpl<VMMemRegionEx>(64, true);
-  } else {
-    _alloc_ptrs = new (std::nothrow) MemPointerArrayImpl<MemPointerRecord>();
-    _vm_ptrs = new (std::nothrow)MemPointerArrayImpl<VMMemRegion>(64, true);
-  }
-
-  _staging_area.init();
-  _lock = new (std::nothrow) Mutex(Monitor::max_nonleaf - 1, "memSnapshotLock");
-  NOT_PRODUCT(_untracked_count = 0;)
-  _number_of_classes = 0;
-}
-
-MemSnapshot::~MemSnapshot() {
-  assert(MemTracker::shutdown_in_progress(), "native memory tracking still on");
-  {
-    MutexLockerEx locker(_lock);
-    if (_alloc_ptrs != NULL) {
-      delete _alloc_ptrs;
-      _alloc_ptrs = NULL;
-    }
-
-    if (_vm_ptrs != NULL) {
-      delete _vm_ptrs;
-      _vm_ptrs = NULL;
-    }
-  }
-
-  if (_lock != NULL) {
-    delete _lock;
-    _lock = NULL;
-  }
-}
-
-
-void MemSnapshot::copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src) {
-  assert(dest != NULL && src != NULL, "Just check");
-  assert(dest->addr() == src->addr(), "Just check");
-  assert(dest->seq() > 0 && src->seq() > 0, "not sequenced");
-
-  if (MemTracker::track_callsite()) {
-    *(SeqMemPointerRecordEx*)dest = *(SeqMemPointerRecordEx*)src;
-  } else {
-    *(SeqMemPointerRecord*)dest = *(SeqMemPointerRecord*)src;
-  }
-}
-
-void MemSnapshot::assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src) {
-  assert(src != NULL && dest != NULL, "Just check");
-  assert(dest->seq() == 0 && src->seq() >0, "cast away sequence");
-
-  if (MemTracker::track_callsite()) {
-    *(MemPointerRecordEx*)dest = *(MemPointerRecordEx*)src;
-  } else {
-    *(MemPointerRecord*)dest = *(MemPointerRecord*)src;
-  }
-}
-
-// merge a recorder to the staging area
-bool MemSnapshot::merge(MemRecorder* rec) {
-  assert(rec != NULL && !rec->out_of_memory(), "Just check");
-
-  SequencedRecordIterator itr(rec->pointer_itr());
-
-  MutexLockerEx lock(_lock, true);
-  MemPointerIterator malloc_staging_itr(_staging_area.malloc_data());
-  MemPointerRecord* incoming_rec = (MemPointerRecord*) itr.current();
-  MemPointerRecord* matched_rec;
-
-  while (incoming_rec != NULL) {
-    if (incoming_rec->is_vm_pointer()) {
-      // we don't do anything with virtual memory records during merge
-      if (!_staging_area.vm_data()->append(incoming_rec)) {
-        return false;
-      }
-    } else {
-      // locate matched record and/or also position the iterator to proper
-      // location for this incoming record.
-      matched_rec = (MemPointerRecord*)malloc_staging_itr.locate(incoming_rec->addr());
-      // we have not seen this memory block in this generation,
-      // so just add to staging area
-      if (matched_rec == NULL) {
-        if (!malloc_staging_itr.insert(incoming_rec)) {
-          return false;
-        }
-      } else if (incoming_rec->addr() == matched_rec->addr()) {
-        // whoever has higher sequence number wins
-        if (incoming_rec->seq() > matched_rec->seq()) {
-          copy_seq_pointer(matched_rec, incoming_rec);
-        }
-      } else if (incoming_rec->addr() < matched_rec->addr()) {
-        if (!malloc_staging_itr.insert(incoming_rec)) {
-          return false;
-        }
-      } else {
-        ShouldNotReachHere();
-      }
-    }
-    incoming_rec = (MemPointerRecord*)itr.next();
-  }
-  NOT_PRODUCT(void check_staging_data();)
-  return true;
-}
-
-
-// promote data to next generation
-bool MemSnapshot::promote(int number_of_classes) {
-  assert(_alloc_ptrs != NULL && _vm_ptrs != NULL, "Just check");
-  assert(_staging_area.malloc_data() != NULL && _staging_area.vm_data() != NULL,
-         "Just check");
-  MutexLockerEx lock(_lock, true);
-
-  MallocRecordIterator  malloc_itr = _staging_area.malloc_record_walker();
-  bool promoted = false;
-  if (promote_malloc_records(&malloc_itr)) {
-    VMRecordIterator vm_itr = _staging_area.virtual_memory_record_walker();
-    if (promote_virtual_memory_records(&vm_itr)) {
-      promoted = true;
-    }
-  }
-
-  NOT_PRODUCT(check_malloc_pointers();)
-  _staging_area.clear();
-  _number_of_classes = number_of_classes;
-  return promoted;
-}
-
-bool MemSnapshot::promote_malloc_records(MemPointerArrayIterator* itr) {
-  MemPointerIterator malloc_snapshot_itr(_alloc_ptrs);
-  MemPointerRecord* new_rec = (MemPointerRecord*)itr->current();
-  MemPointerRecord* matched_rec;
-  while (new_rec != NULL) {
-    matched_rec = (MemPointerRecord*)malloc_snapshot_itr.locate(new_rec->addr());
-    // found matched memory block
-    if (matched_rec != NULL && new_rec->addr() == matched_rec->addr()) {
-      // snapshot already contains 'live' records
-      assert(matched_rec->is_allocation_record() || matched_rec->is_arena_memory_record(),
-             "Sanity check");
-      // update block states
-      if (new_rec->is_allocation_record()) {
-        assign_pointer(matched_rec, new_rec);
-      } else if (new_rec->is_arena_memory_record()) {
-        if (new_rec->size() == 0) {
-          // remove size record once size drops to 0
-          malloc_snapshot_itr.remove();
-        } else {
-          assign_pointer(matched_rec, new_rec);
-        }
-      } else {
-        // a deallocation record
-        assert(new_rec->is_deallocation_record(), "Sanity check");
-        // an arena record can be followed by a size record, we need to remove both
-        if (matched_rec->is_arena_record()) {
-          MemPointerRecord* next = (MemPointerRecord*)malloc_snapshot_itr.peek_next();
-          if (next != NULL && next->is_arena_memory_record() &&
-              next->is_memory_record_of_arena(matched_rec)) {
-            malloc_snapshot_itr.remove();
-          }
-        }
-        // the memory is deallocated, remove related record(s)
-        malloc_snapshot_itr.remove();
-      }
-    } else {
-      // don't insert size 0 record
-      if (new_rec->is_arena_memory_record() && new_rec->size() == 0) {
-        new_rec = NULL;
-      }
-
-      if (new_rec != NULL) {
-        if  (new_rec->is_allocation_record() || new_rec->is_arena_memory_record()) {
-          if (matched_rec != NULL && new_rec->addr() > matched_rec->addr()) {
-            if (!malloc_snapshot_itr.insert_after(new_rec)) {
-              return false;
-            }
-          } else {
-            if (!malloc_snapshot_itr.insert(new_rec)) {
-              return false;
-            }
-          }
-        }
-#ifndef PRODUCT
-        else if (!has_allocation_record(new_rec->addr())) {
-          // NMT can not track some startup memory, which is allocated before NMT is on
-          _untracked_count ++;
-        }
-#endif
-      }
-    }
-    new_rec = (MemPointerRecord*)itr->next();
-  }
-  return true;
-}
-
-bool MemSnapshot::promote_virtual_memory_records(MemPointerArrayIterator* itr) {
-  VMMemPointerIterator vm_snapshot_itr(_vm_ptrs);
-  MemPointerRecord* new_rec = (MemPointerRecord*)itr->current();
-  VMMemRegion*  reserved_rec;
-  while (new_rec != NULL) {
-    assert(new_rec->is_vm_pointer(), "Sanity check");
-
-    // locate a reserved region that contains the specified address, or
-    // the nearest reserved region has base address just above the specified
-    // address
-    reserved_rec = (VMMemRegion*)vm_snapshot_itr.locate(new_rec->addr());
-    if (reserved_rec != NULL && reserved_rec->contains_region(new_rec)) {
-      // snapshot can only have 'live' records
-      assert(reserved_rec->is_reserved_region(), "Sanity check");
-      if (new_rec->is_allocation_record()) {
-        if (!reserved_rec->is_same_region(new_rec)) {
-          // only deal with split a bigger reserved region into smaller regions.
-          // So far, CDS is the only use case.
-          if (!vm_snapshot_itr.split_reserved_region(reserved_rec, new_rec->addr(), new_rec->size())) {
-            return false;
-          }
-        }
-      } else if (new_rec->is_uncommit_record()) {
-        if (!vm_snapshot_itr.remove_uncommitted_region(new_rec)) {
-          return false;
-        }
-      } else if (new_rec->is_commit_record()) {
-        // insert or expand existing committed region to cover this
-        // newly committed region
-        if (!vm_snapshot_itr.add_committed_region(new_rec)) {
-          return false;
-        }
-      } else if (new_rec->is_deallocation_record()) {
-        // release part or all memory region
-        if (!vm_snapshot_itr.remove_released_region(new_rec)) {
-          return false;
-        }
-      } else if (new_rec->is_type_tagging_record()) {
-        // tag this reserved virtual memory range to a memory type. Can not re-tag a memory range
-        // to different type.
-        assert(FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) == mtNone ||
-               FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) == FLAGS_TO_MEMORY_TYPE(new_rec->flags()),
-               "Sanity check");
-        reserved_rec->tag(new_rec->flags());
-    } else {
-        ShouldNotReachHere();
-          }
-        } else {
-      /*
-       * The assertion failure indicates mis-matched virtual memory records. The likely
-       * scenario is, that some virtual memory operations are not going through os::xxxx_memory()
-       * api, which have to be tracked manually. (perfMemory is an example).
-      */
-      assert(new_rec->is_allocation_record(), "Sanity check");
-      if (!vm_snapshot_itr.add_reserved_region(new_rec)) {
-            return false;
-          }
-  }
-    new_rec = (MemPointerRecord*)itr->next();
-  }
-  return true;
-}
-
-#ifndef PRODUCT
-void MemSnapshot::print_snapshot_stats(outputStream* st) {
-  st->print_cr("Snapshot:");
-  st->print_cr("\tMalloced: %d/%d [%5.2f%%]  %dKB", _alloc_ptrs->length(), _alloc_ptrs->capacity(),
-    (100.0 * (float)_alloc_ptrs->length()) / (float)_alloc_ptrs->capacity(), _alloc_ptrs->instance_size()/K);
-
-  st->print_cr("\tVM: %d/%d [%5.2f%%] %dKB", _vm_ptrs->length(), _vm_ptrs->capacity(),
-    (100.0 * (float)_vm_ptrs->length()) / (float)_vm_ptrs->capacity(), _vm_ptrs->instance_size()/K);
-
-  st->print_cr("\tMalloc staging Area:     %d/%d [%5.2f%%] %dKB", _staging_area.malloc_data()->length(),
-    _staging_area.malloc_data()->capacity(),
-    (100.0 * (float)_staging_area.malloc_data()->length()) / (float)_staging_area.malloc_data()->capacity(),
-    _staging_area.malloc_data()->instance_size()/K);
-
-  st->print_cr("\tVirtual memory staging Area:     %d/%d [%5.2f%%] %dKB", _staging_area.vm_data()->length(),
-    _staging_area.vm_data()->capacity(),
-    (100.0 * (float)_staging_area.vm_data()->length()) / (float)_staging_area.vm_data()->capacity(),
-    _staging_area.vm_data()->instance_size()/K);
-
-  st->print_cr("\tUntracked allocation: %d", _untracked_count);
-}
-
-void MemSnapshot::check_malloc_pointers() {
-  MemPointerArrayIteratorImpl mItr(_alloc_ptrs);
-  MemPointerRecord* p = (MemPointerRecord*)mItr.current();
-  MemPointerRecord* prev = NULL;
-  while (p != NULL) {
-    if (prev != NULL) {
-      assert(p->addr() >= prev->addr(), "sorting order");
-    }
-    prev = p;
-    p = (MemPointerRecord*)mItr.next();
-  }
-}
-
-bool MemSnapshot::has_allocation_record(address addr) {
-  MemPointerArrayIteratorImpl itr(_staging_area.malloc_data());
-  MemPointerRecord* cur = (MemPointerRecord*)itr.current();
-  while (cur != NULL) {
-    if (cur->addr() == addr && cur->is_allocation_record()) {
-      return true;
-    }
-    cur = (MemPointerRecord*)itr.next();
-  }
-  return false;
-}
-#endif // PRODUCT
-
-#ifdef ASSERT
-void MemSnapshot::check_staging_data() {
-  MemPointerArrayIteratorImpl itr(_staging_area.malloc_data());
-  MemPointerRecord* cur = (MemPointerRecord*)itr.current();
-  MemPointerRecord* next = (MemPointerRecord*)itr.next();
-  while (next != NULL) {
-    assert((next->addr() > cur->addr()) ||
-      ((next->flags() & MemPointerRecord::tag_masks) >
-       (cur->flags() & MemPointerRecord::tag_masks)),
-       "sorting order");
-    cur = next;
-    next = (MemPointerRecord*)itr.next();
-  }
-
-  MemPointerArrayIteratorImpl vm_itr(_staging_area.vm_data());
-  cur = (MemPointerRecord*)vm_itr.current();
-  while (cur != NULL) {
-    assert(cur->is_vm_pointer(), "virtual memory pointer only");
-    cur = (MemPointerRecord*)vm_itr.next();
-  }
-}
-
-void MemSnapshot::dump_all_vm_pointers() {
-  MemPointerArrayIteratorImpl itr(_vm_ptrs);
-  VMMemRegion* ptr = (VMMemRegion*)itr.current();
-  tty->print_cr("dump virtual memory pointers:");
-  while (ptr != NULL) {
-    if (ptr->is_committed_region()) {
-      tty->print("\t");
-    }
-    tty->print("[" PTR_FORMAT " - " PTR_FORMAT "] [%x]", ptr->addr(),
-      (ptr->addr() + ptr->size()), ptr->flags());
-
-    if (MemTracker::track_callsite()) {
-      VMMemRegionEx* ex = (VMMemRegionEx*)ptr;
-      if (ex->pc() != NULL) {
-        char buf[1024];
-        if (os::dll_address_to_function_name(ex->pc(), buf, sizeof(buf), NULL)) {
-          tty->print_cr("\t%s", buf);
-        } else {
-          tty->cr();
-        }
-      }
-    }
-
-    ptr = (VMMemRegion*)itr.next();
-  }
-  tty->flush();
-}
-#endif // ASSERT
-
diff --git a/hotspot/src/share/vm/services/memSnapshot.hpp b/hotspot/src/share/vm/services/memSnapshot.hpp
deleted file mode 100644
index f7d0756..0000000
--- a/hotspot/src/share/vm/services/memSnapshot.hpp
+++ /dev/null
@@ -1,408 +0,0 @@
-/*
- * Copyright (c) 2012, 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.
- *
- */
-
-#ifndef SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
-#define SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
-
-#include "memory/allocation.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "services/memBaseline.hpp"
-#include "services/memPtrArray.hpp"
-
-// Snapshot pointer array iterator
-
-// The pointer array contains malloc-ed pointers
-class MemPointerIterator : public MemPointerArrayIteratorImpl {
- public:
-  MemPointerIterator(MemPointerArray* arr):
-    MemPointerArrayIteratorImpl(arr) {
-    assert(arr != NULL, "null array");
-  }
-
-#ifdef ASSERT
-  virtual bool is_dup_pointer(const MemPointer* ptr1,
-    const MemPointer* ptr2) const {
-    MemPointerRecord* p1 = (MemPointerRecord*)ptr1;
-    MemPointerRecord* p2 = (MemPointerRecord*)ptr2;
-
-    if (p1->addr() != p2->addr()) return false;
-    if ((p1->flags() & MemPointerRecord::tag_masks) !=
-        (p2->flags() & MemPointerRecord::tag_masks)) {
-      return false;
-    }
-    // we do see multiple commit/uncommit on the same memory, it is ok
-    return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
-           (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
-  }
-
-  virtual bool insert(MemPointer* ptr) {
-    if (_pos > 0) {
-      MemPointer* p1 = (MemPointer*)ptr;
-      MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
-      assert(!is_dup_pointer(p1, p2),
-        err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
-    }
-     if (_pos < _array->length() -1) {
-      MemPointer* p1 = (MemPointer*)ptr;
-      MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
-      assert(!is_dup_pointer(p1, p2),
-        err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
-     }
-    return _array->insert_at(ptr, _pos);
-  }
-
-  virtual bool insert_after(MemPointer* ptr) {
-    if (_pos > 0) {
-      MemPointer* p1 = (MemPointer*)ptr;
-      MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
-      assert(!is_dup_pointer(p1, p2),
-        err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
-    }
-    if (_pos < _array->length() - 1) {
-      MemPointer* p1 = (MemPointer*)ptr;
-      MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
-
-      assert(!is_dup_pointer(p1, p2),
-        err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
-     }
-    if (_array->insert_at(ptr, _pos + 1)) {
-      _pos ++;
-      return true;
-    }
-    return false;
-  }
-#endif
-
-  virtual MemPointer* locate(address addr) {
-    MemPointer* cur = current();
-    while (cur != NULL && cur->addr() < addr) {
-      cur = next();
-    }
-    return cur;
-  }
-};
-
-class VMMemPointerIterator : public MemPointerIterator {
- public:
-  VMMemPointerIterator(MemPointerArray* arr):
-      MemPointerIterator(arr) {
-  }
-
-  // locate an existing reserved memory region that contains specified address,
-  // or the reserved region just above this address, where the incoming
-  // reserved region should be inserted.
-  virtual MemPointer* locate(address addr) {
-    reset();
-    VMMemRegion* reg = (VMMemRegion*)current();
-    while (reg != NULL) {
-      if (reg->is_reserved_region()) {
-        if (reg->contains_address(addr) || addr < reg->base()) {
-          return reg;
-      }
-    }
-      reg = (VMMemRegion*)next();
-    }
-      return NULL;
-    }
-
-  // following methods update virtual memory in the context
-  // of 'current' position, which is properly positioned by
-  // callers via locate method.
-  bool add_reserved_region(MemPointerRecord* rec);
-  bool add_committed_region(MemPointerRecord* rec);
-  bool remove_uncommitted_region(MemPointerRecord* rec);
-  bool remove_released_region(MemPointerRecord* rec);
-
-  // split a reserved region to create a new memory region with specified base and size
-  bool split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size);
- private:
-  bool insert_record(MemPointerRecord* rec);
-  bool insert_record_after(MemPointerRecord* rec);
-
-  bool insert_reserved_region(MemPointerRecord* rec);
-
-  // reset current position
-  inline void reset() { _pos = 0; }
-#ifdef ASSERT
-  // check integrity of records on current reserved memory region.
-  bool check_reserved_region() {
-    VMMemRegion* reserved_region = (VMMemRegion*)current();
-    assert(reserved_region != NULL && reserved_region->is_reserved_region(),
-          "Sanity check");
-    // all committed regions that follow current reserved region, should all
-    // belong to the reserved region.
-    VMMemRegion* next_region = (VMMemRegion*)next();
-    for (; next_region != NULL && next_region->is_committed_region();
-         next_region = (VMMemRegion*)next() ) {
-      if(!reserved_region->contains_region(next_region)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  virtual bool is_dup_pointer(const MemPointer* ptr1,
-    const MemPointer* ptr2) const {
-    VMMemRegion* p1 = (VMMemRegion*)ptr1;
-    VMMemRegion* p2 = (VMMemRegion*)ptr2;
-
-    if (p1->addr() != p2->addr()) return false;
-    if ((p1->flags() & MemPointerRecord::tag_masks) !=
-        (p2->flags() & MemPointerRecord::tag_masks)) {
-      return false;
-    }
-    // we do see multiple commit/uncommit on the same memory, it is ok
-    return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
-           (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
-  }
-#endif
-};
-
-class MallocRecordIterator : public MemPointerArrayIterator {
- private:
-  MemPointerArrayIteratorImpl  _itr;
-
-
-
- public:
-  MallocRecordIterator(MemPointerArray* arr) : _itr(arr) {
-  }
-
-  virtual MemPointer* current() const {
-#ifdef ASSERT
-    MemPointer* cur_rec = _itr.current();
-    if (cur_rec != NULL) {
-      MemPointer* prev_rec = _itr.peek_prev();
-      MemPointer* next_rec = _itr.peek_next();
-      assert(prev_rec == NULL || prev_rec->addr() < cur_rec->addr(), "Sorting order");
-      assert(next_rec == NULL || next_rec->addr() > cur_rec->addr(), "Sorting order");
-    }
-#endif
-    return _itr.current();
-  }
-  virtual MemPointer* next() {
-    MemPointerRecord* next_rec = (MemPointerRecord*)_itr.next();
-    // arena memory record is a special case, which we have to compare
-    // sequence number against its associated arena record.
-    if (next_rec != NULL && next_rec->is_arena_memory_record()) {
-      MemPointerRecord* prev_rec = (MemPointerRecord*)_itr.peek_prev();
-      // if there is an associated arena record, it has to be previous
-      // record because of sorting order (by address) - NMT generates a pseudo address
-      // for arena's size record by offsetting arena's address, that guarantees
-      // the order of arena record and it's size record.
-      if (prev_rec != NULL && prev_rec->is_arena_record() &&
-        next_rec->is_memory_record_of_arena(prev_rec)) {
-        if (prev_rec->seq() > next_rec->seq()) {
-          // Skip this arena memory record
-          // Two scenarios:
-          //   - if the arena record is an allocation record, this early
-          //     size record must be leftover by previous arena,
-          //     and the last size record should have size = 0.
-          //   - if the arena record is a deallocation record, this
-          //     size record should be its cleanup record, which should
-          //     also have size = 0. In other world, arena alway reset
-          //     its size before gone (see Arena's destructor)
-          assert(next_rec->size() == 0, "size not reset");
-          return _itr.next();
-        } else {
-          assert(prev_rec->is_allocation_record(),
-            "Arena size record ahead of allocation record");
-        }
-      }
-    }
-    return next_rec;
-  }
-
-  MemPointer* peek_next() const      { ShouldNotReachHere(); return NULL; }
-  MemPointer* peek_prev() const      { ShouldNotReachHere(); return NULL; }
-  void remove()                      { ShouldNotReachHere(); }
-  bool insert(MemPointer* ptr)       { ShouldNotReachHere(); return false; }
-  bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; }
-};
-
-// collapse duplicated records. Eliminating duplicated records here, is much
-// cheaper than during promotion phase. However, it does have limitation - it
-// can only eliminate duplicated records within the generation, there are
-// still chances seeing duplicated records during promotion.
-// We want to use the record with higher sequence number, because it has
-// more accurate callsite pc.
-class VMRecordIterator : public MemPointerArrayIterator {
- private:
-  MemPointerArrayIteratorImpl  _itr;
-
- public:
-  VMRecordIterator(MemPointerArray* arr) : _itr(arr) {
-    MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
-    MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next();
-    while (next != NULL) {
-      assert(cur != NULL, "Sanity check");
-      assert(((SeqMemPointerRecord*)next)->seq() > ((SeqMemPointerRecord*)cur)->seq(),
-        "pre-sort order");
-
-      if (is_duplicated_record(cur, next)) {
-        _itr.next();
-        next = (MemPointerRecord*)_itr.peek_next();
-      } else {
-        break;
-      }
-    }
-  }
-
-  virtual MemPointer* current() const {
-    return _itr.current();
-  }
-
-  // get next record, but skip the duplicated records
-  virtual MemPointer* next() {
-    MemPointerRecord* cur = (MemPointerRecord*)_itr.next();
-    MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next();
-    while (next != NULL) {
-      assert(cur != NULL, "Sanity check");
-      assert(((SeqMemPointerRecord*)next)->seq() > ((SeqMemPointerRecord*)cur)->seq(),
-        "pre-sort order");
-
-      if (is_duplicated_record(cur, next)) {
-        _itr.next();
-        cur = next;
-        next = (MemPointerRecord*)_itr.peek_next();
-      } else {
-        break;
-      }
-    }
-    return cur;
-  }
-
-  MemPointer* peek_next() const      { ShouldNotReachHere(); return NULL; }
-  MemPointer* peek_prev() const      { ShouldNotReachHere(); return NULL; }
-  void remove()                      { ShouldNotReachHere(); }
-  bool insert(MemPointer* ptr)       { ShouldNotReachHere(); return false; }
-  bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; }
-
- private:
-  bool is_duplicated_record(MemPointerRecord* p1, MemPointerRecord* p2) const {
-    bool ret = (p1->addr() == p2->addr() && p1->size() == p2->size() && p1->flags() == p2->flags());
-    assert(!(ret && FLAGS_TO_MEMORY_TYPE(p1->flags()) == mtThreadStack), "dup on stack record");
-    return ret;
-  }
-};
-
-class StagingArea VALUE_OBJ_CLASS_SPEC {
- private:
-  MemPointerArray*   _malloc_data;
-  MemPointerArray*   _vm_data;
-
- public:
-  StagingArea() : _malloc_data(NULL), _vm_data(NULL) {
-    init();
-  }
-
-  ~StagingArea() {
-    if (_malloc_data != NULL) delete _malloc_data;
-    if (_vm_data != NULL) delete _vm_data;
-  }
-
-  MallocRecordIterator malloc_record_walker() {
-    return MallocRecordIterator(malloc_data());
-  }
-
-  VMRecordIterator virtual_memory_record_walker();
-
-  bool init();
-  void clear() {
-    assert(_malloc_data != NULL && _vm_data != NULL, "Just check");
-    _malloc_data->shrink();
-    _malloc_data->clear();
-    _vm_data->clear();
-  }
-
-  inline MemPointerArray* malloc_data() { return _malloc_data; }
-  inline MemPointerArray* vm_data()     { return _vm_data; }
-};
-
-class MemBaseline;
-class MemSnapshot : public CHeapObj<mtNMT> {
- private:
-  // the following two arrays contain records of all known lived memory blocks
-  // live malloc-ed memory pointers
-  MemPointerArray*      _alloc_ptrs;
-  // live virtual memory pointers
-  MemPointerArray*      _vm_ptrs;
-
-  StagingArea           _staging_area;
-
-  // the lock to protect this snapshot
-  Monitor*              _lock;
-
-  // the number of instance classes
-  int                   _number_of_classes;
-
-  NOT_PRODUCT(size_t    _untracked_count;)
-  friend class MemBaseline;
-
- public:
-  MemSnapshot();
-  virtual ~MemSnapshot();
-
-  // if we are running out of native memory
-  bool out_of_memory() {
-    return (_alloc_ptrs == NULL ||
-      _staging_area.malloc_data() == NULL ||
-      _staging_area.vm_data() == NULL ||
-      _vm_ptrs == NULL || _lock == NULL ||
-      _alloc_ptrs->out_of_memory() ||
-      _vm_ptrs->out_of_memory());
-  }
-
-  // merge a per-thread memory recorder into staging area
-  bool merge(MemRecorder* rec);
-  // promote staged data to snapshot
-  bool promote(int number_of_classes);
-
-  int  number_of_classes() const { return _number_of_classes; }
-
-  void wait(long timeout) {
-    assert(_lock != NULL, "Just check");
-    MonitorLockerEx locker(_lock);
-    locker.wait(true, timeout);
-  }
-
-  NOT_PRODUCT(void print_snapshot_stats(outputStream* st);)
-  NOT_PRODUCT(void check_staging_data();)
-  NOT_PRODUCT(void check_malloc_pointers();)
-  NOT_PRODUCT(bool has_allocation_record(address addr);)
-  // dump all virtual memory pointers in snapshot
-  DEBUG_ONLY( void dump_all_vm_pointers();)
-
- private:
-   // copy sequenced pointer from src to dest
-   void copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src);
-   // assign a sequenced pointer to non-sequenced pointer
-   void assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src);
-
-   bool promote_malloc_records(MemPointerArrayIterator* itr);
-   bool promote_virtual_memory_records(MemPointerArrayIterator* itr);
-};
-
-#endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
diff --git a/hotspot/src/share/vm/services/memTrackWorker.cpp b/hotspot/src/share/vm/services/memTrackWorker.cpp
deleted file mode 100644
index 7bf18eb..0000000
--- a/hotspot/src/share/vm/services/memTrackWorker.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright (c) 2013, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "runtime/threadCritical.hpp"
-#include "services/memTracker.hpp"
-#include "services/memTrackWorker.hpp"
-#include "utilities/decoder.hpp"
-#include "utilities/vmError.hpp"
-
-
-void GenerationData::reset() {
-  _number_of_classes = 0;
-  while (_recorder_list != NULL) {
-    MemRecorder* tmp = _recorder_list;
-    _recorder_list = _recorder_list->next();
-    MemTracker::release_thread_recorder(tmp);
-  }
-}
-
-MemTrackWorker::MemTrackWorker(MemSnapshot* snapshot): _snapshot(snapshot) {
-  // create thread uses cgc thread type for now. We should revisit
-  // the option, or create new thread type.
-  _has_error = !os::create_thread(this, os::cgc_thread);
-  set_name("MemTrackWorker");
-
-  // initial generation circuit buffer
-  if (!has_error()) {
-    _head = _tail = 0;
-    for(int index = 0; index < MAX_GENERATIONS; index ++) {
-      ::new ((void*)&_gen[index]) GenerationData();
-    }
-  }
-  NOT_PRODUCT(_sync_point_count = 0;)
-  NOT_PRODUCT(_merge_count = 0;)
-  NOT_PRODUCT(_last_gen_in_use = 0;)
-}
-
-MemTrackWorker::~MemTrackWorker() {
-  for (int index = 0; index < MAX_GENERATIONS; index ++) {
-    _gen[index].reset();
-  }
-}
-
-void* MemTrackWorker::operator new(size_t size) throw() {
-  assert(false, "use nothrow version");
-  return NULL;
-}
-
-void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() {
-  return allocate(size, false, mtNMT);
-}
-
-void MemTrackWorker::start() {
-  os::start_thread(this);
-}
-
-/*
- * Native memory tracking worker thread loop:
- *   1. merge one generation of memory recorders to staging area
- *   2. promote staging data to memory snapshot
- *
- * This thread can run through safepoint.
- */
-
-void MemTrackWorker::run() {
-  assert(MemTracker::is_on(), "native memory tracking is off");
-  this->initialize_thread_local_storage();
-  this->record_stack_base_and_size();
-  assert(_snapshot != NULL, "Worker should not be started");
-  MemRecorder* rec;
-  unsigned long processing_generation = 0;
-  bool          worker_idle = false;
-
-  while (!MemTracker::shutdown_in_progress()) {
-    NOT_PRODUCT(_last_gen_in_use = generations_in_use();)
-    {
-      // take a recorder from earliest generation in buffer
-      ThreadCritical tc;
-      rec = _gen[_head].next_recorder();
-    }
-    if (rec != NULL) {
-      if (rec->get_generation() != processing_generation || worker_idle) {
-        processing_generation = rec->get_generation();
-        worker_idle = false;
-        MemTracker::set_current_processing_generation(processing_generation);
-      }
-
-      // merge the recorder into staging area
-      if (!_snapshot->merge(rec)) {
-        MemTracker::shutdown(MemTracker::NMT_out_of_memory);
-      } else {
-        NOT_PRODUCT(_merge_count ++;)
-      }
-      MemTracker::release_thread_recorder(rec);
-    } else {
-      // no more recorder to merge, promote staging area
-      // to snapshot
-      if (_head != _tail) {
-        long number_of_classes;
-        {
-          ThreadCritical tc;
-          if (_gen[_head].has_more_recorder() || _head == _tail) {
-            continue;
-          }
-          number_of_classes = _gen[_head].number_of_classes();
-          _gen[_head].reset();
-
-          // done with this generation, increment _head pointer
-          _head = (_head + 1) % MAX_GENERATIONS;
-        }
-        // promote this generation data to snapshot
-        if (!_snapshot->promote(number_of_classes)) {
-          // failed to promote, means out of memory
-          MemTracker::shutdown(MemTracker::NMT_out_of_memory);
-        }
-      } else {
-        // worker thread is idle
-        worker_idle = true;
-        MemTracker::report_worker_idle();
-        _snapshot->wait(1000);
-        ThreadCritical tc;
-        // check if more data arrived
-        if (!_gen[_head].has_more_recorder()) {
-          _gen[_head].add_recorders(MemTracker::get_pending_recorders());
-        }
-      }
-    }
-  }
-  assert(MemTracker::shutdown_in_progress(), "just check");
-
-  // transits to final shutdown
-  MemTracker::final_shutdown();
-}
-
-// at synchronization point, where 'safepoint visible' Java threads are blocked
-// at a safepoint, and the rest of threads are blocked on ThreadCritical lock.
-// The caller MemTracker::sync() already takes ThreadCritical before calling this
-// method.
-//
-// Following tasks are performed:
-//   1. add all recorders in pending queue to current generation
-//   2. increase generation
-
-void MemTrackWorker::at_sync_point(MemRecorder* rec, int number_of_classes) {
-  NOT_PRODUCT(_sync_point_count ++;)
-  assert(count_recorder(rec) <= MemRecorder::_instance_count,
-    "pending queue has infinite loop");
-
-  bool out_of_generation_buffer = false;
-  // check shutdown state inside ThreadCritical
-  if (MemTracker::shutdown_in_progress()) return;
-
-  _gen[_tail].set_number_of_classes(number_of_classes);
-  // append the recorders to the end of the generation
-  _gen[_tail].add_recorders(rec);
-  assert(count_recorder(_gen[_tail].peek()) <= MemRecorder::_instance_count,
-    "after add to current generation has infinite loop");
-  // we have collected all recorders for this generation. If there is data,
-  // we need to increment _tail to start a new generation.
-  if (_gen[_tail].has_more_recorder()  || _head == _tail) {
-    _tail = (_tail + 1) % MAX_GENERATIONS;
-    out_of_generation_buffer = (_tail == _head);
-  }
-
-  if (out_of_generation_buffer) {
-    MemTracker::shutdown(MemTracker::NMT_out_of_generation);
-  }
-}
-
-#ifndef PRODUCT
-int MemTrackWorker::count_recorder(const MemRecorder* head) {
-  int count = 0;
-  while(head != NULL) {
-    count ++;
-    head = head->next();
-  }
-  return count;
-}
-
-int MemTrackWorker::count_pending_recorders() const {
-  int count = 0;
-  for (int index = 0; index < MAX_GENERATIONS; index ++) {
-    MemRecorder* head = _gen[index].peek();
-    if (head != NULL) {
-      count += count_recorder(head);
-    }
-  }
-  return count;
-}
-#endif
diff --git a/hotspot/src/share/vm/services/memTrackWorker.hpp b/hotspot/src/share/vm/services/memTrackWorker.hpp
deleted file mode 100644
index ee45244..0000000
--- a/hotspot/src/share/vm/services/memTrackWorker.hpp
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * Copyright (c) 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.
- *
- */
-
-#ifndef SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP
-#define SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP
-
-#include "memory/allocation.hpp"
-#include "runtime/thread.hpp"
-#include "services/memRecorder.hpp"
-
-// Maximum MAX_GENERATIONS generation data can be tracked.
-#define MAX_GENERATIONS  512
-
-class GenerationData VALUE_OBJ_CLASS_SPEC {
- private:
-  int           _number_of_classes;
-  MemRecorder*  _recorder_list;
-
- public:
-  GenerationData(): _number_of_classes(0), _recorder_list(NULL) { }
-
-  inline int  number_of_classes() const { return _number_of_classes; }
-  inline void set_number_of_classes(long num) { _number_of_classes = num; }
-
-  inline MemRecorder* next_recorder() {
-    if (_recorder_list == NULL) {
-      return NULL;
-    } else {
-      MemRecorder* tmp = _recorder_list;
-      _recorder_list = _recorder_list->next();
-      return tmp;
-    }
-  }
-
-  inline bool has_more_recorder() const {
-    return (_recorder_list != NULL);
-  }
-
-  // add recorders to this generation
-  void add_recorders(MemRecorder* head) {
-    if (head != NULL) {
-      if (_recorder_list == NULL) {
-        _recorder_list = head;
-      } else {
-        MemRecorder* tmp = _recorder_list;
-        for (; tmp->next() != NULL; tmp = tmp->next());
-        tmp->set_next(head);
-      }
-    }
-  }
-
-  void reset();
-
-  NOT_PRODUCT(MemRecorder* peek() const { return _recorder_list; })
-};
-
-class MemTrackWorker : public NamedThread {
- private:
-  // circular buffer. This buffer contains generation data to be merged into global
-  // snaphsot.
-  // Each slot holds a generation
-  GenerationData  _gen[MAX_GENERATIONS];
-  int             _head, _tail; // head and tail pointers to above circular buffer
-
-  bool            _has_error;
-
-  MemSnapshot*    _snapshot;
-
- public:
-  MemTrackWorker(MemSnapshot* snapshot);
-  ~MemTrackWorker();
-  _NOINLINE_ void* operator new(size_t size) throw();
-  _NOINLINE_ void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw();
-
-  void start();
-  void run();
-
-  inline bool has_error() const { return _has_error; }
-
-  // task at synchronization point
-  void at_sync_point(MemRecorder* pending_recorders, int number_of_classes);
-
-  // for debugging purpose, they are not thread safe.
-  NOT_PRODUCT(static int count_recorder(const MemRecorder* head);)
-  NOT_PRODUCT(int count_pending_recorders() const;)
-
-  NOT_PRODUCT(int _sync_point_count;)
-  NOT_PRODUCT(int _merge_count;)
-  NOT_PRODUCT(int _last_gen_in_use;)
-
-  // how many generations are queued
-  inline int generations_in_use() const {
-    return (_tail >= _head ? (_tail - _head + 1) : (MAX_GENERATIONS - (_head - _tail) + 1));
-  }
-};
-
-#endif // SHARE_VM_SERVICES_MEM_TRACK_WORKER_HPP
diff --git a/hotspot/src/share/vm/services/memTracker.cpp b/hotspot/src/share/vm/services/memTracker.cpp
index a2961ee..84cea12 100644
--- a/hotspot/src/share/vm/services/memTracker.cpp
+++ b/hotspot/src/share/vm/services/memTracker.cpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,861 +23,315 @@
  */
 #include "precompiled.hpp"
 
-#include "oops/instanceKlass.hpp"
-#include "runtime/atomic.hpp"
-#include "runtime/interfaceSupport.hpp"
-#include "runtime/mutexLocker.hpp"
-#include "runtime/safepoint.hpp"
-#include "runtime/threadCritical.hpp"
-#include "runtime/vm_operations.hpp"
-#include "services/memPtr.hpp"
+#include "runtime/mutex.hpp"
+#include "services/memBaseline.hpp"
 #include "services/memReporter.hpp"
+#include "services/mallocTracker.inline.hpp"
 #include "services/memTracker.hpp"
-#include "utilities/decoder.hpp"
 #include "utilities/defaultStream.hpp"
-#include "utilities/globalDefinitions.hpp"
 
-bool NMT_track_callsite = false;
+#ifdef SOLARIS
+  volatile bool NMT_stack_walkable = false;
+#else
+  volatile bool NMT_stack_walkable = true;
+#endif
 
-// walk all 'known' threads at NMT sync point, and collect their recorders
-void SyncThreadRecorderClosure::do_thread(Thread* thread) {
-  assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
-  if (thread->is_Java_thread()) {
-    JavaThread* javaThread = (JavaThread*)thread;
-    MemRecorder* recorder = javaThread->get_recorder();
-    if (recorder != NULL) {
-      MemTracker::enqueue_pending_recorder(recorder);
-      javaThread->set_recorder(NULL);
+volatile NMT_TrackingLevel MemTracker::_tracking_level = NMT_unknown;
+NMT_TrackingLevel MemTracker::_cmdline_tracking_level = NMT_unknown;
+
+MemBaseline MemTracker::_baseline;
+Mutex*      MemTracker::_query_lock = NULL;
+bool MemTracker::_is_nmt_env_valid = true;
+
+
+NMT_TrackingLevel MemTracker::init_tracking_level() {
+  NMT_TrackingLevel level = NMT_off;
+  char buf[64];
+  char nmt_option[64];
+  jio_snprintf(buf, sizeof(buf), "NMT_LEVEL_%d", os::current_process_id());
+  if (os::getenv(buf, nmt_option, sizeof(nmt_option))) {
+    if (strcmp(nmt_option, "summary") == 0) {
+      level = NMT_summary;
+    } else if (strcmp(nmt_option, "detail") == 0) {
+#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
+      level = NMT_detail;
+#else
+      level = NMT_summary;
+#endif // PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
+    } else if (strcmp(nmt_option, "off") != 0) {
+      // The option value is invalid
+      _is_nmt_env_valid = false;
     }
+
+    // Remove the environment variable to avoid leaking to child processes
+    os::unsetenv(buf);
   }
-  _thread_count ++;
+
+  // Construct NativeCallStack::EMPTY_STACK. It may get constructed twice,
+  // but it is benign, the results are the same.
+  ::new ((void*)&NativeCallStack::EMPTY_STACK) NativeCallStack(0, false);
+
+  if (!MallocTracker::initialize(level) ||
+      !VirtualMemoryTracker::initialize(level)) {
+    level = NMT_off;
+  }
+  return level;
 }
 
+void MemTracker::init() {
+  NMT_TrackingLevel level = tracking_level();
+  if (level >= NMT_summary) {
+    if (!VirtualMemoryTracker::late_initialize(level)) {
+      shutdown();
+      return;
+    }
+    _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
+    // Already OOM. It is unlikely, but still have to handle it.
+    if (_query_lock == NULL) {
+      shutdown();
+    }
+  }
+}
 
-MemRecorder* volatile           MemTracker::_global_recorder = NULL;
-MemSnapshot*                    MemTracker::_snapshot = NULL;
-MemBaseline                     MemTracker::_baseline;
-Mutex*                          MemTracker::_query_lock = NULL;
-MemRecorder* volatile           MemTracker::_merge_pending_queue = NULL;
-MemRecorder* volatile           MemTracker::_pooled_recorders = NULL;
-MemTrackWorker*                 MemTracker::_worker_thread = NULL;
-int                             MemTracker::_sync_point_skip_count = 0;
-MemTracker::NMTLevel            MemTracker::_tracking_level = MemTracker::NMT_off;
-volatile MemTracker::NMTStates  MemTracker::_state = NMT_uninited;
-MemTracker::ShutdownReason      MemTracker::_reason = NMT_shutdown_none;
-int                             MemTracker::_thread_count = 255;
-volatile jint                   MemTracker::_pooled_recorder_count = 0;
-volatile unsigned long          MemTracker::_processing_generation = 0;
-volatile bool                   MemTracker::_worker_thread_idle = false;
-volatile jint                   MemTracker::_pending_op_count = 0;
-volatile bool                   MemTracker::_slowdown_calling_thread = false;
-debug_only(intx                 MemTracker::_main_thread_tid = 0;)
-NOT_PRODUCT(volatile jint       MemTracker::_pending_recorder_count = 0;)
-
-void MemTracker::init_tracking_options(const char* option_line) {
-  _tracking_level = NMT_off;
-  if (strcmp(option_line, "=summary") == 0) {
-    _tracking_level = NMT_summary;
-  } else if (strcmp(option_line, "=detail") == 0) {
-    // detail relies on a stack-walking ability that may not
-    // be available depending on platform and/or compiler flags
-#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
-      _tracking_level = NMT_detail;
-#else
+bool MemTracker::check_launcher_nmt_support(const char* value) {
+  if (strcmp(value, "=detail") == 0) {
+#if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
       jio_fprintf(defaultStream::error_stream(),
         "NMT detail is not supported on this platform.  Using NMT summary instead.\n");
-      _tracking_level = NMT_summary;
+    if (MemTracker::tracking_level() != NMT_summary) {
+    return false;
+  }
+#else
+    if (MemTracker::tracking_level() != NMT_detail) {
+      return false;
+    }
 #endif
-  } else if (strcmp(option_line, "=off") != 0) {
-    vm_exit_during_initialization("Syntax error, expecting -XX:NativeMemoryTracking=[off|summary|detail]", NULL);
-  }
-}
-
-// first phase of bootstrapping, when VM is still in single-threaded mode.
-void MemTracker::bootstrap_single_thread() {
-  if (_tracking_level > NMT_off) {
-    assert(_state == NMT_uninited, "wrong state");
-
-    // NMT is not supported with UseMallocOnly is on. NMT can NOT
-    // handle the amount of malloc data without significantly impacting
-    // runtime performance when this flag is on.
-    if (UseMallocOnly) {
-      shutdown(NMT_use_malloc_only);
-      return;
+  } else if (strcmp(value, "=summary") == 0) {
+    if (MemTracker::tracking_level() != NMT_summary) {
+      return false;
     }
-
-    _query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
-    if (_query_lock == NULL) {
-      shutdown(NMT_out_of_memory);
-      return;
+  } else if (strcmp(value, "=off") == 0) {
+    if (MemTracker::tracking_level() != NMT_off) {
+      return false;
     }
-
-    debug_only(_main_thread_tid = os::current_thread_id();)
-    _state = NMT_bootstrapping_single_thread;
-    NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
-  }
-}
-
-// second phase of bootstrapping, when VM is about to or already entered multi-theaded mode.
-void MemTracker::bootstrap_multi_thread() {
-  if (_tracking_level > NMT_off && _state == NMT_bootstrapping_single_thread) {
-  // create nmt lock for multi-thread execution
-    assert(_main_thread_tid == os::current_thread_id(), "wrong thread");
-    _state = NMT_bootstrapping_multi_thread;
-    NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
-  }
-}
-
-// fully start nmt
-void MemTracker::start() {
-  // Native memory tracking is off from command line option
-  if (_tracking_level == NMT_off || shutdown_in_progress()) return;
-
-  assert(_main_thread_tid == os::current_thread_id(), "wrong thread");
-  assert(_state == NMT_bootstrapping_multi_thread, "wrong state");
-
-  _snapshot = new (std::nothrow)MemSnapshot();
-  if (_snapshot != NULL) {
-    if (!_snapshot->out_of_memory() && start_worker(_snapshot)) {
-      _state = NMT_started;
-      NMT_track_callsite = (_tracking_level == NMT_detail && can_walk_stack());
-      return;
-    }
-
-    delete _snapshot;
-    _snapshot = NULL;
-  }
-
-  // fail to start native memory tracking, shut it down
-  shutdown(NMT_initialization);
-}
-
-/**
- * Shutting down native memory tracking.
- * We can not shutdown native memory tracking immediately, so we just
- * setup shutdown pending flag, every native memory tracking component
- * should orderly shut itself down.
- *
- * The shutdown sequences:
- *  1. MemTracker::shutdown() sets MemTracker to shutdown pending state
- *  2. Worker thread calls MemTracker::final_shutdown(), which transites
- *     MemTracker to final shutdown state.
- *  3. At sync point, MemTracker does final cleanup, before sets memory
- *     tracking level to off to complete shutdown.
- */
-void MemTracker::shutdown(ShutdownReason reason) {
-  if (_tracking_level == NMT_off) return;
-
-  if (_state <= NMT_bootstrapping_single_thread) {
-    // we still in single thread mode, there is not contention
-    _state = NMT_shutdown_pending;
-    _reason = reason;
   } else {
-    // we want to know who initialized shutdown
-    if ((jint)NMT_started == Atomic::cmpxchg((jint)NMT_shutdown_pending,
-                                       (jint*)&_state, (jint)NMT_started)) {
-        _reason = reason;
-    }
-  }
-}
-
-// final phase of shutdown
-void MemTracker::final_shutdown() {
-  // delete all pending recorders and pooled recorders
-  delete_all_pending_recorders();
-  delete_all_pooled_recorders();
-
-  {
-    // shared baseline and snapshot are the only objects needed to
-    // create query results
-    MutexLockerEx locker(_query_lock, true);
-    // cleanup baseline data and snapshot
-    _baseline.clear();
-    delete _snapshot;
-    _snapshot = NULL;
+    _is_nmt_env_valid = false;
   }
 
-  // shutdown shared decoder instance, since it is only
-  // used by native memory tracking so far.
-  Decoder::shutdown();
-
-  MemTrackWorker* worker = NULL;
-  {
-    ThreadCritical tc;
-    // can not delete worker inside the thread critical
-    if (_worker_thread != NULL && Thread::current() == _worker_thread) {
-      worker = _worker_thread;
-      _worker_thread = NULL;
-    }
-  }
-  if (worker != NULL) {
-    delete worker;
-  }
-  _state = NMT_final_shutdown;
-}
-
-// delete all pooled recorders
-void MemTracker::delete_all_pooled_recorders() {
-  // free all pooled recorders
-  MemRecorder* volatile cur_head = _pooled_recorders;
-  if (cur_head != NULL) {
-    MemRecorder* null_ptr = NULL;
-    while (cur_head != NULL && (void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr,
-      (void*)&_pooled_recorders, (void*)cur_head)) {
-      cur_head = _pooled_recorders;
-    }
-    if (cur_head != NULL) {
-      delete cur_head;
-      _pooled_recorder_count = 0;
-    }
-  }
-}
-
-// delete all recorders in pending queue
-void MemTracker::delete_all_pending_recorders() {
-  // free all pending recorders
-  MemRecorder* pending_head = get_pending_recorders();
-  if (pending_head != NULL) {
-    delete pending_head;
-  }
-}
-
-/*
- * retrieve per-thread recorder of specified thread.
- * if thread == NULL, it means global recorder
- */
-MemRecorder* MemTracker::get_thread_recorder(JavaThread* thread) {
-  if (shutdown_in_progress()) return NULL;
-
-  MemRecorder* rc;
-  if (thread == NULL) {
-    rc = _global_recorder;
-  } else {
-    rc = thread->get_recorder();
-  }
-
-  if (rc != NULL && rc->is_full()) {
-    enqueue_pending_recorder(rc);
-    rc = NULL;
-  }
-
-  if (rc == NULL) {
-    rc = get_new_or_pooled_instance();
-    if (thread == NULL) {
-      _global_recorder = rc;
-    } else {
-      thread->set_recorder(rc);
-    }
-  }
-  return rc;
-}
-
-/*
- * get a per-thread recorder from pool, or create a new one if
- * there is not one available.
- */
-MemRecorder* MemTracker::get_new_or_pooled_instance() {
-   MemRecorder* cur_head = const_cast<MemRecorder*> (_pooled_recorders);
-   if (cur_head == NULL) {
-     MemRecorder* rec = new (std::nothrow)MemRecorder();
-     if (rec == NULL || rec->out_of_memory()) {
-       shutdown(NMT_out_of_memory);
-       if (rec != NULL) {
-         delete rec;
-         rec = NULL;
-       }
-     }
-     return rec;
-   } else {
-     MemRecorder* next_head = cur_head->next();
-     if ((void*)cur_head != Atomic::cmpxchg_ptr((void*)next_head, (void*)&_pooled_recorders,
-       (void*)cur_head)) {
-       return get_new_or_pooled_instance();
-     }
-     cur_head->set_next(NULL);
-     Atomic::dec(&_pooled_recorder_count);
-     cur_head->set_generation();
-     return cur_head;
-  }
-}
-
-/*
- * retrieve all recorders in pending queue, and empty the queue
- */
-MemRecorder* MemTracker::get_pending_recorders() {
-  MemRecorder* cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
-  MemRecorder* null_ptr = NULL;
-  while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)null_ptr, (void*)&_merge_pending_queue,
-    (void*)cur_head)) {
-    cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
-  }
-  NOT_PRODUCT(Atomic::store(0, &_pending_recorder_count));
-  return cur_head;
-}
-
-/*
- * release a recorder to recorder pool.
- */
-void MemTracker::release_thread_recorder(MemRecorder* rec) {
-  assert(rec != NULL, "null recorder");
-  // we don't want to pool too many recorders
-  rec->set_next(NULL);
-  if (shutdown_in_progress() || _pooled_recorder_count > _thread_count * 2) {
-    delete rec;
-    return;
-  }
-
-  rec->clear();
-  MemRecorder* cur_head = const_cast<MemRecorder*>(_pooled_recorders);
-  rec->set_next(cur_head);
-  while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_pooled_recorders,
-    (void*)cur_head)) {
-    cur_head = const_cast<MemRecorder*>(_pooled_recorders);
-    rec->set_next(cur_head);
-  }
-  Atomic::inc(&_pooled_recorder_count);
-}
-
-// write a record to proper recorder. No lock can be taken from this method
-// down.
-void MemTracker::write_tracking_record(address addr, MEMFLAGS flags,
-    size_t size, jint seq, address pc, JavaThread* thread) {
-
-    MemRecorder* rc = get_thread_recorder(thread);
-    if (rc != NULL) {
-      rc->record(addr, flags, size, seq, pc);
-    }
-}
-
-/**
- * enqueue a recorder to pending queue
- */
-void MemTracker::enqueue_pending_recorder(MemRecorder* rec) {
-  assert(rec != NULL, "null recorder");
-
-  // we are shutting down, so just delete it
-  if (shutdown_in_progress()) {
-    rec->set_next(NULL);
-    delete rec;
-    return;
-  }
-
-  MemRecorder* cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
-  rec->set_next(cur_head);
-  while ((void*)cur_head != Atomic::cmpxchg_ptr((void*)rec, (void*)&_merge_pending_queue,
-    (void*)cur_head)) {
-    cur_head = const_cast<MemRecorder*>(_merge_pending_queue);
-    rec->set_next(cur_head);
-  }
-  NOT_PRODUCT(Atomic::inc(&_pending_recorder_count);)
-}
-
-/*
- * The method is called at global safepoint
- * during it synchronization process.
- *   1. enqueue all JavaThreads' per-thread recorders
- *   2. enqueue global recorder
- *   3. retrieve all pending recorders
- *   4. reset global sequence number generator
- *   5. call worker's sync
- */
-#define MAX_SAFEPOINTS_TO_SKIP     128
-#define SAFE_SEQUENCE_THRESHOLD    30
-#define HIGH_GENERATION_THRESHOLD  60
-#define MAX_RECORDER_THREAD_RATIO  30
-#define MAX_RECORDER_PER_THREAD    100
-
-void MemTracker::sync() {
-  assert(_tracking_level > NMT_off, "NMT is not enabled");
-  assert(SafepointSynchronize::is_at_safepoint(), "Safepoint required");
-
-  // Some GC tests hit large number of safepoints in short period of time
-  // without meaningful activities. We should prevent going to
-  // sync point in these cases, which can potentially exhaust generation buffer.
-  // Here is the factots to determine if we should go into sync point:
-  // 1. not to overflow sequence number
-  // 2. if we are in danger to overflow generation buffer
-  // 3. how many safepoints we already skipped sync point
-  if (_state == NMT_started) {
-    // worker thread is not ready, no one can manage generation
-    // buffer, so skip this safepoint
-    if (_worker_thread == NULL) return;
-
-    if (_sync_point_skip_count < MAX_SAFEPOINTS_TO_SKIP) {
-      int per_seq_in_use = SequenceGenerator::peek() * 100 / max_jint;
-      int per_gen_in_use = _worker_thread->generations_in_use() * 100 / MAX_GENERATIONS;
-      if (per_seq_in_use < SAFE_SEQUENCE_THRESHOLD && per_gen_in_use >= HIGH_GENERATION_THRESHOLD) {
-        _sync_point_skip_count ++;
-        return;
-      }
-    }
-    {
-      // This method is running at safepoint, with ThreadCritical lock,
-      // it should guarantee that NMT is fully sync-ed.
-      ThreadCritical tc;
-
-      // We can NOT execute NMT sync-point if there are pending tracking ops.
-      if (_pending_op_count == 0) {
-        SequenceGenerator::reset();
-        _sync_point_skip_count = 0;
-
-        // walk all JavaThreads to collect recorders
-        SyncThreadRecorderClosure stc;
-        Threads::threads_do(&stc);
-
-        _thread_count = stc.get_thread_count();
-        MemRecorder* pending_recorders = get_pending_recorders();
-
-        if (_global_recorder != NULL) {
-          _global_recorder->set_next(pending_recorders);
-          pending_recorders = _global_recorder;
-          _global_recorder = NULL;
-        }
-
-        // see if NMT has too many outstanding recorder instances, it usually
-        // means that worker thread is lagging behind in processing them.
-        if (!AutoShutdownNMT) {
-          _slowdown_calling_thread = (MemRecorder::_instance_count > MAX_RECORDER_THREAD_RATIO * _thread_count);
-        } else {
-          // If auto shutdown is on, enforce MAX_RECORDER_PER_THREAD threshold to prevent OOM
-          if (MemRecorder::_instance_count >= _thread_count * MAX_RECORDER_PER_THREAD) {
-            shutdown(NMT_out_of_memory);
-          }
-        }
-
-        // check _worker_thread with lock to avoid racing condition
-        if (_worker_thread != NULL) {
-          _worker_thread->at_sync_point(pending_recorders, InstanceKlass::number_of_instance_classes());
-        }
-        assert(SequenceGenerator::peek() == 1, "Should not have memory activities during sync-point");
-      } else {
-        _sync_point_skip_count ++;
-      }
-    }
-  }
-
-  // now, it is the time to shut whole things off
-  if (_state == NMT_final_shutdown) {
-    // walk all JavaThreads to delete all recorders
-    SyncThreadRecorderClosure stc;
-    Threads::threads_do(&stc);
-    // delete global recorder
-    {
-      ThreadCritical tc;
-      if (_global_recorder != NULL) {
-        delete _global_recorder;
-        _global_recorder = NULL;
-      }
-    }
-    MemRecorder* pending_recorders = get_pending_recorders();
-    if (pending_recorders != NULL) {
-      delete pending_recorders;
-    }
-    // try at a later sync point to ensure MemRecorder instance drops to zero to
-    // completely shutdown NMT
-    if (MemRecorder::_instance_count == 0) {
-      _state = NMT_shutdown;
-      _tracking_level = NMT_off;
-    }
-  }
-}
-
-/*
- * Start worker thread.
- */
-bool MemTracker::start_worker(MemSnapshot* snapshot) {
-  assert(_worker_thread == NULL && _snapshot != NULL, "Just Check");
-  _worker_thread = new (std::nothrow) MemTrackWorker(snapshot);
-  if (_worker_thread == NULL) {
-    return false;
-  } else if (_worker_thread->has_error()) {
-    delete _worker_thread;
-    _worker_thread = NULL;
-    return false;
-  }
-  _worker_thread->start();
   return true;
 }
 
-/*
- * We need to collect a JavaThread's per-thread recorder
- * before it exits.
- */
-void MemTracker::thread_exiting(JavaThread* thread) {
-  if (is_on()) {
-    MemRecorder* rec = thread->get_recorder();
-    if (rec != NULL) {
-      enqueue_pending_recorder(rec);
-      thread->set_recorder(NULL);
+bool MemTracker::verify_nmt_option() {
+  return _is_nmt_env_valid;
+}
+
+void* MemTracker::malloc_base(void* memblock) {
+  return MallocTracker::get_base(memblock);
+}
+
+void Tracker::record(address addr, size_t size) {
+  if (MemTracker::tracking_level() < NMT_summary) return;
+  switch(_type) {
+    case uncommit:
+      VirtualMemoryTracker::remove_uncommitted_region(addr, size);
+      break;
+    case release:
+      VirtualMemoryTracker::remove_released_region(addr, size);
+        break;
+    default:
+      ShouldNotReachHere();
+  }
+}
+
+
+// Shutdown can only be issued via JCmd, and NMT JCmd is serialized
+// by lock
+void MemTracker::shutdown() {
+  // We can only shutdown NMT to minimal tracking level if it is
+  // ever on.
+  if (tracking_level () > NMT_minimal) {
+    transition_to(NMT_minimal);
+  }
+}
+
+bool MemTracker::transition_to(NMT_TrackingLevel level) {
+  NMT_TrackingLevel current_level = tracking_level();
+
+  if (current_level == level) {
+    return true;
+  } else if (current_level > level) {
+    // Downgrade tracking level, we want to lower the tracking
+    // level first
+    _tracking_level = level;
+    // Make _tracking_level visible immediately.
+    OrderAccess::fence();
+    VirtualMemoryTracker::transition(current_level, level);
+    MallocTracker::transition(current_level, level);
+
+    if (level == NMT_minimal) _baseline.reset();
+  } else {
+    VirtualMemoryTracker::transition(current_level, level);
+    MallocTracker::transition(current_level, level);
+
+    _tracking_level = level;
+    // Make _tracking_level visible immediately.
+    OrderAccess::fence();
+  }
+
+  return true;
+}
+
+void MemTracker::final_report(outputStream* output) {
+  assert(output != NULL, "No output stream");
+  if (tracking_level() >= NMT_summary) {
+    MallocMemorySnapshot* malloc_memory_snapshot =
+      MallocMemorySummary::as_snapshot();
+    malloc_memory_snapshot->make_adjustment();
+
+    VirtualMemorySnapshot* virtual_memory_snapshot =
+      VirtualMemorySummary::as_snapshot();
+
+    MemSummaryReporter rptr(malloc_memory_snapshot,
+      virtual_memory_snapshot, output);
+    rptr.report();
+    // shutdown NMT, the data no longer accurate
+    shutdown();
+  }
+}
+
+// This is a walker to gather malloc site hashtable statistics,
+// the result is used for tuning.
+class StatisticsWalker : public MallocSiteWalker {
+ private:
+  enum Threshold {
+    // aggregates statistics over this threshold into one
+    // line item.
+    report_threshold = 20
+  };
+
+ private:
+  // Number of allocation sites that have all memory freed
+  int   _empty_entries;
+  // Total number of allocation sites, include empty sites
+  int   _total_entries;
+  // Number of captured call stack distribution
+  int   _stack_depth_distribution[NMT_TrackingStackDepth];
+  // Hash distribution
+  int   _hash_distribution[report_threshold];
+  // Number of hash buckets that have entries over the threshold
+  int   _bucket_over_threshold;
+
+  // The hash bucket that walker is currently walking
+  int   _current_hash_bucket;
+  // The length of current hash bucket
+  int   _current_bucket_length;
+  // Number of hash buckets that are not empty
+  int   _used_buckets;
+  // Longest hash bucket length
+  int   _longest_bucket_length;
+
+ public:
+  StatisticsWalker() : _empty_entries(0), _total_entries(0) {
+    int index = 0;
+    for (index = 0; index < NMT_TrackingStackDepth; index ++) {
+      _stack_depth_distribution[index] = 0;
     }
+    for (index = 0; index < report_threshold; index ++) {
+      _hash_distribution[index] = 0;
+    }
+    _bucket_over_threshold = 0;
+    _longest_bucket_length = 0;
+    _current_hash_bucket = -1;
+    _current_bucket_length = 0;
+    _used_buckets = 0;
   }
-}
 
-// baseline current memory snapshot
-bool MemTracker::baseline() {
-  MutexLocker lock(_query_lock);
-  MemSnapshot* snapshot = get_snapshot();
-  if (snapshot != NULL) {
-    return _baseline.baseline(*snapshot, false);
-  }
-  return false;
-}
+  virtual bool at(const MallocSite* e) {
+    if (e->size() == 0) _empty_entries ++;
+    _total_entries ++;
 
-// print memory usage from current snapshot
-bool MemTracker::print_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
-  MemBaseline  baseline;
-  MutexLocker  lock(_query_lock);
-  MemSnapshot* snapshot = get_snapshot();
-  if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) {
-    BaselineReporter reporter(out, unit);
-    reporter.report_baseline(baseline, summary_only);
+    // stack depth distrubution
+    int frames = e->call_stack()->frames();
+    _stack_depth_distribution[frames - 1] ++;
+
+    // hash distribution
+    int hash_bucket = e->hash() % MallocSiteTable::hash_buckets();
+    if (_current_hash_bucket == -1) {
+      _current_hash_bucket = hash_bucket;
+      _current_bucket_length = 1;
+    } else if (_current_hash_bucket == hash_bucket) {
+      _current_bucket_length ++;
+    } else {
+      record_bucket_length(_current_bucket_length);
+      _current_hash_bucket = hash_bucket;
+      _current_bucket_length = 1;
+    }
     return true;
   }
-  return false;
-}
 
-// Whitebox API for blocking until the current generation of NMT data has been merged
-bool MemTracker::wbtest_wait_for_data_merge() {
-  // NMT can't be shutdown while we're holding _query_lock
-  MutexLocker lock(_query_lock);
-  assert(_worker_thread != NULL, "Invalid query");
-  // the generation at query time, so NMT will spin till this generation is processed
-  unsigned long generation_at_query_time = SequenceGenerator::current_generation();
-  unsigned long current_processing_generation = _processing_generation;
-  // if generation counter overflown
-  bool generation_overflown = (generation_at_query_time < current_processing_generation);
-  long generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation;
-  // spin
-  while (!shutdown_in_progress()) {
-    if (!generation_overflown) {
-      if (current_processing_generation > generation_at_query_time) {
-        return true;
+  // walk completed
+  void completed() {
+    record_bucket_length(_current_bucket_length);
+  }
+
+  void report_statistics(outputStream* out) {
+    int index;
+    out->print_cr("Malloc allocation site table:");
+    out->print_cr("\tTotal entries: %d", _total_entries);
+    out->print_cr("\tEmpty entries: %d (%2.2f%%)", _empty_entries, ((float)_empty_entries * 100) / _total_entries);
+    out->print_cr(" ");
+    out->print_cr("Hash distribution:");
+    if (_used_buckets < MallocSiteTable::hash_buckets()) {
+      out->print_cr("empty bucket: %d", (MallocSiteTable::hash_buckets() - _used_buckets));
+    }
+    for (index = 0; index < report_threshold; index ++) {
+      if (_hash_distribution[index] != 0) {
+        if (index == 0) {
+          out->print_cr("  %d    entry: %d", 1, _hash_distribution[0]);
+        } else if (index < 9) { // single digit
+          out->print_cr("  %d  entries: %d", (index + 1), _hash_distribution[index]);
+        } else {
+          out->print_cr(" %d entries: %d", (index + 1), _hash_distribution[index]);
+        }
       }
+    }
+    if (_bucket_over_threshold > 0) {
+      out->print_cr(" >%d entries: %d", report_threshold,  _bucket_over_threshold);
+    }
+    out->print_cr("most entries: %d", _longest_bucket_length);
+    out->print_cr(" ");
+    out->print_cr("Call stack depth distribution:");
+    for (index = 0; index < NMT_TrackingStackDepth; index ++) {
+      if (_stack_depth_distribution[index] > 0) {
+        out->print_cr("\t%d: %d", index + 1, _stack_depth_distribution[index]);
+      }
+    }
+  }
+
+ private:
+  void record_bucket_length(int length) {
+    _used_buckets ++;
+    if (length <= report_threshold) {
+      _hash_distribution[length - 1] ++;
     } else {
-      assert(generations_to_wrap >= 0, "Sanity check");
-      long current_generations_to_wrap = MAX_UNSIGNED_LONG - current_processing_generation;
-      assert(current_generations_to_wrap >= 0, "Sanity check");
-      // to overflow an unsigned long should take long time, so to_wrap check should be sufficient
-      if (current_generations_to_wrap > generations_to_wrap &&
-          current_processing_generation > generation_at_query_time) {
-        return true;
-      }
+      _bucket_over_threshold ++;
     }
-
-    // if worker thread is idle, but generation is not advancing, that means
-    // there is not safepoint to let NMT advance generation, force one.
-    if (_worker_thread_idle) {
-      VM_ForceSafepoint vfs;
-      VMThread::execute(&vfs);
-    }
-    MemSnapshot* snapshot = get_snapshot();
-    if (snapshot == NULL) {
-      return false;
-    }
-    snapshot->wait(1000);
-    current_processing_generation = _processing_generation;
+    _longest_bucket_length = MAX2(_longest_bucket_length, length);
   }
-  // We end up here if NMT is shutting down before our data has been merged
-  return false;
-}
-
-// compare memory usage between current snapshot and baseline
-bool MemTracker::compare_memory_usage(BaselineOutputer& out, size_t unit, bool summary_only) {
-  MutexLocker lock(_query_lock);
-  if (_baseline.baselined()) {
-    MemBaseline baseline;
-    MemSnapshot* snapshot = get_snapshot();
-    if (snapshot != NULL && baseline.baseline(*snapshot, summary_only)) {
-      BaselineReporter reporter(out, unit);
-      reporter.diff_baselines(baseline, _baseline, summary_only);
-      return true;
-    }
-  }
-  return false;
-}
-
-#ifndef PRODUCT
-void MemTracker::walk_stack(int toSkip, char* buf, int len) {
-  int cur_len = 0;
-  char tmp[1024];
-  address pc;
-
-  while (cur_len < len) {
-    pc = os::get_caller_pc(toSkip + 1);
-    if (pc != NULL && os::dll_address_to_function_name(pc, tmp, sizeof(tmp), NULL)) {
-      jio_snprintf(&buf[cur_len], (len - cur_len), "%s\n", tmp);
-      cur_len = (int)strlen(buf);
-    } else {
-      buf[cur_len] = '\0';
-      break;
-    }
-    toSkip ++;
-  }
-}
-
-void MemTracker::print_tracker_stats(outputStream* st) {
-  st->print_cr("\nMemory Tracker Stats:");
-  st->print_cr("\tMax sequence number = %d", SequenceGenerator::max_seq_num());
-  st->print_cr("\tthead count = %d", _thread_count);
-  st->print_cr("\tArena instance = %d", Arena::_instance_count);
-  st->print_cr("\tpooled recorder count = %d", _pooled_recorder_count);
-  st->print_cr("\tqueued recorder count = %d", _pending_recorder_count);
-  st->print_cr("\tmemory recorder instance count = %d", MemRecorder::_instance_count);
-  if (_worker_thread != NULL) {
-    st->print_cr("\tWorker thread:");
-    st->print_cr("\t\tSync point count = %d", _worker_thread->_sync_point_count);
-    st->print_cr("\t\tpending recorder count = %d", _worker_thread->count_pending_recorders());
-    st->print_cr("\t\tmerge count = %d", _worker_thread->_merge_count);
-  } else {
-    st->print_cr("\tWorker thread is not started");
-  }
-  st->print_cr(" ");
-
-  if (_snapshot != NULL) {
-    _snapshot->print_snapshot_stats(st);
-  } else {
-    st->print_cr("No snapshot");
-  }
-}
-#endif
+};
 
 
-// Tracker Implementation
+void MemTracker::tuning_statistics(outputStream* out) {
+  // NMT statistics
+  StatisticsWalker walker;
+  MallocSiteTable::walk_malloc_site(&walker);
+  walker.completed();
 
-/*
- * Create a tracker.
- * This is a fairly complicated constructor, as it has to make two important decisions:
- *   1) Does it need to take ThreadCritical lock to write tracking record
- *   2) Does it need to pre-reserve a sequence number for the tracking record
- *
- * The rules to determine if ThreadCritical is needed:
- *   1. When nmt is in single-threaded bootstrapping mode, no lock is needed as VM
- *      still in single thread mode.
- *   2. For all threads other than JavaThread, ThreadCritical is needed
- *      to write to recorders to global recorder.
- *   3. For JavaThreads that are no longer visible by safepoint, also
- *      need to take ThreadCritical and records are written to global
- *      recorders, since these threads are NOT walked by Threads.do_thread().
- *   4. JavaThreads that are running in safepoint-safe states do not stop
- *      for safepoints, ThreadCritical lock should be taken to write
- *      memory records.
- *   5. JavaThreads that are running in VM state do not need any lock and
- *      records are written to per-thread recorders.
- *   6. For a thread has yet to attach VM 'Thread', they need to take
- *      ThreadCritical to write to global recorder.
- *
- *  The memory operations that need pre-reserve sequence numbers:
- *    The memory operations that "release" memory blocks and the
- *    operations can fail, need to pre-reserve sequence number. They
- *    are realloc, uncommit and release.
- *
- *  The reason for pre-reserve sequence number, is to prevent race condition:
- *    Thread 1                      Thread 2
- *    <release>
- *                                  <allocate>
- *                                  <write allocate record>
- *   <write release record>
- *   if Thread 2 happens to obtain the memory address Thread 1 just released,
- *   then NMT can mistakenly report the memory is free.
- *
- *  Noticeably, free() does not need pre-reserve sequence number, because the call
- *  does not fail, so we can alway write "release" record before the memory is actaully
- *  freed.
- *
- *  For realloc, uncommit and release, following coding pattern should be used:
- *
- *     MemTracker::Tracker tkr = MemTracker::get_realloc_tracker();
- *     ptr = ::realloc(...);
- *     if (ptr == NULL) {
- *       tkr.record(...)
- *     } else {
- *       tkr.discard();
- *     }
- *
- *     MemTracker::Tracker tkr = MemTracker::get_virtual_memory_uncommit_tracker();
- *     if (uncommit(...)) {
- *       tkr.record(...);
- *     } else {
- *       tkr.discard();
- *     }
- *
- *     MemTracker::Tracker tkr = MemTracker::get_virtual_memory_release_tracker();
- *     if (release(...)) {
- *       tkr.record(...);
- *     } else {
- *       tkr.discard();
- *     }
- *
- * Since pre-reserved sequence number is only good for the generation that it is acquired,
- * when there is pending Tracker that reserved sequence number, NMT sync-point has
- * to be skipped to prevent from advancing generation. This is done by inc and dec
- * MemTracker::_pending_op_count, when MemTracker::_pending_op_count > 0, NMT sync-point is skipped.
- * Not all pre-reservation of sequence number will increment pending op count. For JavaThreads
- * that honor safepoints, safepoint can not occur during the memory operations, so the
- * pre-reserved sequence number won't cross the generation boundry.
- */
-MemTracker::Tracker::Tracker(MemoryOperation op, Thread* thr) {
-  _op = NoOp;
-  _seq = 0;
-  if (MemTracker::is_on()) {
-    _java_thread = NULL;
-    _op = op;
-
-    // figure out if ThreadCritical lock is needed to write this operation
-    // to MemTracker
-    if (MemTracker::is_single_threaded_bootstrap()) {
-      thr = NULL;
-    } else if (thr == NULL) {
-      // don't use Thread::current(), since it is possible that
-      // the calling thread has yet to attach to VM 'Thread',
-      // which will result assertion failure
-      thr = ThreadLocalStorage::thread();
-    }
-
-    if (thr != NULL) {
-      // Check NMT load
-      MemTracker::check_NMT_load(thr);
-
-      if (thr->is_Java_thread() && ((JavaThread*)thr)->is_safepoint_visible()) {
-        _java_thread = (JavaThread*)thr;
-        JavaThreadState  state = _java_thread->thread_state();
-        // JavaThreads that are safepoint safe, can run through safepoint,
-        // so ThreadCritical is needed to ensure no threads at safepoint create
-        // new records while the records are being gathered and the sequence number is changing
-        _need_thread_critical_lock =
-          SafepointSynchronize::safepoint_safe(_java_thread, state);
-      } else {
-        _need_thread_critical_lock = true;
-      }
-    } else {
-       _need_thread_critical_lock
-         = !MemTracker::is_single_threaded_bootstrap();
-    }
-
-    // see if we need to pre-reserve sequence number for this operation
-    if (_op == Realloc || _op == Uncommit || _op == Release) {
-      if (_need_thread_critical_lock) {
-        ThreadCritical tc;
-        MemTracker::inc_pending_op_count();
-        _seq = SequenceGenerator::next();
-      } else {
-        // for the threads that honor safepoints, no safepoint can occur
-        // during the lifespan of tracker, so we don't need to increase
-        // pending op count.
-        _seq = SequenceGenerator::next();
-      }
-    }
-  }
-}
-
-void MemTracker::Tracker::discard() {
-  if (MemTracker::is_on() && _seq != 0) {
-    if (_need_thread_critical_lock) {
-      ThreadCritical tc;
-      MemTracker::dec_pending_op_count();
-    }
-    _seq = 0;
-  }
-}
-
-
-void MemTracker::Tracker::record(address old_addr, address new_addr, size_t size,
-  MEMFLAGS flags, address pc) {
-  assert(old_addr != NULL && new_addr != NULL, "Sanity check");
-  assert(_op == Realloc || _op == NoOp, "Wrong call");
-  if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp) {
-    assert(_seq > 0, "Need pre-reserve sequence number");
-    if (_need_thread_critical_lock) {
-      ThreadCritical tc;
-      // free old address, use pre-reserved sequence number
-      MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(),
-        0, _seq, pc, _java_thread);
-      MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(),
-        size, SequenceGenerator::next(), pc, _java_thread);
-      // decrement MemTracker pending_op_count
-      MemTracker::dec_pending_op_count();
-    } else {
-      // free old address, use pre-reserved sequence number
-      MemTracker::write_tracking_record(old_addr, MemPointerRecord::free_tag(),
-        0, _seq, pc, _java_thread);
-      MemTracker::write_tracking_record(new_addr, flags | MemPointerRecord::malloc_tag(),
-        size, SequenceGenerator::next(), pc, _java_thread);
-    }
-    _seq = 0;
-  }
-}
-
-void MemTracker::Tracker::record(address addr, size_t size, MEMFLAGS flags, address pc) {
-  // OOM already?
-  if (addr == NULL) return;
-
-  if (MemTracker::is_on() && NMT_CAN_TRACK(flags) && _op != NoOp) {
-    bool pre_reserved_seq = (_seq != 0);
-    address  pc = CALLER_CALLER_PC;
-    MEMFLAGS orig_flags = flags;
-
-    // or the tagging flags
-    switch(_op) {
-      case Malloc:
-        flags |= MemPointerRecord::malloc_tag();
-        break;
-      case Free:
-        flags = MemPointerRecord::free_tag();
-        break;
-      case Realloc:
-        fatal("Use the other Tracker::record()");
-        break;
-      case Reserve:
-      case ReserveAndCommit:
-        flags |= MemPointerRecord::virtual_memory_reserve_tag();
-        break;
-      case Commit:
-        flags = MemPointerRecord::virtual_memory_commit_tag();
-        break;
-      case Type:
-        flags |= MemPointerRecord::virtual_memory_type_tag();
-        break;
-      case Uncommit:
-        assert(pre_reserved_seq, "Need pre-reserve sequence number");
-        flags = MemPointerRecord::virtual_memory_uncommit_tag();
-        break;
-      case Release:
-        assert(pre_reserved_seq, "Need pre-reserve sequence number");
-        flags = MemPointerRecord::virtual_memory_release_tag();
-        break;
-      case ArenaSize:
-        // a bit of hack here, add a small postive offset to arena
-        // address for its size record, so the size record is sorted
-        // right after arena record.
-        flags = MemPointerRecord::arena_size_tag();
-        addr += sizeof(void*);
-        break;
-      case StackRelease:
-        flags = MemPointerRecord::virtual_memory_release_tag();
-        break;
-      default:
-        ShouldNotReachHere();
-    }
-
-    // write memory tracking record
-    if (_need_thread_critical_lock) {
-      ThreadCritical tc;
-      if (_seq == 0) _seq = SequenceGenerator::next();
-      MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread);
-      if (_op == ReserveAndCommit) {
-        MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(),
-          size, SequenceGenerator::next(), pc, _java_thread);
-      }
-      if (pre_reserved_seq) MemTracker::dec_pending_op_count();
-    } else {
-      if (_seq == 0) _seq = SequenceGenerator::next();
-      MemTracker::write_tracking_record(addr, flags, size, _seq, pc, _java_thread);
-      if (_op == ReserveAndCommit) {
-        MemTracker::write_tracking_record(addr, orig_flags | MemPointerRecord::virtual_memory_commit_tag(),
-          size, SequenceGenerator::next(), pc, _java_thread);
-      }
-    }
-    _seq = 0;
-  }
+  out->print_cr("Native Memory Tracking Statistics:");
+  out->print_cr("Malloc allocation site table size: %d", MallocSiteTable::hash_buckets());
+  out->print_cr("             Tracking stack depth: %d", NMT_TrackingStackDepth);
+  NOT_PRODUCT(out->print_cr("Peak concurrent access: %d", MallocSiteTable::access_peak_count());)
+  out->print_cr(" ");
+  walker.report_statistics(out);
 }
 
diff --git a/hotspot/src/share/vm/services/memTracker.hpp b/hotspot/src/share/vm/services/memTracker.hpp
index 1072e5d..5b04def 100644
--- a/hotspot/src/share/vm/services/memTracker.hpp
+++ b/hotspot/src/share/vm/services/memTracker.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -25,574 +25,288 @@
 #ifndef SHARE_VM_SERVICES_MEM_TRACKER_HPP
 #define SHARE_VM_SERVICES_MEM_TRACKER_HPP
 
-#include "utilities/macros.hpp"
+#include "services/nmtCommon.hpp"
+#include "utilities/nativeCallStack.hpp"
+
 
 #if !INCLUDE_NMT
 
-#include "utilities/ostream.hpp"
+#define CURRENT_PC   NativeCallStack::EMPTY_STACK
+#define CALLER_PC    NativeCallStack::EMPTY_STACK
 
-class BaselineOutputer : public StackObj {
-
-};
-
-class BaselineTTYOutputer : public BaselineOutputer {
-  public:
-    BaselineTTYOutputer(outputStream* st) { }
+class Tracker : public StackObj {
+ public:
+  Tracker() { }
+  void record(address addr, size_t size) { }
 };
 
 class MemTracker : AllStatic {
-  public:
-   enum ShutdownReason {
-      NMT_shutdown_none,     // no shutdown requested
-      NMT_shutdown_user,     // user requested shutdown
-      NMT_normal,            // normal shutdown, process exit
-      NMT_out_of_memory,     // shutdown due to out of memory
-      NMT_initialization,    // shutdown due to initialization failure
-      NMT_use_malloc_only,   // can not combine NMT with UseMallocOnly flag
-      NMT_error_reporting,   // shutdown by vmError::report_and_die()
-      NMT_out_of_generation, // running out of generation queue
-      NMT_sequence_overflow  // overflow the sequence number
-   };
+ public:
+  static inline NMT_TrackingLevel tracking_level() { return NMT_off; }
+  static inline void shutdown() { }
+  static inline void init() { }
+  static bool check_launcher_nmt_support(const char* value) { return true; }
+  static bool verify_nmt_option() { return true; }
 
-  class Tracker {
-   public:
-    void discard() { }
+  static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag,
+    const NativeCallStack& stack, NMT_TrackingLevel level) { return mem_base; }
+  static inline size_t malloc_header_size(NMT_TrackingLevel level) { return 0; }
+  static inline size_t malloc_header_size(void* memblock) { return 0; }
+  static inline void* malloc_base(void* memblock) { return memblock; }
+  static inline void* record_free(void* memblock) { return memblock; }
 
-    void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL) { }
-    void record(address old_addr, address new_addr, size_t size,
-      MEMFLAGS flags, address pc = NULL) { }
-  };
+  static inline void record_new_arena(MEMFLAGS flag) { }
+  static inline void record_arena_free(MEMFLAGS flag) { }
+  static inline void record_arena_size_change(int diff, MEMFLAGS flag) { }
+  static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
+                       MEMFLAGS flag = mtNone) { }
+  static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
+    const NativeCallStack& stack, MEMFLAGS flag = mtNone) { }
+  static inline void record_virtual_memory_commit(void* addr, size_t size, const NativeCallStack& stack) { }
+  static inline Tracker get_virtual_memory_uncommit_tracker() { return Tracker(); }
+  static inline Tracker get_virtual_memory_release_tracker() { }
+  static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) { }
+  static inline void record_thread_stack(void* addr, size_t size) { }
+  static inline void release_thread_stack(void* addr, size_t size) { }
 
-  private:
-   static Tracker  _tkr;
-
-
-  public:
-   static inline void init_tracking_options(const char* option_line) { }
-   static inline bool is_on()   { return false; }
-   static const char* reason()  { return "Native memory tracking is not implemented"; }
-   static inline bool can_walk_stack() { return false; }
-
-   static inline void bootstrap_single_thread() { }
-   static inline void bootstrap_multi_thread() { }
-   static inline void start() { }
-
-   static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
-        address pc = 0, Thread* thread = NULL) { }
-   static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) { }
-   static inline void record_arena_size(address addr, size_t size) { }
-   static inline void record_virtual_memory_reserve(address addr, size_t size,
-        MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
-   static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size,
-        MEMFLAGS flags, address pc = 0, Thread* thread = NULL) { }
-   static inline void record_virtual_memory_commit(address addr, size_t size,
-        address pc = 0, Thread* thread = NULL) { }
-   static inline void record_virtual_memory_release(address addr, size_t size,
-        Thread* thread = NULL) { }
-   static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
-        Thread* thread = NULL) { }
-   static inline Tracker get_realloc_tracker() { return _tkr; }
-   static inline Tracker get_virtual_memory_uncommit_tracker() { return _tkr; }
-   static inline Tracker get_virtual_memory_release_tracker()  { return _tkr; }
-   static inline bool baseline() { return false; }
-   static inline bool has_baseline() { return false; }
-
-   static inline void set_autoShutdown(bool value) { }
-   static void shutdown(ShutdownReason reason) { }
-   static inline bool shutdown_in_progress() { return false; }
-   static bool print_memory_usage(BaselineOutputer& out, size_t unit,
-            bool summary_only = true) { return false; }
-   static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
-            bool summary_only = true) { return false; }
-
-   static bool wbtest_wait_for_data_merge() { return false; }
-
-   static inline void sync() { }
-   static inline void thread_exiting(JavaThread* thread) { }
+  static void final_report(outputStream*) { }
 };
 
-
-#else // !INCLUDE_NMT
-
-#include "memory/allocation.hpp"
-#include "runtime/globals.hpp"
-#include "runtime/mutex.hpp"
-#include "runtime/os.hpp"
-#include "runtime/thread.hpp"
-#include "services/memPtr.hpp"
-#include "services/memRecorder.hpp"
-#include "services/memSnapshot.hpp"
-#include "services/memTrackWorker.hpp"
-
-extern bool NMT_track_callsite;
-
-#ifndef MAX_UNSIGNED_LONG
-#define MAX_UNSIGNED_LONG    (unsigned long)(-1)
-#endif
-
-#ifdef ASSERT
-  #define DEBUG_CALLER_PC  (NMT_track_callsite ? os::get_caller_pc(2) : 0)
 #else
-  #define DEBUG_CALLER_PC  0
-#endif
 
-// The thread closure walks threads to collect per-thread
-// memory recorders at NMT sync point
-class SyncThreadRecorderClosure : public ThreadClosure {
- private:
-  int _thread_count;
+#include "runtime/atomic.hpp"
+#include "runtime/threadCritical.hpp"
+#include "services/mallocTracker.hpp"
+#include "services/virtualMemoryTracker.hpp"
+
+extern volatile bool NMT_stack_walkable;
+
+#define CURRENT_PC ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ? \
+                    NativeCallStack(0, true) : NativeCallStack::EMPTY_STACK)
+#define CALLER_PC  ((MemTracker::tracking_level() == NMT_detail && NMT_stack_walkable) ?  \
+                    NativeCallStack(1, true) : NativeCallStack::EMPTY_STACK)
+
+class MemBaseline;
+class Mutex;
+
+// Tracker is used for guarding 'release' semantics of virtual memory operation, to avoid
+// the other thread obtains and records the same region that is just 'released' by current
+// thread but before it can record the operation.
+class Tracker : public StackObj {
+ public:
+  enum TrackerType {
+     uncommit,
+     release
+  };
 
  public:
-  SyncThreadRecorderClosure() {
-    _thread_count =0;
-  }
-
-  void do_thread(Thread* thread);
-  int  get_thread_count() const {
-    return _thread_count;
-  }
+  Tracker(enum TrackerType type) : _type(type) { }
+  void record(address addr, size_t size);
+ private:
+  enum TrackerType  _type;
+  // Virtual memory tracking data structures are protected by ThreadCritical lock.
+  ThreadCritical    _tc;
 };
 
-class BaselineOutputer;
-class MemSnapshot;
-class MemTrackWorker;
-class Thread;
-/*
- * MemTracker is the 'gate' class to native memory tracking runtime.
- */
 class MemTracker : AllStatic {
-  friend class GenerationData;
-  friend class MemTrackWorker;
-  friend class MemSnapshot;
-  friend class SyncThreadRecorderClosure;
-
-  // NMT state
-  enum NMTStates {
-    NMT_uninited,                        // not yet initialized
-    NMT_bootstrapping_single_thread,     // bootstrapping, VM is in single thread mode
-    NMT_bootstrapping_multi_thread,      // bootstrapping, VM is about to enter multi-thread mode
-    NMT_started,                         // NMT fully started
-    NMT_shutdown_pending,                // shutdown pending
-    NMT_final_shutdown,                  // in final phase of shutdown
-    NMT_shutdown                         // shutdown
-  };
-
  public:
-  class Tracker : public StackObj {
-    friend class MemTracker;
-   public:
-    enum MemoryOperation {
-      NoOp,                   // no op
-      Malloc,                 // malloc
-      Realloc,                // realloc
-      Free,                   // free
-      Reserve,                // virtual memory reserve
-      Commit,                 // virtual memory commit
-      ReserveAndCommit,       // virtual memory reserve and commit
-      StackAlloc = ReserveAndCommit, // allocate thread stack
-      Type,                   // assign virtual memory type
-      Uncommit,               // virtual memory uncommit
-      Release,                // virtual memory release
-      ArenaSize,              // set arena size
-      StackRelease            // release thread stack
-    };
-
-
-   protected:
-    Tracker(MemoryOperation op, Thread* thr = NULL);
-
-   public:
-    void discard();
-
-    void record(address addr, size_t size = 0, MEMFLAGS flags = mtNone, address pc = NULL);
-    void record(address old_addr, address new_addr, size_t size,
-      MEMFLAGS flags, address pc = NULL);
-
-   private:
-    bool            _need_thread_critical_lock;
-    JavaThread*     _java_thread;
-    MemoryOperation _op;          // memory operation
-    jint            _seq;         // reserved sequence number
-  };
-
-
- public:
-  // native memory tracking level
-  enum NMTLevel {
-    NMT_off,              // native memory tracking is off
-    NMT_summary,          // don't track callsite
-    NMT_detail            // track callsite also
-  };
-
-   enum ShutdownReason {
-     NMT_shutdown_none,     // no shutdown requested
-     NMT_shutdown_user,     // user requested shutdown
-     NMT_normal,            // normal shutdown, process exit
-     NMT_out_of_memory,     // shutdown due to out of memory
-     NMT_initialization,    // shutdown due to initialization failure
-     NMT_use_malloc_only,   // can not combine NMT with UseMallocOnly flag
-     NMT_error_reporting,   // shutdown by vmError::report_and_die()
-     NMT_out_of_generation, // running out of generation queue
-     NMT_sequence_overflow  // overflow the sequence number
-   };
-
- public:
-  // initialize NMT tracking level from command line options, called
-   // from VM command line parsing code
-  static void init_tracking_options(const char* option_line);
-
-  // if NMT is enabled to record memory activities
-  static inline bool is_on() {
-    return (_tracking_level >= NMT_summary &&
-      _state >= NMT_bootstrapping_single_thread);
-  }
-
-  static inline enum NMTLevel tracking_level() {
+  static inline NMT_TrackingLevel tracking_level() {
+    if (_tracking_level == NMT_unknown) {
+      // No fencing is needed here, since JVM is in single-threaded
+      // mode.
+      _tracking_level = init_tracking_level();
+      _cmdline_tracking_level = _tracking_level;
+    }
     return _tracking_level;
   }
 
-  // user readable reason for shutting down NMT
-  static const char* reason() {
-    switch(_reason) {
-      case NMT_shutdown_none:
-        return "Native memory tracking is not enabled";
-      case NMT_shutdown_user:
-        return "Native memory tracking has been shutdown by user";
-      case NMT_normal:
-        return "Native memory tracking has been shutdown due to process exiting";
-      case NMT_out_of_memory:
-        return "Native memory tracking has been shutdown due to out of native memory";
-      case NMT_initialization:
-        return "Native memory tracking failed to initialize";
-      case NMT_error_reporting:
-        return "Native memory tracking has been shutdown due to error reporting";
-      case NMT_out_of_generation:
-        return "Native memory tracking has been shutdown due to running out of generation buffer";
-      case NMT_sequence_overflow:
-        return "Native memory tracking has been shutdown due to overflow the sequence number";
-      case NMT_use_malloc_only:
-        return "Native memory tracking is not supported when UseMallocOnly is on";
-      default:
-        ShouldNotReachHere();
-        return NULL;
+  // A late initialization, for the stuff(s) can not be
+  // done in init_tracking_level(), which can NOT malloc
+  // any memory.
+  static void init();
+
+  // Shutdown native memory tracking
+  static void shutdown();
+
+  // Verify native memory tracking command line option.
+  // This check allows JVM to detect if compatible launcher
+  // is used.
+  // If an incompatible launcher is used, NMT may not be
+  // able to start, even it is enabled by command line option.
+  // A warning message should be given if it is encountered.
+  static bool check_launcher_nmt_support(const char* value);
+
+  // This method checks native memory tracking environment
+  // variable value passed by launcher.
+  // Launcher only obligates to pass native memory tracking
+  // option value, but not obligates to validate the value,
+  // and launcher has option to discard native memory tracking
+  // option from the command line once it sets up the environment
+  // variable, so NMT has to catch the bad value here.
+  static bool verify_nmt_option();
+
+  // Transition the tracking level to specified level
+  static bool transition_to(NMT_TrackingLevel level);
+
+  static inline void* record_malloc(void* mem_base, size_t size, MEMFLAGS flag,
+    const NativeCallStack& stack, NMT_TrackingLevel level) {
+    return MallocTracker::record_malloc(mem_base, size, flag, stack, level);
+  }
+
+  static inline size_t malloc_header_size(NMT_TrackingLevel level) {
+    return MallocTracker::malloc_header_size(level);
+  }
+
+  static size_t malloc_header_size(void* memblock) {
+    if (tracking_level() != NMT_off) {
+      return MallocTracker::get_header_size(memblock);
+    }
+    return 0;
+  }
+
+  // To malloc base address, which is the starting address
+  // of malloc tracking header if tracking is enabled.
+  // Otherwise, it returns the same address.
+  static void* malloc_base(void* memblock);
+
+  // Record malloc free and return malloc base address
+  static inline void* record_free(void* memblock) {
+    return MallocTracker::record_free(memblock);
+  }
+
+
+  // Record creation of an arena
+  static inline void record_new_arena(MEMFLAGS flag) {
+    if (tracking_level() < NMT_summary) return;
+    MallocTracker::record_new_arena(flag);
+  }
+
+  // Record destruction of an arena
+  static inline void record_arena_free(MEMFLAGS flag) {
+    if (tracking_level() < NMT_summary) return;
+    MallocTracker::record_arena_free(flag);
+  }
+
+  // Record arena size change. Arena size is the size of all arena
+  // chuncks that backing up the arena.
+  static inline void record_arena_size_change(int diff, MEMFLAGS flag) {
+    if (tracking_level() < NMT_summary) return;
+    MallocTracker::record_arena_size_change(diff, flag);
+  }
+
+  static inline void record_virtual_memory_reserve(void* addr, size_t size, const NativeCallStack& stack,
+    MEMFLAGS flag = mtNone) {
+    if (tracking_level() < NMT_summary) return;
+    if (addr != NULL) {
+      ThreadCritical tc;
+      // Recheck to avoid potential racing during NMT shutdown
+      if (tracking_level() < NMT_summary) return;
+      VirtualMemoryTracker::add_reserved_region((address)addr, size, stack, flag);
     }
   }
 
-  // test if we can walk native stack
-  static bool can_walk_stack() {
-  // native stack is not walkable during bootstrapping on sparc
-#if defined(SPARC)
-    return (_state == NMT_started);
-#else
-    return (_state >= NMT_bootstrapping_single_thread && _state  <= NMT_started);
-#endif
-  }
-
-  // if native memory tracking tracks callsite
-  static inline bool track_callsite() { return _tracking_level == NMT_detail; }
-
-  // NMT automatically shuts itself down under extreme situation by default.
-  // When the value is set to false,  NMT will try its best to stay alive,
-  // even it has to slow down VM.
-  static inline void set_autoShutdown(bool value) {
-    AutoShutdownNMT = value;
-    if (AutoShutdownNMT && _slowdown_calling_thread) {
-      _slowdown_calling_thread = false;
+  static inline void record_virtual_memory_reserve_and_commit(void* addr, size_t size,
+    const NativeCallStack& stack, MEMFLAGS flag = mtNone) {
+    if (tracking_level() < NMT_summary) return;
+    if (addr != NULL) {
+      ThreadCritical tc;
+      if (tracking_level() < NMT_summary) return;
+      VirtualMemoryTracker::add_reserved_region((address)addr, size,
+        stack, flag, true);
     }
   }
 
-  // shutdown native memory tracking capability. Native memory tracking
-  // can be shutdown by VM when it encounters low memory scenarios.
-  // Memory tracker should gracefully shutdown itself, and preserve the
-  // latest memory statistics for post morten diagnosis.
-  static void shutdown(ShutdownReason reason);
-
-  // if there is shutdown requested
-  static inline bool shutdown_in_progress() {
-    return (_state >= NMT_shutdown_pending);
-  }
-
-  // bootstrap native memory tracking, so it can start to collect raw data
-  // before worker thread can start
-
-  // the first phase of bootstrapping, when VM still in single-threaded mode
-  static void bootstrap_single_thread();
-  // the second phase of bootstrapping, VM is about or already in multi-threaded mode
-  static void bootstrap_multi_thread();
-
-
-  // start() has to be called when VM still in single thread mode, but after
-  // command line option parsing is done.
-  static void start();
-
-  // record a 'malloc' call
-  static inline void record_malloc(address addr, size_t size, MEMFLAGS flags,
-                            address pc = 0, Thread* thread = NULL) {
-    Tracker tkr(Tracker::Malloc, thread);
-    tkr.record(addr, size, flags, pc);
-  }
-  // record a 'free' call
-  static inline void record_free(address addr, MEMFLAGS flags, Thread* thread = NULL) {
-    Tracker tkr(Tracker::Free, thread);
-    tkr.record(addr, 0, flags, DEBUG_CALLER_PC);
-  }
-
-  static inline void record_arena_size(address addr, size_t size) {
-    Tracker tkr(Tracker::ArenaSize);
-    tkr.record(addr, size);
-  }
-
-  // record a virtual memory 'reserve' call
-  static inline void record_virtual_memory_reserve(address addr, size_t size,
-                     MEMFLAGS flags, address pc = 0, Thread* thread = NULL) {
-    assert(size > 0, "Sanity check");
-    Tracker tkr(Tracker::Reserve, thread);
-    tkr.record(addr, size, flags, pc);
-  }
-
-  static inline void record_thread_stack(address addr, size_t size, Thread* thr,
-                           address pc = 0) {
-    Tracker tkr(Tracker::StackAlloc, thr);
-    tkr.record(addr, size, mtThreadStack, pc);
-  }
-
-  static inline void release_thread_stack(address addr, size_t size, Thread* thr) {
-    Tracker tkr(Tracker::StackRelease, thr);
-    tkr.record(addr, size, mtThreadStack, DEBUG_CALLER_PC);
-  }
-
-  // record a virtual memory 'commit' call
-  static inline void record_virtual_memory_commit(address addr, size_t size,
-                            address pc, Thread* thread = NULL) {
-    Tracker tkr(Tracker::Commit, thread);
-    tkr.record(addr, size, mtNone, pc);
-  }
-
-  static inline void record_virtual_memory_reserve_and_commit(address addr, size_t size,
-    MEMFLAGS flags, address pc, Thread* thread = NULL) {
-    Tracker tkr(Tracker::ReserveAndCommit, thread);
-    tkr.record(addr, size, flags, pc);
-  }
-
-  static inline void record_virtual_memory_release(address addr, size_t size,
-      Thread* thread = NULL) {
-    if (is_on()) {
-      Tracker tkr(Tracker::Release, thread);
-      tkr.record(addr, size);
+  static inline void record_virtual_memory_commit(void* addr, size_t size,
+    const NativeCallStack& stack) {
+    if (tracking_level() < NMT_summary) return;
+    if (addr != NULL) {
+      ThreadCritical tc;
+      if (tracking_level() < NMT_summary) return;
+      VirtualMemoryTracker::add_committed_region((address)addr, size, stack);
     }
   }
 
-  // record memory type on virtual memory base address
-  static inline void record_virtual_memory_type(address base, MEMFLAGS flags,
-                            Thread* thread = NULL) {
-    Tracker tkr(Tracker::Type);
-    tkr.record(base, 0, flags);
-  }
-
-  // Get memory trackers for memory operations that can result race conditions.
-  // The memory tracker has to be obtained before realloc, virtual memory uncommit
-  // and virtual memory release, and call tracker.record() method if operation
-  // succeeded, or tracker.discard() to abort the tracking.
-  static inline Tracker get_realloc_tracker() {
-    return Tracker(Tracker::Realloc);
-  }
-
   static inline Tracker get_virtual_memory_uncommit_tracker() {
-    return Tracker(Tracker::Uncommit);
+    assert(tracking_level() >= NMT_summary, "Check by caller");
+    return Tracker(Tracker::uncommit);
   }
 
   static inline Tracker get_virtual_memory_release_tracker() {
-    return Tracker(Tracker::Release);
+    assert(tracking_level() >= NMT_summary, "Check by caller");
+    return Tracker(Tracker::release);
   }
 
-
-  // create memory baseline of current memory snapshot
-  static bool baseline();
-  // is there a memory baseline
-  static bool has_baseline() {
-    return _baseline.baselined();
-  }
-
-  // print memory usage from current snapshot
-  static bool print_memory_usage(BaselineOutputer& out, size_t unit,
-           bool summary_only = true);
-  // compare memory usage between current snapshot and baseline
-  static bool compare_memory_usage(BaselineOutputer& out, size_t unit,
-           bool summary_only = true);
-
-  // the version for whitebox testing support, it ensures that all memory
-  // activities before this method call, are reflected in the snapshot
-  // database.
-  static bool wbtest_wait_for_data_merge();
-
-  // sync is called within global safepoint to synchronize nmt data
-  static void sync();
-
-  // called when a thread is about to exit
-  static void thread_exiting(JavaThread* thread);
-
-  // retrieve global snapshot
-  static MemSnapshot* get_snapshot() {
-    if (shutdown_in_progress()) {
-      return NULL;
-    }
-    return _snapshot;
-  }
-
-  // print tracker stats
-  NOT_PRODUCT(static void print_tracker_stats(outputStream* st);)
-  NOT_PRODUCT(static void walk_stack(int toSkip, char* buf, int len);)
-
- private:
-  // start native memory tracking worker thread
-  static bool start_worker(MemSnapshot* snapshot);
-
-  // called by worker thread to complete shutdown process
-  static void final_shutdown();
-
- protected:
-  // retrieve per-thread recorder of the specified thread.
-  // if the recorder is full, it will be enqueued to overflow
-  // queue, a new recorder is acquired from recorder pool or a
-  // new instance is created.
-  // when thread == NULL, it means global recorder
-  static MemRecorder* get_thread_recorder(JavaThread* thread);
-
-  // per-thread recorder pool
-  static void release_thread_recorder(MemRecorder* rec);
-  static void delete_all_pooled_recorders();
-
-  // pending recorder queue. Recorders are queued to pending queue
-  // when they are overflowed or collected at nmt sync point.
-  static void enqueue_pending_recorder(MemRecorder* rec);
-  static MemRecorder* get_pending_recorders();
-  static void delete_all_pending_recorders();
-
-  // write a memory tracking record in recorder
-  static void write_tracking_record(address addr, MEMFLAGS type,
-    size_t size, jint seq, address pc, JavaThread* thread);
-
-  static bool is_single_threaded_bootstrap() {
-    return _state == NMT_bootstrapping_single_thread;
-  }
-
-  static void check_NMT_load(Thread* thr) {
-    assert(thr != NULL, "Sanity check");
-    if (_slowdown_calling_thread && thr != _worker_thread) {
-#ifdef _WINDOWS
-      // On Windows, os::NakedYield() does not work as well
-      // as os::yield_all()
-      os::yield_all();
-#else
-     // On Solaris, os::yield_all() depends on os::sleep()
-     // which requires JavaTherad in _thread_in_vm state.
-     // Transits thread to _thread_in_vm state can be dangerous
-     // if caller holds lock, as it may deadlock with Threads_lock.
-     // So use NaKedYield instead.
-     //
-     // Linux and BSD, NakedYield() and yield_all() implementations
-     // are the same.
-      os::NakedYield();
-#endif
+  static inline void record_virtual_memory_type(void* addr, MEMFLAGS flag) {
+    if (tracking_level() < NMT_summary) return;
+    if (addr != NULL) {
+      ThreadCritical tc;
+      if (tracking_level() < NMT_summary) return;
+      VirtualMemoryTracker::set_reserved_region_type((address)addr, flag);
     }
   }
 
-  static void inc_pending_op_count() {
-    Atomic::inc(&_pending_op_count);
+  static inline void record_thread_stack(void* addr, size_t size) {
+    if (tracking_level() < NMT_summary) return;
+    if (addr != NULL) {
+      // uses thread stack malloc slot for book keeping number of threads
+      MallocMemorySummary::record_malloc(0, mtThreadStack);
+      record_virtual_memory_reserve_and_commit(addr, size, CALLER_PC, mtThreadStack);
+    }
   }
 
-  static void dec_pending_op_count() {
-    Atomic::dec(&_pending_op_count);
-    assert(_pending_op_count >= 0, "Sanity check");
+  static inline void release_thread_stack(void* addr, size_t size) {
+    if (tracking_level() < NMT_summary) return;
+    if (addr != NULL) {
+      // uses thread stack malloc slot for book keeping number of threads
+      MallocMemorySummary::record_free(0, mtThreadStack);
+      ThreadCritical tc;
+      if (tracking_level() < NMT_summary) return;
+      VirtualMemoryTracker::remove_released_region((address)addr, size);
+    }
   }
 
+  // Query lock is used to synchronize the access to tracking data.
+  // So far, it is only used by JCmd query, but it may be used by
+  // other tools.
+  static inline Mutex* query_lock() { return _query_lock; }
+
+  // Make a final report and shutdown.
+  // This function generates summary report without creating snapshots,
+  // to avoid additional memory allocation. It uses native memory summary
+  // counters, and makes adjustment to them, once the adjustment is made,
+  // the counters are no longer accurate. As the result, this function
+  // should only be used for final reporting before shutting down.
+  static void final_report(outputStream*);
+
+  // Stored baseline
+  static inline MemBaseline& get_baseline() {
+    return _baseline;
+  }
+
+  static NMT_TrackingLevel cmdline_tracking_level() {
+    return _cmdline_tracking_level;
+  }
+
+  static void tuning_statistics(outputStream* out);
 
  private:
-  // retrieve a pooled memory record or create new one if there is not
-  // one available
-  static MemRecorder* get_new_or_pooled_instance();
-  static void create_memory_record(address addr, MEMFLAGS type,
-                   size_t size, address pc, Thread* thread);
-  static void create_record_in_recorder(address addr, MEMFLAGS type,
-                   size_t size, address pc, JavaThread* thread);
-
-  static void set_current_processing_generation(unsigned long generation) {
-    _worker_thread_idle = false;
-    _processing_generation = generation;
-  }
-
-  static void report_worker_idle() {
-    _worker_thread_idle = true;
-  }
+  static NMT_TrackingLevel init_tracking_level();
 
  private:
-  // global memory snapshot
-  static MemSnapshot*     _snapshot;
-
-  // a memory baseline of snapshot
+  // Tracking level
+  static volatile NMT_TrackingLevel   _tracking_level;
+  // If NMT option value passed by launcher through environment
+  // variable is valid
+  static bool                         _is_nmt_env_valid;
+  // command line tracking level
+  static NMT_TrackingLevel            _cmdline_tracking_level;
+  // Stored baseline
   static MemBaseline      _baseline;
-
-  // query lock
+  // Query lock
   static Mutex*           _query_lock;
-
-  // a thread can start to allocate memory before it is attached
-  // to VM 'Thread', those memory activities are recorded here.
-  // ThreadCritical is required to guard this global recorder.
-  static MemRecorder* volatile _global_recorder;
-
-  // main thread id
-  debug_only(static intx   _main_thread_tid;)
-
-  // pending recorders to be merged
-  static MemRecorder* volatile     _merge_pending_queue;
-
-  NOT_PRODUCT(static volatile jint   _pending_recorder_count;)
-
-  // pooled memory recorders
-  static MemRecorder* volatile     _pooled_recorders;
-
-  // memory recorder pool management, uses following
-  // counter to determine if a released memory recorder
-  // should be pooled
-
-  // latest thread count
-  static int               _thread_count;
-  // pooled recorder count
-  static volatile jint     _pooled_recorder_count;
-
-
-  // worker thread to merge pending recorders into snapshot
-  static MemTrackWorker*  _worker_thread;
-
-  // how many safepoints we skipped without entering sync point
-  static int              _sync_point_skip_count;
-
-  // if the tracker is properly intialized
-  static bool             _is_tracker_ready;
-  // tracking level (off, summary and detail)
-  static enum NMTLevel    _tracking_level;
-
-  // current nmt state
-  static volatile enum NMTStates   _state;
-  // the reason for shutting down nmt
-  static enum ShutdownReason       _reason;
-  // the generation that NMT is processing
-  static volatile unsigned long    _processing_generation;
-  // although NMT is still procesing current generation, but
-  // there is not more recorder to process, set idle state
-  static volatile bool             _worker_thread_idle;
-
-  // if NMT should slow down calling thread to allow
-  // worker thread to catch up
-  static volatile bool             _slowdown_calling_thread;
-
-  // pending memory op count.
-  // Certain memory ops need to pre-reserve sequence number
-  // before memory operation can happen to avoid race condition.
-  // See MemTracker::Tracker for detail
-  static volatile jint             _pending_op_count;
 };
 
-#endif // !INCLUDE_NMT
+#endif // INCLUDE_NMT
 
 #endif // SHARE_VM_SERVICES_MEM_TRACKER_HPP
+
diff --git a/hotspot/src/share/vm/services/memoryManager.cpp b/hotspot/src/share/vm/services/memoryManager.cpp
index 0cfd05b..0daa0a3 100644
--- a/hotspot/src/share/vm/services/memoryManager.cpp
+++ b/hotspot/src/share/vm/services/memoryManager.cpp
@@ -28,6 +28,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "services/lowMemoryDetector.hpp"
 #include "services/management.hpp"
 #include "services/memoryManager.hpp"
diff --git a/hotspot/src/share/vm/services/memoryPool.cpp b/hotspot/src/share/vm/services/memoryPool.cpp
index 5d9c253..1510cd5 100644
--- a/hotspot/src/share/vm/services/memoryPool.cpp
+++ b/hotspot/src/share/vm/services/memoryPool.cpp
@@ -29,6 +29,7 @@
 #include "oops/oop.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/javaCalls.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "services/lowMemoryDetector.hpp"
 #include "services/management.hpp"
 #include "services/memoryManager.hpp"
diff --git a/hotspot/src/share/vm/services/nmtCommon.cpp b/hotspot/src/share/vm/services/nmtCommon.cpp
new file mode 100644
index 0000000..0934e96
--- /dev/null
+++ b/hotspot/src/share/vm/services/nmtCommon.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ */
+#include "precompiled.hpp"
+#include "services/nmtCommon.hpp"
+
+const char* NMTUtil::_memory_type_names[] = {
+  "Java Heap",
+  "Class",
+  "Thread",
+  "Thread Stack",
+  "Code",
+  "GC",
+  "Compiler",
+  "Internal",
+  "Other",
+  "Symbol",
+  "Native Memory Tracking",
+  "Shared class space",
+  "Arena Chunk",
+  "Test",
+  "Tracing",
+  "Unknown"
+};
+
+
+const char* NMTUtil::scale_name(size_t scale) {
+  switch(scale) {
+    case K: return "KB";
+    case M: return "MB";
+    case G: return "GB";
+  }
+  ShouldNotReachHere();
+  return NULL;
+}
+
+size_t NMTUtil::scale_from_name(const char* scale) {
+  assert(scale != NULL, "Null pointer check");
+  if (strncmp(scale, "KB", 2) == 0 ||
+      strncmp(scale, "kb", 2) == 0) {
+    return K;
+  } else if (strncmp(scale, "MB", 2) == 0 ||
+             strncmp(scale, "mb", 2) == 0) {
+    return M;
+  } else if (strncmp(scale, "GB", 2) == 0 ||
+             strncmp(scale, "gb", 2) == 0) {
+    return G;
+  } else {
+    return 0; // Invalid value
+  }
+  return K;
+}
+
diff --git a/hotspot/src/share/vm/services/nmtCommon.hpp b/hotspot/src/share/vm/services/nmtCommon.hpp
new file mode 100644
index 0000000..f057484
--- /dev/null
+++ b/hotspot/src/share/vm/services/nmtCommon.hpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_SERVICES_NMT_COMMON_HPP
+#define SHARE_VM_SERVICES_NMT_COMMON_HPP
+
+#include "memory/allocation.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+#define CALC_OBJ_SIZE_IN_TYPE(obj, type) (align_size_up_(sizeof(obj), sizeof(type))/sizeof(type))
+
+// Data type for memory counters
+#ifdef _LP64
+  typedef jlong    MemoryCounterType;
+#else
+  typedef jint     MemoryCounterType;
+#endif
+
+// Native memory tracking level
+enum NMT_TrackingLevel {
+  NMT_unknown = 0xFF,
+  NMT_off     = 0x00,
+  NMT_minimal = 0x01,
+  NMT_summary = 0x02,
+  NMT_detail  = 0x03
+};
+
+// Number of stack frames to capture. This is a
+// build time decision.
+const int NMT_TrackingStackDepth = 4;
+
+// A few common utilities for native memory tracking
+class NMTUtil : AllStatic {
+ public:
+  // Map memory type to index
+  static inline int flag_to_index(MEMFLAGS flag) {
+    return (flag & 0xff);
+  }
+
+  // Map memory type to human readable name
+  static const char* flag_to_name(MEMFLAGS flag) {
+    return _memory_type_names[flag_to_index(flag)];
+  }
+
+  // Map an index to memory type
+  static MEMFLAGS index_to_flag(int index) {
+    return (MEMFLAGS)index;
+  }
+
+  // Memory size scale
+  static const char* scale_name(size_t scale);
+  static size_t scale_from_name(const char* scale);
+
+  // Translate memory size in specified scale
+  static size_t amount_in_scale(size_t amount, size_t scale) {
+    return (amount + scale / 2) / scale;
+  }
+ private:
+  static const char* _memory_type_names[mt_number_of_types];
+};
+
+
+#endif
diff --git a/hotspot/src/share/vm/services/nmtDCmd.cpp b/hotspot/src/share/vm/services/nmtDCmd.cpp
index 8ced287..fcad784 100644
--- a/hotspot/src/share/vm/services/nmtDCmd.cpp
+++ b/hotspot/src/share/vm/services/nmtDCmd.cpp
@@ -22,6 +22,8 @@
  *
  */
 #include "precompiled.hpp"
+
+#include "runtime/mutexLocker.hpp"
 #include "services/nmtDCmd.hpp"
 #include "services/memReporter.hpp"
 #include "services/memTracker.hpp"
@@ -49,13 +51,8 @@
   _shutdown("shutdown", "request runtime to shutdown itself and free the " \
             "memory used by runtime.",
             "BOOLEAN", false, "false"),
-  _auto_shutdown("autoShutdown", "automatically shutdown itself under "    \
-            "stress situation",
-            "BOOLEAN", true, "true"),
-#ifndef PRODUCT
-  _debug("debug", "print tracker statistics. Debug only, not thread safe", \
+  _statistics("statistics", "print tracker statistics for tuning purpose.", \
             "BOOLEAN", false, "false"),
-#endif
   _scale("scale", "Memory usage in which scale, KB, MB or GB",
        "STRING", false, "KB") {
   _dcmdparser.add_dcmd_option(&_summary);
@@ -64,25 +61,30 @@
   _dcmdparser.add_dcmd_option(&_summary_diff);
   _dcmdparser.add_dcmd_option(&_detail_diff);
   _dcmdparser.add_dcmd_option(&_shutdown);
-  _dcmdparser.add_dcmd_option(&_auto_shutdown);
-#ifndef PRODUCT
-  _dcmdparser.add_dcmd_option(&_debug);
-#endif
+  _dcmdparser.add_dcmd_option(&_statistics);
   _dcmdparser.add_dcmd_option(&_scale);
 }
 
+
+size_t NMTDCmd::get_scale(const char* scale) const {
+  if (scale == NULL) return 0;
+  return NMTUtil::scale_from_name(scale);
+}
+
 void NMTDCmd::execute(DCmdSource source, TRAPS) {
+  // Check NMT state
+  //  native memory tracking has to be on
+  if (MemTracker::tracking_level() == NMT_off) {
+    output()->print_cr("Native memory tracking is not enabled");
+    return;
+  } else if (MemTracker::tracking_level() == NMT_minimal) {
+     output()->print_cr("Native memory tracking has been shutdown");
+     return;
+  }
+
   const char* scale_value = _scale.value();
-  size_t scale_unit;
-  if (strcmp(scale_value, "KB") == 0 || strcmp(scale_value, "kb") == 0) {
-    scale_unit = K;
-  } else if (strcmp(scale_value, "MB") == 0 ||
-             strcmp(scale_value, "mb") == 0) {
-    scale_unit = M;
-  } else if (strcmp(scale_value, "GB") == 0 ||
-             strcmp(scale_value, "gb") == 0) {
-    scale_unit = G;
-  } else {
+  size_t scale_unit = get_scale(scale_value);
+  if (scale_unit == 0) {
     output()->print_cr("Incorrect scale value: %s", scale_value);
     return;
   }
@@ -94,19 +96,11 @@
   if (_summary_diff.is_set() && _summary_diff.value()) { ++nopt; }
   if (_detail_diff.is_set() && _detail_diff.value()) { ++nopt; }
   if (_shutdown.is_set() && _shutdown.value()) { ++nopt; }
-  if (_auto_shutdown.is_set()) { ++nopt; }
-
-#ifndef PRODUCT
-  if (_debug.is_set() && _debug.value()) { ++nopt; }
-#endif
+  if (_statistics.is_set() && _statistics.value()) { ++nopt; }
 
   if (nopt > 1) {
       output()->print_cr("At most one of the following option can be specified: " \
-        "summary, detail, baseline, summary.diff, detail.diff, shutdown"
-#ifndef PRODUCT
-        ", debug"
-#endif
-      );
+        "summary, detail, baseline, summary.diff, detail.diff, shutdown");
       return;
   } else if (nopt == 0) {
     if (_summary.is_set()) {
@@ -117,53 +111,47 @@
     }
   }
 
-#ifndef PRODUCT
-  if (_debug.value()) {
-    output()->print_cr("debug command is NOT thread-safe, may cause crash");
-    MemTracker::print_tracker_stats(output());
-    return;
-  }
-#endif
-
-  // native memory tracking has to be on
-  if (!MemTracker::is_on() || MemTracker::shutdown_in_progress()) {
-    // if it is not on, what's the reason?
-    output()->print_cr("%s", MemTracker::reason());
-    return;
-  }
+  // Serialize NMT query
+  MutexLocker locker(MemTracker::query_lock());
 
   if (_summary.value()) {
-    BaselineTTYOutputer outputer(output());
-    MemTracker::print_memory_usage(outputer, scale_unit, true);
+    report(true, scale_unit);
   } else if (_detail.value()) {
-    BaselineTTYOutputer outputer(output());
-    MemTracker::print_memory_usage(outputer, scale_unit, false);
+    if (!check_detail_tracking_level(output())) {
+    return;
+  }
+    report(false, scale_unit);
   } else if (_baseline.value()) {
-    if (MemTracker::baseline()) {
-      output()->print_cr("Successfully baselined.");
+    MemBaseline& baseline = MemTracker::get_baseline();
+    if (!baseline.baseline(MemTracker::tracking_level() != NMT_detail)) {
+      output()->print_cr("Baseline failed");
     } else {
-      output()->print_cr("Baseline failed.");
+      output()->print_cr("Baseline succeeded");
     }
   } else if (_summary_diff.value()) {
-    if (MemTracker::has_baseline()) {
-      BaselineTTYOutputer outputer(output());
-      MemTracker::compare_memory_usage(outputer, scale_unit, true);
+    MemBaseline& baseline = MemTracker::get_baseline();
+    if (baseline.baseline_type() >= MemBaseline::Summary_baselined) {
+      report_diff(true, scale_unit);
     } else {
-      output()->print_cr("No baseline to compare, run 'baseline' command first");
+      output()->print_cr("No baseline for comparison");
     }
   } else if (_detail_diff.value()) {
-    if (MemTracker::has_baseline()) {
-      BaselineTTYOutputer outputer(output());
-      MemTracker::compare_memory_usage(outputer, scale_unit, false);
+    if (!check_detail_tracking_level(output())) {
+    return;
+  }
+    MemBaseline& baseline = MemTracker::get_baseline();
+    if (baseline.baseline_type() == MemBaseline::Detail_baselined) {
+      report_diff(false, scale_unit);
     } else {
-      output()->print_cr("No baseline to compare to, run 'baseline' command first");
+      output()->print_cr("No detail baseline for comparison");
     }
   } else if (_shutdown.value()) {
-    MemTracker::shutdown(MemTracker::NMT_shutdown_user);
-    output()->print_cr("Shutdown is in progress, it will take a few moments to " \
-      "completely shutdown");
-  } else if (_auto_shutdown.is_set()) {
-    MemTracker::set_autoShutdown(_auto_shutdown.value());
+    MemTracker::shutdown();
+    output()->print_cr("Native memory tracking has been turned off");
+  } else if (_statistics.value()) {
+    if (check_detail_tracking_level(output())) {
+      MemTracker::tuning_statistics(output());
+    }
   } else {
     ShouldNotReachHere();
     output()->print_cr("Unknown command");
@@ -181,3 +169,46 @@
   }
 }
 
+void NMTDCmd::report(bool summaryOnly, size_t scale_unit) {
+  MemBaseline baseline;
+  if (baseline.baseline(summaryOnly)) {
+    if (summaryOnly) {
+      MemSummaryReporter rpt(baseline, output(), scale_unit);
+      rpt.report();
+    } else {
+      MemDetailReporter rpt(baseline, output(), scale_unit);
+      rpt.report();
+    }
+  }
+}
+
+void NMTDCmd::report_diff(bool summaryOnly, size_t scale_unit) {
+  MemBaseline& early_baseline = MemTracker::get_baseline();
+  assert(early_baseline.baseline_type() != MemBaseline::Not_baselined,
+    "Not yet baselined");
+  assert(summaryOnly || early_baseline.baseline_type() == MemBaseline::Detail_baselined,
+    "Not a detail baseline");
+
+  MemBaseline baseline;
+  if (baseline.baseline(summaryOnly)) {
+    if (summaryOnly) {
+      MemSummaryDiffReporter rpt(early_baseline, baseline, output(), scale_unit);
+      rpt.report_diff();
+    } else {
+      MemDetailDiffReporter rpt(early_baseline, baseline, output(), scale_unit);
+      rpt.report_diff();
+    }
+  }
+}
+
+bool NMTDCmd::check_detail_tracking_level(outputStream* out) {
+  if (MemTracker::tracking_level() == NMT_detail) {
+    return true;
+  } else if (MemTracker::cmdline_tracking_level() == NMT_detail) {
+    out->print_cr("Tracking level has been downgraded due to lack of resources");
+    return false;
+  } else {
+    out->print_cr("Detail tracking is not enabled");
+    return false;
+  }
+}
diff --git a/hotspot/src/share/vm/services/nmtDCmd.hpp b/hotspot/src/share/vm/services/nmtDCmd.hpp
index 62872c6..df1ab36 100644
--- a/hotspot/src/share/vm/services/nmtDCmd.hpp
+++ b/hotspot/src/share/vm/services/nmtDCmd.hpp
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -25,8 +25,12 @@
 #ifndef SHARE_VM_SERVICES_NMT_DCMD_HPP
 #define SHARE_VM_SERVICES_NMT_DCMD_HPP
 
+#if INCLUDE_NMT
+
 #include "services/diagnosticArgument.hpp"
 #include "services/diagnosticFramework.hpp"
+#include "services/memBaseline.hpp"
+#include "services/mallocTracker.hpp"
 
 /**
  * Native memory tracking DCmd implementation
@@ -39,10 +43,7 @@
   DCmdArgument<bool>  _summary_diff;
   DCmdArgument<bool>  _detail_diff;
   DCmdArgument<bool>  _shutdown;
-  DCmdArgument<bool>  _auto_shutdown;
-#ifndef PRODUCT
-  DCmdArgument<bool>  _debug;
-#endif
+  DCmdArgument<bool>  _statistics;
   DCmdArgument<char*> _scale;
 
  public:
@@ -61,6 +62,17 @@
   }
   static int num_arguments();
   virtual void execute(DCmdSource source, TRAPS);
+
+ private:
+  void report(bool summaryOnly, size_t scale);
+  void report_diff(bool summaryOnly, size_t scale);
+
+  size_t get_scale(const char* scale) const;
+
+  // check if NMT running at detail tracking level
+  bool check_detail_tracking_level(outputStream* out);
 };
 
+#endif // INCLUDE_NMT
+
 #endif // SHARE_VM_SERVICES_NMT_DCMD_HPP
diff --git a/hotspot/src/share/vm/services/threadService.cpp b/hotspot/src/share/vm/services/threadService.cpp
index 3376aba..02156a2 100644
--- a/hotspot/src/share/vm/services/threadService.cpp
+++ b/hotspot/src/share/vm/services/threadService.cpp
@@ -33,6 +33,7 @@
 #include "runtime/init.hpp"
 #include "runtime/thread.hpp"
 #include "runtime/vframe.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/threadService.hpp"
diff --git a/hotspot/src/share/vm/services/virtualMemoryTracker.cpp b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp
new file mode 100644
index 0000000..20c4536
--- /dev/null
+++ b/hotspot/src/share/vm/services/virtualMemoryTracker.cpp
@@ -0,0 +1,475 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ */
+#include "precompiled.hpp"
+
+#include "runtime/threadCritical.hpp"
+#include "services/virtualMemoryTracker.hpp"
+
+size_t VirtualMemorySummary::_snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)];
+
+void VirtualMemorySummary::initialize() {
+  assert(sizeof(_snapshot) >= sizeof(VirtualMemorySnapshot), "Sanity Check");
+  // Use placement operator new to initialize static data area.
+  ::new ((void*)_snapshot) VirtualMemorySnapshot();
+}
+
+SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* VirtualMemoryTracker::_reserved_regions;
+
+int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) {
+  return r1.compare(r2);
+}
+
+int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2) {
+  return r1.compare(r2);
+}
+
+bool ReservedMemoryRegion::add_committed_region(address addr, size_t size, const NativeCallStack& stack) {
+  assert(addr != NULL, "Invalid address");
+  assert(size > 0, "Invalid size");
+  assert(contain_region(addr, size), "Not contain this region");
+
+  if (all_committed()) return true;
+
+  CommittedMemoryRegion committed_rgn(addr, size, stack);
+  LinkedListNode<CommittedMemoryRegion>* node = _committed_regions.find_node(committed_rgn);
+  if (node != NULL) {
+    CommittedMemoryRegion* rgn = node->data();
+    if (rgn->same_region(addr, size)) {
+      return true;
+    }
+
+    if (rgn->adjacent_to(addr, size)) {
+      // check if the next region covers this committed region,
+      // the regions may not be merged due to different call stacks
+      LinkedListNode<CommittedMemoryRegion>* next =
+        node->next();
+      if (next != NULL && next->data()->contain_region(addr, size)) {
+        if (next->data()->same_region(addr, size)) {
+          next->data()->set_call_stack(stack);
+        }
+        return true;
+      }
+      if (rgn->call_stack()->equals(stack)) {
+        VirtualMemorySummary::record_uncommitted_memory(rgn->size(), flag());
+        // the two adjacent regions have the same call stack, merge them
+        rgn->expand_region(addr, size);
+        VirtualMemorySummary::record_committed_memory(rgn->size(), flag());
+        return true;
+      }
+      VirtualMemorySummary::record_committed_memory(size, flag());
+      if (rgn->base() > addr) {
+        return _committed_regions.insert_before(committed_rgn, node) != NULL;
+      } else {
+        return _committed_regions.insert_after(committed_rgn, node) != NULL;
+      }
+    }
+    assert(rgn->contain_region(addr, size), "Must cover this region");
+    return true;
+  } else {
+    // New committed region
+    VirtualMemorySummary::record_committed_memory(size, flag());
+    return add_committed_region(committed_rgn);
+  }
+}
+
+void ReservedMemoryRegion::set_all_committed(bool b) {
+  if (all_committed() != b) {
+    _all_committed = b;
+    if (b) {
+      VirtualMemorySummary::record_committed_memory(size(), flag());
+    }
+  }
+}
+
+bool ReservedMemoryRegion::remove_uncommitted_region(LinkedListNode<CommittedMemoryRegion>* node,
+  address addr, size_t size) {
+  assert(addr != NULL, "Invalid address");
+  assert(size > 0, "Invalid size");
+
+  CommittedMemoryRegion* rgn = node->data();
+  assert(rgn->contain_region(addr, size), "Has to be contained");
+  assert(!rgn->same_region(addr, size), "Can not be the same region");
+
+  if (rgn->base() == addr ||
+      rgn->end() == addr + size) {
+    rgn->exclude_region(addr, size);
+    return true;
+  } else {
+    // split this region
+    address top =rgn->end();
+    // use this region for lower part
+    size_t exclude_size = rgn->end() - addr;
+    rgn->exclude_region(addr, exclude_size);
+
+    // higher part
+    address high_base = addr + size;
+    size_t  high_size = top - high_base;
+
+    CommittedMemoryRegion high_rgn(high_base, high_size, *rgn->call_stack());
+    LinkedListNode<CommittedMemoryRegion>* high_node = _committed_regions.add(high_rgn);
+    assert(high_node == NULL || node->next() == high_node, "Should be right after");
+    return (high_node != NULL);
+  }
+
+  return false;
+}
+
+bool ReservedMemoryRegion::remove_uncommitted_region(address addr, size_t sz) {
+  // uncommit stack guard pages
+  if (flag() == mtThreadStack && !same_region(addr, sz)) {
+    return true;
+  }
+
+  assert(addr != NULL, "Invalid address");
+  assert(sz > 0, "Invalid size");
+
+  if (all_committed()) {
+    assert(_committed_regions.is_empty(), "Sanity check");
+    assert(contain_region(addr, sz), "Reserved region does not contain this region");
+    set_all_committed(false);
+    VirtualMemorySummary::record_uncommitted_memory(sz, flag());
+    if (same_region(addr, sz)) {
+      return true;
+    } else {
+      CommittedMemoryRegion rgn(base(), size(), *call_stack());
+      if (rgn.base() == addr || rgn.end() == (addr + sz)) {
+        rgn.exclude_region(addr, sz);
+        return add_committed_region(rgn);
+      } else {
+        // split this region
+        // top of the whole region
+        address top =rgn.end();
+        // use this region for lower part
+        size_t exclude_size = rgn.end() - addr;
+        rgn.exclude_region(addr, exclude_size);
+        if (add_committed_region(rgn)) {
+          // higher part
+          address high_base = addr + sz;
+          size_t  high_size = top - high_base;
+          CommittedMemoryRegion high_rgn(high_base, high_size, NativeCallStack::EMPTY_STACK);
+          return add_committed_region(high_rgn);
+        } else {
+          return false;
+        }
+      }
+    }
+  } else {
+    // we have to walk whole list to remove the committed regions in
+    // specified range
+    LinkedListNode<CommittedMemoryRegion>* head =
+      _committed_regions.head();
+    LinkedListNode<CommittedMemoryRegion>* prev = NULL;
+    VirtualMemoryRegion uncommitted_rgn(addr, sz);
+
+    while (head != NULL && !uncommitted_rgn.is_empty()) {
+      CommittedMemoryRegion* crgn = head->data();
+      // this committed region overlaps to region to uncommit
+      if (crgn->overlap_region(uncommitted_rgn.base(), uncommitted_rgn.size())) {
+        if (crgn->same_region(uncommitted_rgn.base(), uncommitted_rgn.size())) {
+          // find matched region, remove the node will do
+          VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag());
+          _committed_regions.remove_after(prev);
+          return true;
+        } else if (crgn->contain_region(uncommitted_rgn.base(), uncommitted_rgn.size())) {
+          // this committed region contains whole uncommitted region
+          VirtualMemorySummary::record_uncommitted_memory(uncommitted_rgn.size(), flag());
+          return remove_uncommitted_region(head, uncommitted_rgn.base(), uncommitted_rgn.size());
+        } else if (uncommitted_rgn.contain_region(crgn->base(), crgn->size())) {
+          // this committed region has been uncommitted
+          size_t exclude_size = crgn->end() - uncommitted_rgn.base();
+          uncommitted_rgn.exclude_region(uncommitted_rgn.base(), exclude_size);
+          VirtualMemorySummary::record_uncommitted_memory(crgn->size(), flag());
+          LinkedListNode<CommittedMemoryRegion>* tmp = head;
+          head = head->next();
+          _committed_regions.remove_after(prev);
+          continue;
+        } else if (crgn->contain_address(uncommitted_rgn.base())) {
+          size_t toUncommitted = crgn->end() - uncommitted_rgn.base();
+          crgn->exclude_region(uncommitted_rgn.base(), toUncommitted);
+          uncommitted_rgn.exclude_region(uncommitted_rgn.base(), toUncommitted);
+          VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag());
+        } else if (uncommitted_rgn.contain_address(crgn->base())) {
+          size_t toUncommitted = uncommitted_rgn.end() - crgn->base();
+          crgn->exclude_region(crgn->base(), toUncommitted);
+          uncommitted_rgn.exclude_region(uncommitted_rgn.end() - toUncommitted,
+            toUncommitted);
+          VirtualMemorySummary::record_uncommitted_memory(toUncommitted, flag());
+        }
+      }
+      prev = head;
+      head = head->next();
+    }
+  }
+
+  return true;
+}
+
+void ReservedMemoryRegion::move_committed_regions(address addr, ReservedMemoryRegion& rgn) {
+  assert(addr != NULL, "Invalid address");
+
+  // split committed regions
+  LinkedListNode<CommittedMemoryRegion>* head =
+    _committed_regions.head();
+  LinkedListNode<CommittedMemoryRegion>* prev = NULL;
+
+  while (head != NULL) {
+    if (head->data()->base() >= addr) {
+      break;
+    }
+    prev = head;
+    head = head->next();
+  }
+
+  if (head != NULL) {
+    if (prev != NULL) {
+      prev->set_next(head->next());
+    } else {
+      _committed_regions.set_head(NULL);
+    }
+  }
+
+  rgn._committed_regions.set_head(head);
+}
+
+size_t ReservedMemoryRegion::committed_size() const {
+  if (all_committed()) {
+    return size();
+  } else {
+    size_t committed = 0;
+    LinkedListNode<CommittedMemoryRegion>* head =
+      _committed_regions.head();
+    while (head != NULL) {
+      committed += head->data()->size();
+      head = head->next();
+    }
+    return committed;
+  }
+}
+
+void ReservedMemoryRegion::set_flag(MEMFLAGS f) {
+  assert((flag() == mtNone || flag() == f), "Overwrite memory type");
+  if (flag() != f) {
+    VirtualMemorySummary::move_reserved_memory(flag(), f, size());
+    VirtualMemorySummary::move_committed_memory(flag(), f, committed_size());
+    _flag = f;
+  }
+}
+
+bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) {
+  if (level >= NMT_summary) {
+    VirtualMemorySummary::initialize();
+  }
+  return true;
+}
+
+bool VirtualMemoryTracker::late_initialize(NMT_TrackingLevel level) {
+  if (level >= NMT_summary) {
+    _reserved_regions = new (std::nothrow, ResourceObj::C_HEAP, mtNMT)
+      SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>();
+    return (_reserved_regions != NULL);
+  }
+  return true;
+}
+
+bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
+   const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
+  assert(base_addr != NULL, "Invalid address");
+  assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
+  ReservedMemoryRegion  rgn(base_addr, size, stack, flag);
+  ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
+  LinkedListNode<ReservedMemoryRegion>* node;
+  if (reserved_rgn == NULL) {
+    VirtualMemorySummary::record_reserved_memory(size, flag);
+    node = _reserved_regions->add(rgn);
+    if (node != NULL) {
+      node->data()->set_all_committed(all_committed);
+      return true;
+    } else {
+      return false;
+    }
+  } else {
+    if (reserved_rgn->same_region(base_addr, size)) {
+      reserved_rgn->set_call_stack(stack);
+      reserved_rgn->set_flag(flag);
+      return true;
+    } else if (reserved_rgn->adjacent_to(base_addr, size)) {
+      VirtualMemorySummary::record_reserved_memory(size, flag);
+      reserved_rgn->expand_region(base_addr, size);
+      reserved_rgn->set_call_stack(stack);
+      return true;
+    } else {
+      // Overlapped reservation.
+      // It can happen when the regions are thread stacks, as JNI
+      // thread does not detach from VM before exits, and leads to
+      // leak JavaThread object
+      if (reserved_rgn->flag() == mtThreadStack) {
+        guarantee(!CheckJNICalls, "Attached JNI thread exited without being detached");
+        // Overwrite with new region
+
+        // Release old region
+        VirtualMemorySummary::record_uncommitted_memory(reserved_rgn->committed_size(), reserved_rgn->flag());
+        VirtualMemorySummary::record_released_memory(reserved_rgn->size(), reserved_rgn->flag());
+
+        // Add new region
+        VirtualMemorySummary::record_reserved_memory(rgn.size(), flag);
+
+        *reserved_rgn = rgn;
+        return true;
+      }
+
+      // CDS mapping region.
+      // CDS reserves the whole region for mapping CDS archive, then maps each section into the region.
+      // NMT reports CDS as a whole.
+      if (reserved_rgn->flag() == mtClassShared) {
+        assert(reserved_rgn->contain_region(base_addr, size), "Reserved CDS region should contain this mapping region");
+        return true;
+      }
+
+      ShouldNotReachHere();
+      return false;
+    }
+  }
+}
+
+void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) {
+  assert(addr != NULL, "Invalid address");
+  assert(_reserved_regions != NULL, "Sanity check");
+
+  ReservedMemoryRegion   rgn(addr, 1);
+  ReservedMemoryRegion*  reserved_rgn = _reserved_regions->find(rgn);
+  if (reserved_rgn != NULL) {
+    assert(reserved_rgn->contain_address(addr), "Containment");
+    if (reserved_rgn->flag() != flag) {
+      assert(reserved_rgn->flag() == mtNone, "Overwrite memory type");
+      reserved_rgn->set_flag(flag);
+    }
+  }
+}
+
+bool VirtualMemoryTracker::add_committed_region(address addr, size_t size,
+  const NativeCallStack& stack) {
+  assert(addr != NULL, "Invalid address");
+  assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
+
+  ReservedMemoryRegion  rgn(addr, size);
+  ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
+
+  assert(reserved_rgn != NULL, "No reserved region");
+  assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
+  return reserved_rgn->add_committed_region(addr, size, stack);
+}
+
+bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) {
+  assert(addr != NULL, "Invalid address");
+  assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
+
+  ReservedMemoryRegion  rgn(addr, size);
+  ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
+  assert(reserved_rgn != NULL, "No reserved region");
+  assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
+  return reserved_rgn->remove_uncommitted_region(addr, size);
+}
+
+bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
+  assert(addr != NULL, "Invalid address");
+  assert(size > 0, "Invalid size");
+  assert(_reserved_regions != NULL, "Sanity check");
+
+  ReservedMemoryRegion  rgn(addr, size);
+  ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
+
+  assert(reserved_rgn != NULL, "No reserved region");
+
+  // uncommit regions within the released region
+  if (!reserved_rgn->remove_uncommitted_region(addr, size)) {
+    return false;
+  }
+
+
+  VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag());
+
+  if (reserved_rgn->same_region(addr, size)) {
+    return _reserved_regions->remove(rgn);
+  } else {
+    assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
+    if (reserved_rgn->base() == addr ||
+        reserved_rgn->end() == addr + size) {
+        reserved_rgn->exclude_region(addr, size);
+      return true;
+    } else {
+      address top = reserved_rgn->end();
+      address high_base = addr + size;
+      ReservedMemoryRegion high_rgn(high_base, top - high_base,
+        *reserved_rgn->call_stack(), reserved_rgn->flag());
+
+      // use original region for lower region
+      reserved_rgn->exclude_region(addr, top - addr);
+      LinkedListNode<ReservedMemoryRegion>* new_rgn = _reserved_regions->add(high_rgn);
+      if (new_rgn == NULL) {
+        return false;
+      } else {
+        reserved_rgn->move_committed_regions(addr, *new_rgn->data());
+        return true;
+      }
+    }
+  }
+}
+
+
+bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
+  assert(_reserved_regions != NULL, "Sanity check");
+  ThreadCritical tc;
+  LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions->head();
+  while (head != NULL) {
+    const ReservedMemoryRegion* rgn = head->peek();
+    if (!walker->do_allocation_site(rgn)) {
+      return false;
+    }
+    head = head->next();
+  }
+  return true;
+}
+
+// Transition virtual memory tracking level.
+bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel to) {
+  if (from == NMT_minimal) {
+    assert(to == NMT_summary || to == NMT_detail, "Just check");
+    VirtualMemorySummary::reset();
+  } else if (to == NMT_minimal) {
+    assert(from == NMT_summary || from == NMT_detail, "Just check");
+    // Clean up virtual memory tracking data structures.
+    ThreadCritical tc;
+    if (_reserved_regions != NULL) {
+      delete _reserved_regions;
+      _reserved_regions = NULL;
+    }
+  }
+
+  return true;
+}
+
+
diff --git a/hotspot/src/share/vm/services/virtualMemoryTracker.hpp b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp
new file mode 100644
index 0000000..bdb686c
--- /dev/null
+++ b/hotspot/src/share/vm/services/virtualMemoryTracker.hpp
@@ -0,0 +1,440 @@
+/*
+ * Copyright (c) 2013, 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.
+ *
+ */
+
+#ifndef SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP
+#define SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP
+
+#if INCLUDE_NMT
+
+#include "memory/allocation.hpp"
+#include "services/allocationSite.hpp"
+#include "services/nmtCommon.hpp"
+#include "utilities/linkedlist.hpp"
+#include "utilities/nativeCallStack.hpp"
+#include "utilities/ostream.hpp"
+
+
+/*
+ * Virtual memory counter
+ */
+class VirtualMemory VALUE_OBJ_CLASS_SPEC {
+ private:
+  size_t     _reserved;
+  size_t     _committed;
+
+ public:
+  VirtualMemory() : _reserved(0), _committed(0) { }
+
+  inline void reserve_memory(size_t sz) { _reserved += sz; }
+  inline void commit_memory (size_t sz) {
+    _committed += sz;
+    assert(_committed <= _reserved, "Sanity check");
+  }
+
+  inline void release_memory (size_t sz) {
+    assert(_reserved >= sz, "Negative amount");
+    _reserved -= sz;
+  }
+
+  inline void uncommit_memory(size_t sz) {
+    assert(_committed >= sz, "Negative amount");
+    _committed -= sz;
+  }
+
+  void reset() {
+    _reserved  = 0;
+    _committed = 0;
+  }
+
+  inline size_t reserved()  const { return _reserved;  }
+  inline size_t committed() const { return _committed; }
+};
+
+// Virtual memory allocation site, keeps track where the virtual memory is reserved.
+class VirtualMemoryAllocationSite : public AllocationSite<VirtualMemory> {
+ public:
+  VirtualMemoryAllocationSite(const NativeCallStack& stack) :
+    AllocationSite<VirtualMemory>(stack) { }
+
+  inline void reserve_memory(size_t sz)  { data()->reserve_memory(sz);  }
+  inline void commit_memory (size_t sz)  { data()->commit_memory(sz);   }
+  inline void uncommit_memory(size_t sz) { data()->uncommit_memory(sz); }
+  inline void release_memory(size_t sz)  { data()->release_memory(sz);  }
+  inline size_t reserved() const  { return peek()->reserved(); }
+  inline size_t committed() const { return peek()->committed(); }
+};
+
+class VirtualMemorySummary;
+
+// This class represents a snapshot of virtual memory at a given time.
+// The latest snapshot is saved in a static area.
+class VirtualMemorySnapshot : public ResourceObj {
+  friend class VirtualMemorySummary;
+
+ private:
+  VirtualMemory  _virtual_memory[mt_number_of_types];
+
+ public:
+  inline VirtualMemory* by_type(MEMFLAGS flag) {
+    int index = NMTUtil::flag_to_index(flag);
+    return &_virtual_memory[index];
+  }
+
+  inline VirtualMemory* by_index(int index) {
+    assert(index >= 0, "Index out of bound");
+    assert(index < mt_number_of_types, "Index out of bound");
+    return &_virtual_memory[index];
+  }
+
+  inline size_t total_reserved() const {
+    size_t amount = 0;
+    for (int index = 0; index < mt_number_of_types; index ++) {
+      amount += _virtual_memory[index].reserved();
+    }
+    return amount;
+  }
+
+  inline size_t total_committed() const {
+    size_t amount = 0;
+    for (int index = 0; index < mt_number_of_types; index ++) {
+      amount += _virtual_memory[index].committed();
+    }
+    return amount;
+  }
+
+  inline void reset() {
+    for (int index = 0; index < mt_number_of_types; index ++) {
+      _virtual_memory[index].reset();
+    }
+  }
+
+  void copy_to(VirtualMemorySnapshot* s) {
+    for (int index = 0; index < mt_number_of_types; index ++) {
+      s->_virtual_memory[index] = _virtual_memory[index];
+    }
+  }
+};
+
+class VirtualMemorySummary : AllStatic {
+ public:
+  static void initialize();
+
+  static inline void record_reserved_memory(size_t size, MEMFLAGS flag) {
+    as_snapshot()->by_type(flag)->reserve_memory(size);
+  }
+
+  static inline void record_committed_memory(size_t size, MEMFLAGS flag) {
+    as_snapshot()->by_type(flag)->commit_memory(size);
+  }
+
+  static inline void record_uncommitted_memory(size_t size, MEMFLAGS flag) {
+    as_snapshot()->by_type(flag)->uncommit_memory(size);
+  }
+
+  static inline void record_released_memory(size_t size, MEMFLAGS flag) {
+    as_snapshot()->by_type(flag)->release_memory(size);
+  }
+
+  // Move virtual memory from one memory type to another.
+  // Virtual memory can be reserved before it is associated with a memory type, and tagged
+  // as 'unknown'. Once the memory is tagged, the virtual memory will be moved from 'unknown'
+  // type to specified memory type.
+  static inline void move_reserved_memory(MEMFLAGS from, MEMFLAGS to, size_t size) {
+    as_snapshot()->by_type(from)->release_memory(size);
+    as_snapshot()->by_type(to)->reserve_memory(size);
+  }
+
+  static inline void move_committed_memory(MEMFLAGS from, MEMFLAGS to, size_t size) {
+    as_snapshot()->by_type(from)->uncommit_memory(size);
+    as_snapshot()->by_type(to)->commit_memory(size);
+  }
+
+  static inline void snapshot(VirtualMemorySnapshot* s) {
+    as_snapshot()->copy_to(s);
+  }
+
+  static inline void reset() {
+    as_snapshot()->reset();
+  }
+
+  static VirtualMemorySnapshot* as_snapshot() {
+    return (VirtualMemorySnapshot*)_snapshot;
+  }
+
+ private:
+  static size_t _snapshot[CALC_OBJ_SIZE_IN_TYPE(VirtualMemorySnapshot, size_t)];
+};
+
+
+
+/*
+ * A virtual memory region
+ */
+class VirtualMemoryRegion VALUE_OBJ_CLASS_SPEC {
+ private:
+  address      _base_address;
+  size_t       _size;
+
+ public:
+  VirtualMemoryRegion(address addr, size_t size) :
+    _base_address(addr), _size(size) {
+     assert(addr != NULL, "Invalid address");
+     assert(size > 0, "Invalid size");
+   }
+
+  inline address base() const { return _base_address;   }
+  inline address end()  const { return base() + size(); }
+  inline size_t  size() const { return _size;           }
+
+  inline bool is_empty() const { return size() == 0; }
+
+  inline bool contain_address(address addr) const {
+    return (addr >= base() && addr < end());
+  }
+
+
+  inline bool contain_region(address addr, size_t size) const {
+    return contain_address(addr) && contain_address(addr + size - 1);
+  }
+
+  inline bool same_region(address addr, size_t sz) const {
+    return (addr == base() && sz == size());
+  }
+
+
+  inline bool overlap_region(address addr, size_t sz) const {
+    VirtualMemoryRegion rgn(addr, sz);
+    return contain_address(addr) ||
+           contain_address(addr + sz - 1) ||
+           rgn.contain_address(base()) ||
+           rgn.contain_address(end() - 1);
+  }
+
+  inline bool adjacent_to(address addr, size_t sz) const {
+    return (addr == end() || (addr + sz) == base());
+  }
+
+  void exclude_region(address addr, size_t sz) {
+    assert(contain_region(addr, sz), "Not containment");
+    assert(addr == base() || addr + sz == end(), "Can not exclude from middle");
+    size_t new_size = size() - sz;
+
+    if (addr == base()) {
+      set_base(addr + sz);
+    }
+    set_size(new_size);
+  }
+
+  void expand_region(address addr, size_t sz) {
+    assert(adjacent_to(addr, sz), "Not adjacent regions");
+    if (base() == addr + sz) {
+      set_base(addr);
+    }
+    set_size(size() + sz);
+  }
+
+ protected:
+  void set_base(address base) {
+    assert(base != NULL, "Sanity check");
+    _base_address = base;
+  }
+
+  void set_size(size_t  size) {
+    assert(size > 0, "Sanity check");
+    _size = size;
+  }
+};
+
+
+class CommittedMemoryRegion : public VirtualMemoryRegion {
+ private:
+  NativeCallStack  _stack;
+
+ public:
+  CommittedMemoryRegion(address addr, size_t size, const NativeCallStack& stack) :
+    VirtualMemoryRegion(addr, size), _stack(stack) { }
+
+  inline int compare(const CommittedMemoryRegion& rgn) const {
+    if (overlap_region(rgn.base(), rgn.size()) ||
+        adjacent_to   (rgn.base(), rgn.size())) {
+      return 0;
+    } else {
+      if (base() == rgn.base()) {
+        return 0;
+      } else if (base() > rgn.base()) {
+        return 1;
+      } else {
+        return -1;
+      }
+    }
+  }
+
+  inline bool equals(const CommittedMemoryRegion& rgn) const {
+    return compare(rgn) == 0;
+  }
+
+  inline void set_call_stack(const NativeCallStack& stack) { _stack = stack; }
+  inline const NativeCallStack* call_stack() const         { return &_stack; }
+};
+
+
+typedef LinkedListIterator<CommittedMemoryRegion> CommittedRegionIterator;
+
+int compare_committed_region(const CommittedMemoryRegion&, const CommittedMemoryRegion&);
+class ReservedMemoryRegion : public VirtualMemoryRegion {
+ private:
+  SortedLinkedList<CommittedMemoryRegion, compare_committed_region>
+    _committed_regions;
+
+  NativeCallStack  _stack;
+  MEMFLAGS         _flag;
+
+  bool             _all_committed;
+
+ public:
+  ReservedMemoryRegion(address base, size_t size, const NativeCallStack& stack,
+    MEMFLAGS flag = mtNone) :
+    VirtualMemoryRegion(base, size), _stack(stack), _flag(flag),
+    _all_committed(false) { }
+
+
+  ReservedMemoryRegion(address base, size_t size) :
+    VirtualMemoryRegion(base, size), _stack(NativeCallStack::EMPTY_STACK), _flag(mtNone),
+    _all_committed(false) { }
+
+  // Copy constructor
+  ReservedMemoryRegion(const ReservedMemoryRegion& rr) :
+    VirtualMemoryRegion(rr.base(), rr.size()) {
+    *this = rr;
+  }
+
+  inline void  set_call_stack(const NativeCallStack& stack) { _stack = stack; }
+  inline const NativeCallStack* call_stack() const          { return &_stack;  }
+
+  void  set_flag(MEMFLAGS flag);
+  inline MEMFLAGS flag() const            { return _flag;  }
+
+  inline int compare(const ReservedMemoryRegion& rgn) const {
+    if (overlap_region(rgn.base(), rgn.size())) {
+      return 0;
+    } else {
+      if (base() == rgn.base()) {
+        return 0;
+      } else if (base() > rgn.base()) {
+        return 1;
+      } else {
+        return -1;
+      }
+    }
+  }
+
+  inline bool equals(const ReservedMemoryRegion& rgn) const {
+    return compare(rgn) == 0;
+  }
+
+  bool    add_committed_region(address addr, size_t size, const NativeCallStack& stack);
+  bool    remove_uncommitted_region(address addr, size_t size);
+
+  size_t  committed_size() const;
+
+  // move committed regions that higher than specified address to
+  // the new region
+  void    move_committed_regions(address addr, ReservedMemoryRegion& rgn);
+
+  inline bool all_committed() const { return _all_committed; }
+  void        set_all_committed(bool b);
+
+  CommittedRegionIterator iterate_committed_regions() const {
+    return CommittedRegionIterator(_committed_regions.head());
+  }
+
+  ReservedMemoryRegion& operator= (const ReservedMemoryRegion& other) {
+    set_base(other.base());
+    set_size(other.size());
+
+    _stack =         *other.call_stack();
+    _flag  =         other.flag();
+    _all_committed = other.all_committed();
+    if (other.all_committed()) {
+      set_all_committed(true);
+    } else {
+      CommittedRegionIterator itr = other.iterate_committed_regions();
+      const CommittedMemoryRegion* rgn = itr.next();
+      while (rgn != NULL) {
+        _committed_regions.add(*rgn);
+        rgn = itr.next();
+      }
+    }
+    return *this;
+  }
+
+ private:
+  // The committed region contains the uncommitted region, subtract the uncommitted
+  // region from this committed region
+  bool remove_uncommitted_region(LinkedListNode<CommittedMemoryRegion>* node,
+    address addr, size_t sz);
+
+  bool add_committed_region(const CommittedMemoryRegion& rgn) {
+    assert(rgn.base() != NULL, "Invalid base address");
+    assert(size() > 0, "Invalid size");
+    return _committed_regions.add(rgn) != NULL;
+  }
+};
+
+int compare_reserved_region_base(const ReservedMemoryRegion& r1, const ReservedMemoryRegion& r2);
+
+class VirtualMemoryWalker : public StackObj {
+ public:
+   virtual bool do_allocation_site(const ReservedMemoryRegion* rgn) { return false; }
+};
+
+// Main class called from MemTracker to track virtual memory allocations, commits and releases.
+class VirtualMemoryTracker : AllStatic {
+ public:
+  static bool initialize(NMT_TrackingLevel level);
+
+  // Late phase initialization
+  static bool late_initialize(NMT_TrackingLevel level);
+
+  static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack,
+    MEMFLAGS flag = mtNone, bool all_committed = false);
+
+  static bool add_committed_region      (address base_addr, size_t size, const NativeCallStack& stack);
+  static bool remove_uncommitted_region (address base_addr, size_t size);
+  static bool remove_released_region    (address base_addr, size_t size);
+  static void set_reserved_region_type  (address addr, MEMFLAGS flag);
+
+  // Walk virtual memory data structure for creating baseline, etc.
+  static bool walk_virtual_memory(VirtualMemoryWalker* walker);
+
+  static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
+
+ private:
+  static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* _reserved_regions;
+};
+
+
+#endif // INCLUDE_NMT
+
+#endif // SHARE_VM_SERVICES_VIRTUAL_MEMORY_TRACKER_HPP
diff --git a/hotspot/src/share/vm/trace/tracetypes.xml b/hotspot/src/share/vm/trace/tracetypes.xml
index eb1c708..f41dfc0 100644
--- a/hotspot/src/share/vm/trace/tracetypes.xml
+++ b/hotspot/src/share/vm/trace/tracetypes.xml
@@ -98,6 +98,7 @@
       <value type="SYMBOL" field="name" label="Name"/>
       <value type="SYMBOL" field="signature" label="Signature"/>
       <value type="SHORT" field="modifiers" label="Access modifiers"/>
+      <value type="BOOLEAN" field="hidden" label="Hidden"/>
     </content_type>
 
     <content_type id="UTFConstant" hr_name="UTF constant"
diff --git a/hotspot/src/share/vm/utilities/array.hpp b/hotspot/src/share/vm/utilities/array.hpp
index 40b3b01..b7ce8e7 100644
--- a/hotspot/src/share/vm/utilities/array.hpp
+++ b/hotspot/src/share/vm/utilities/array.hpp
@@ -28,6 +28,7 @@
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "memory/metaspace.hpp"
+#include "runtime/orderAccess.hpp"
 
 // correct linkage required to compile w/o warnings
 // (must be on file level - cannot be local)
@@ -304,6 +305,7 @@
   friend class MetadataFactory;
   friend class VMStructs;
   friend class MethodHandleCompiler;           // special case
+  friend class WhiteBox;
 protected:
   int _length;                                 // the number of array elements
   T   _data[1];                                // the array memory
@@ -325,6 +327,31 @@
 
   static size_t byte_sizeof(int length) { return sizeof(Array<T>) + MAX2(length - 1, 0) * sizeof(T); }
 
+  // WhiteBox API helper.
+  // Can't distinguish between array of length 0 and length 1,
+  // will always return 0 in those cases.
+  static int bytes_to_length(size_t bytes)       {
+    assert(is_size_aligned(bytes, BytesPerWord), "Must be, for now");
+
+    if (sizeof(Array<T>) >= bytes) {
+      return 0;
+    }
+
+    size_t left = bytes - sizeof(Array<T>);
+    assert(is_size_aligned(left, sizeof(T)), "Must be");
+
+    size_t elements = left / sizeof(T);
+    assert(elements <= (size_t)INT_MAX, err_msg("number of elements " SIZE_FORMAT "doesn't fit into an int.", elements));
+
+    int length = (int)elements;
+
+    assert((size_t)size(length) * BytesPerWord == bytes,
+        err_msg("Expected: " SIZE_FORMAT " got: " SIZE_FORMAT,
+                bytes, (size_t)size(length) * BytesPerWord));
+
+    return length;
+  }
+
   explicit Array(int length) : _length(length) {
     assert(length >= 0, "illegal length");
   }
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions.hpp b/hotspot/src/share/vm/utilities/globalDefinitions.hpp
index 5a4bd19..a2d8278 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions.hpp
@@ -558,6 +558,27 @@
   return fabs(value);
 }
 
+//----------------------------------------------------------------------------------------------------
+// Special casts
+// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
+typedef union {
+  jfloat f;
+  jint i;
+} FloatIntConv;
+
+typedef union {
+  jdouble d;
+  jlong l;
+  julong ul;
+} DoubleLongConv;
+
+inline jint    jint_cast    (jfloat  x)  { return ((FloatIntConv*)&x)->i; }
+inline jfloat  jfloat_cast  (jint    x)  { return ((FloatIntConv*)&x)->f; }
+
+inline jlong   jlong_cast   (jdouble x)  { return ((DoubleLongConv*)&x)->l;  }
+inline julong  julong_cast  (jdouble x)  { return ((DoubleLongConv*)&x)->ul; }
+inline jdouble jdouble_cast (jlong   x)  { return ((DoubleLongConv*)&x)->d;  }
+
 inline jint low (jlong value)                    { return jint(value); }
 inline jint high(jlong value)                    { return jint(value >> 32); }
 
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp
index 22e5d27..576b023 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_gcc.hpp
@@ -167,17 +167,6 @@
 typedef uint32_t juint;
 typedef uint64_t julong;
 
-//----------------------------------------------------------------------------------------------------
-// Special (possibly not-portable) casts
-// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
-// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar
-
-inline jint    jint_cast   (jfloat  x)           { return *(jint*   )&x; }
-inline jlong   jlong_cast  (jdouble x)           { return *(jlong*  )&x; }
-inline julong  julong_cast (jdouble x)           { return *(julong* )&x; }
-
-inline jfloat  jfloat_cast (jint    x)           { return *(jfloat* )&x; }
-inline jdouble jdouble_cast(jlong   x)           { return *(jdouble*)&x; }
 
 //----------------------------------------------------------------------------------------------------
 // Constant for jlong (specifying an long long canstant is C++ compiler specific)
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
index e91e607..b64bbf8 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_sparcWorks.hpp
@@ -183,15 +183,6 @@
 typedef unsigned int       juint;
 typedef unsigned long long julong;
 
-//----------------------------------------------------------------------------------------------------
-// Special (possibly not-portable) casts
-// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
-
-inline jint    jint_cast   (jfloat  x)           { return *(jint*   )&x; }
-inline jlong   jlong_cast  (jdouble x)           { return *(jlong*  )&x; }
-
-inline jfloat  jfloat_cast (jint    x)           { return *(jfloat* )&x; }
-inline jdouble jdouble_cast(jlong   x)           { return *(jdouble*)&x; }
 
 //----------------------------------------------------------------------------------------------------
 // Constant for jlong (specifying an long long constant is C++ compiler specific)
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
index db22cc8..46e8f9e 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp
@@ -116,16 +116,6 @@
 typedef unsigned int     juint;
 typedef unsigned __int64 julong;
 
-//----------------------------------------------------------------------------------------------------
-// Special (possibly not-portable) casts
-// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
-
-inline jint    jint_cast   (jfloat  x)           { return *(jint*   )&x; }
-inline jlong   jlong_cast  (jdouble x)           { return *(jlong*  )&x; }
-
-inline jfloat  jfloat_cast (jint    x)           { return *(jfloat* )&x; }
-inline jdouble jdouble_cast(jlong   x)           { return *(jdouble*)&x; }
-
 
 //----------------------------------------------------------------------------------------------------
 // Non-standard stdlib-like stuff:
diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp
index 8a34006..ad71883 100644
--- a/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp
+++ b/hotspot/src/share/vm/utilities/globalDefinitions_xlc.hpp
@@ -114,16 +114,6 @@
 typedef uint32_t juint;
 typedef uint64_t julong;
 
-//----------------------------------------------------------------------------------------------------
-// Special (possibly not-portable) casts
-// Cast floats into same-size integers and vice-versa w/o changing bit-pattern
-// %%%%%% These seem like standard C++ to me--how about factoring them out? - Ungar
-
-inline jint    jint_cast   (jfloat  x)           { return *(jint*   )&x; }
-inline jlong   jlong_cast  (jdouble x)           { return *(jlong*  )&x; }
-
-inline jfloat  jfloat_cast (jint    x)           { return *(jfloat* )&x; }
-inline jdouble jdouble_cast(jlong   x)           { return *(jdouble*)&x; }
 
 //----------------------------------------------------------------------------------------------------
 // Constant for jlong (specifying an long long canstant is C++ compiler specific)
diff --git a/hotspot/src/share/vm/utilities/growableArray.hpp b/hotspot/src/share/vm/utilities/growableArray.hpp
index 7eebe93..c92848d 100644
--- a/hotspot/src/share/vm/utilities/growableArray.hpp
+++ b/hotspot/src/share/vm/utilities/growableArray.hpp
@@ -147,6 +147,9 @@
   }
 };
 
+template<class E> class GrowableArrayIterator;
+template<class E, class UnaryPredicate> class GrowableArrayFilterIterator;
+
 template<class E> class GrowableArray : public GenericGrowableArray {
   friend class VMStructs;
 
@@ -243,6 +246,14 @@
     return _data[_len-1];
   }
 
+  GrowableArrayIterator<E> begin() const {
+    return GrowableArrayIterator<E>(this, 0);
+  }
+
+  GrowableArrayIterator<E> end() const {
+    return GrowableArrayIterator<E>(this, length());
+  }
+
   void push(const E& elem) { append(elem); }
 
   E pop() {
@@ -338,6 +349,7 @@
 
   // inserts the given element before the element at index i
   void insert_before(const int idx, const E& elem) {
+    assert(0 <= idx && idx <= _len, "illegal index");
     check_nesting();
     if (_len == _max) grow(_len);
     for (int j = _len - 1; j >= idx; j--) {
@@ -349,7 +361,7 @@
 
   void appendAll(const GrowableArray<E>* l) {
     for (int i = 0; i < l->_len; i++) {
-      raw_at_put_grow(_len, l->_data[i], 0);
+      raw_at_put_grow(_len, l->_data[i], E());
     }
   }
 
@@ -412,4 +424,83 @@
     tty->print("}\n");
 }
 
+// Custom STL-style iterator to iterate over GrowableArrays
+// It is constructed by invoking GrowableArray::begin() and GrowableArray::end()
+template<class E> class GrowableArrayIterator : public StackObj {
+  friend class GrowableArray<E>;
+  template<class F, class UnaryPredicate> friend class GrowableArrayFilterIterator;
+
+ private:
+  const GrowableArray<E>* _array; // GrowableArray we iterate over
+  int _position;                  // The current position in the GrowableArray
+
+  // Private constructor used in GrowableArray::begin() and GrowableArray::end()
+  GrowableArrayIterator(const GrowableArray<E>* array, int position) : _array(array), _position(position) {
+    assert(0 <= position && position <= _array->length(), "illegal position");
+  }
+
+ public:
+  GrowableArrayIterator<E>& operator++()  { ++_position; return *this; }
+  E operator*()                           { return _array->at(_position); }
+
+  bool operator==(const GrowableArrayIterator<E>& rhs)  {
+    assert(_array == rhs._array, "iterator belongs to different array");
+    return _position == rhs._position;
+  }
+
+  bool operator!=(const GrowableArrayIterator<E>& rhs)  {
+    assert(_array == rhs._array, "iterator belongs to different array");
+    return _position != rhs._position;
+  }
+};
+
+// Custom STL-style iterator to iterate over elements of a GrowableArray that satisfy a given predicate
+template<class E, class UnaryPredicate> class GrowableArrayFilterIterator : public StackObj {
+  friend class GrowableArray<E>;
+
+ private:
+  const GrowableArray<E>* _array;   // GrowableArray we iterate over
+  int _position;                    // Current position in the GrowableArray
+  UnaryPredicate _predicate;        // Unary predicate the elements of the GrowableArray should satisfy
+
+ public:
+  GrowableArrayFilterIterator(const GrowableArrayIterator<E>& begin, UnaryPredicate filter_predicate)
+   : _array(begin._array), _position(begin._position), _predicate(filter_predicate) {
+    // Advance to first element satisfying the predicate
+    while(_position != _array->length() && !_predicate(_array->at(_position))) {
+      ++_position;
+    }
+  }
+
+  GrowableArrayFilterIterator<E, UnaryPredicate>& operator++() {
+    do {
+      // Advance to next element satisfying the predicate
+      ++_position;
+    } while(_position != _array->length() && !_predicate(_array->at(_position)));
+    return *this;
+  }
+
+  E operator*()   { return _array->at(_position); }
+
+  bool operator==(const GrowableArrayIterator<E>& rhs)  {
+    assert(_array == rhs._array, "iterator belongs to different array");
+    return _position == rhs._position;
+  }
+
+  bool operator!=(const GrowableArrayIterator<E>& rhs)  {
+    assert(_array == rhs._array, "iterator belongs to different array");
+    return _position != rhs._position;
+  }
+
+  bool operator==(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs)  {
+    assert(_array == rhs._array, "iterator belongs to different array");
+    return _position == rhs._position;
+  }
+
+  bool operator!=(const GrowableArrayFilterIterator<E, UnaryPredicate>& rhs)  {
+    assert(_array == rhs._array, "iterator belongs to different array");
+    return _position != rhs._position;
+  }
+};
+
 #endif // SHARE_VM_UTILITIES_GROWABLEARRAY_HPP
diff --git a/hotspot/src/share/vm/utilities/hashtable.inline.hpp b/hotspot/src/share/vm/utilities/hashtable.inline.hpp
index 237fa5f..9356c98 100644
--- a/hotspot/src/share/vm/utilities/hashtable.inline.hpp
+++ b/hotspot/src/share/vm/utilities/hashtable.inline.hpp
@@ -26,6 +26,7 @@
 #define SHARE_VM_UTILITIES_HASHTABLE_INLINE_HPP
 
 #include "memory/allocation.inline.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/hashtable.hpp"
 #include "utilities/dtrace.hpp"
 
diff --git a/hotspot/src/share/vm/utilities/linkedlist.cpp b/hotspot/src/share/vm/utilities/linkedlist.cpp
new file mode 100644
index 0000000..ba96b2e
--- /dev/null
+++ b/hotspot/src/share/vm/utilities/linkedlist.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2011, 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.
+ *
+ */
+
+#include "precompiled.hpp"
+
+/////////////// Unit tests ///////////////
+
+#ifndef PRODUCT
+
+#include "runtime/os.hpp"
+#include "utilities/linkedlist.hpp"
+#include "memory/allocation.hpp"
+#include "memory/allocation.inline.hpp"
+
+class Integer : public StackObj {
+ private:
+  int  _value;
+ public:
+  Integer(int i) : _value(i) { }
+
+  int   value() const { return _value; }
+  bool  equals(const Integer& i) const {
+   return _value == i.value();
+  }
+};
+
+int compare_Integer(const Integer& i1, const Integer& i2) {
+  return i1.value() - i2.value();
+}
+
+void check_list_values(const int* expected, const LinkedList<Integer>* list) {
+  LinkedListNode<Integer>* head = list->head();
+  int index = 0;
+  while (head != NULL) {
+    assert(head->peek()->value() == expected[index], "Unexpected value");
+    head = head->next();
+    index ++;
+  }
+}
+
+void Test_linked_list() {
+  LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest>  ll;
+
+
+  // Test regular linked list
+  assert(ll.is_empty(), "Start with empty list");
+  Integer one(1), two(2), three(3), four(4), five(5), six(6);
+
+  ll.add(six);
+  assert(!ll.is_empty(), "Should not be empty");
+
+  Integer* i = ll.find(six);
+  assert(i != NULL, "Should find it");
+
+  i = ll.find(three);
+  assert(i == NULL, "Not in the list");
+
+  LinkedListNode<Integer>* node = ll.find_node(six);
+  assert(node != NULL, "6 is in the list");
+
+  ll.insert_after(three, node);
+  ll.insert_before(one, node);
+  int expected[3] = {1, 6, 3};
+  check_list_values(expected, &ll);
+
+  ll.add(two);
+  ll.add(four);
+  ll.add(five);
+
+  // Test sorted linked list
+  SortedLinkedList<Integer, compare_Integer, ResourceObj::C_HEAP, mtTest> sl;
+  assert(sl.is_empty(), "Start with empty list");
+
+  size_t ll_size = ll.size();
+  sl.move(&ll);
+  size_t sl_size = sl.size();
+
+  assert(ll_size == sl_size, "Should be the same size");
+  assert(ll.is_empty(), "No more entires");
+
+  // sorted result
+  int sorted_result[] = {1, 2, 3, 4, 5, 6};
+  check_list_values(sorted_result, &sl);
+
+  node = sl.find_node(four);
+  assert(node != NULL, "4 is in the list");
+  sl.remove_before(node);
+  sl.remove_after(node);
+  int remains[] = {1, 2, 4, 6};
+  check_list_values(remains, &sl);
+}
+#endif // PRODUCT
+
diff --git a/hotspot/src/share/vm/utilities/linkedlist.hpp b/hotspot/src/share/vm/utilities/linkedlist.hpp
new file mode 100644
index 0000000..a76c15c
--- /dev/null
+++ b/hotspot/src/share/vm/utilities/linkedlist.hpp
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_LINKED_LIST_HPP
+#define SHARE_VM_UTILITIES_LINKED_LIST_HPP
+
+#include "memory/allocation.hpp"
+
+/*
+ * The implementation of a generic linked list, which uses various
+ * backing storages, such as C heap, arena and resource, etc.
+ */
+
+
+// An entry in a linked list. It should use the same backing storage
+// as the linked list that contains this entry.
+template <class E> class LinkedListNode : public ResourceObj {
+ private:
+  E                       _data;  // embedded content
+  LinkedListNode<E>*      _next;  // next entry
+
+ protected:
+  LinkedListNode() : _next(NULL) { }
+
+ public:
+  LinkedListNode(const E& e): _data(e), _next(NULL) { }
+
+  inline void set_next(LinkedListNode<E>* node) { _next = node; }
+  inline LinkedListNode<E> * next() const       { return _next; }
+
+  E*  data() { return &_data; }
+  const E* peek() const { return &_data; }
+};
+
+// A linked list interface. It does not specify
+// any storage type it uses, so all methods involving
+// memory allocation or deallocation are pure virtual
+template <class E> class LinkedList : public ResourceObj {
+ protected:
+  LinkedListNode<E>*    _head;
+
+ public:
+  LinkedList() : _head(NULL) { }
+
+  inline void set_head(LinkedListNode<E>* h) { _head = h; }
+  inline LinkedListNode<E>* head() const     { return _head; }
+  inline bool is_empty()           const     { return head() == NULL; }
+
+  inline size_t size() const {
+    LinkedListNode<E>* p;
+    size_t count = 0;
+    for (p = head(); p != NULL; count++, p = p->next());
+    return count;
+ }
+
+  // Move all entries from specified linked list to this one
+  virtual void move(LinkedList<E>* list) = 0;
+
+  // Add an entry to this linked list
+  virtual LinkedListNode<E>* add(const E& e) = 0;
+  // Add all entries from specified linked list to this one,
+  virtual void add(LinkedListNode<E>* node) = 0;
+
+  // Add a linked list to this linked list
+  virtual bool  add(const LinkedList<E>* list) = 0;
+
+  // Search entry in the linked list
+  virtual LinkedListNode<E>* find_node(const E& e) = 0;
+  virtual E* find(const E& e) = 0;
+
+  // Insert entry to the linked list
+  virtual LinkedListNode<E>* insert_before(const E& e, LinkedListNode<E>* ref) = 0;
+  virtual LinkedListNode<E>* insert_after (const E& e, LinkedListNode<E>* ref) = 0;
+
+  // Remove entry from the linked list
+  virtual bool               remove(const E& e) = 0;
+  virtual bool               remove(LinkedListNode<E>* node) = 0;
+  virtual bool               remove_before(LinkedListNode<E>* ref) = 0;
+  virtual bool               remove_after(LinkedListNode<E>*  ref) = 0;
+
+  LinkedListNode<E>* unlink_head() {
+    LinkedListNode<E>* h = this->head();
+    if (h != NULL) {
+      this->set_head(h->next());
+    }
+    return h;
+  }
+
+  DEBUG_ONLY(virtual ResourceObj::allocation_type storage_type() = 0;)
+};
+
+// A linked list implementation.
+// The linked list can be allocated in various type of memory: C heap, arena and resource area, etc.
+template <class E, ResourceObj::allocation_type T = ResourceObj::C_HEAP,
+  MEMFLAGS F = mtNMT, AllocFailType alloc_failmode = AllocFailStrategy::RETURN_NULL>
+  class LinkedListImpl : public LinkedList<E> {
+ protected:
+  Arena*                 _arena;
+ public:
+  LinkedListImpl() :  _arena(NULL) { }
+  LinkedListImpl(Arena* a) : _arena(a) { }
+
+  virtual ~LinkedListImpl() {
+    clear();
+  }
+
+  virtual void clear() {
+    LinkedListNode<E>* p = this->head();
+    this->set_head(NULL);
+    while (p != NULL) {
+      LinkedListNode<E>* to_delete = p;
+      p = p->next();
+      delete_node(to_delete);
+    }
+  }
+
+  // Add an entry to the linked list
+  virtual LinkedListNode<E>* add(const E& e)  {
+    LinkedListNode<E>* node = this->new_node(e);
+    if (node != NULL) {
+      this->add(node);
+    }
+
+    return node;
+  }
+
+  virtual void add(LinkedListNode<E>* node) {
+    assert(node != NULL, "NULL pointer");
+    node->set_next(this->head());
+    this->set_head(node);
+  }
+
+  // Move a linked list to this linked list, both have to be allocated on the same
+  // storage type.
+  virtual void move(LinkedList<E>* list) {
+    assert(list->storage_type() == this->storage_type(), "Different storage type");
+    LinkedListNode<E>* node = this->head();
+    while (node != NULL && node->next() != NULL) {
+      node = node->next();
+    }
+    if (node == NULL) {
+      this->set_head(list->head());
+    } else {
+      node->set_next(list->head());
+    }
+    // All entries are moved
+    list->set_head(NULL);
+  }
+
+  virtual bool add(const LinkedList<E>* list) {
+    LinkedListNode<E>* node = list->head();
+    while (node != NULL) {
+      if (this->add(*node->peek()) == NULL) {
+        return false;
+      }
+      node = node->next();
+    }
+    return true;
+  }
+
+
+  virtual LinkedListNode<E>* find_node(const E& e) {
+    LinkedListNode<E>* p = this->head();
+    while (p != NULL && !p->peek()->equals(e)) {
+      p = p->next();
+    }
+    return p;
+  }
+
+  E* find(const E& e) {
+    LinkedListNode<E>* node = find_node(e);
+    return (node == NULL) ? NULL : node->data();
+  }
+
+
+  // Add an entry in front of the reference entry
+  LinkedListNode<E>* insert_before(const E& e, LinkedListNode<E>* ref_node) {
+    LinkedListNode<E>* node = this->new_node(e);
+    if (node == NULL) return NULL;
+    if (ref_node == this->head()) {
+      node->set_next(ref_node);
+      this->set_head(node);
+    } else {
+      LinkedListNode<E>* p = this->head();
+      while (p != NULL && p->next() != ref_node) {
+        p = p->next();
+      }
+      assert(p != NULL, "ref_node not in the list");
+      node->set_next(ref_node);
+      p->set_next(node);
+    }
+    return node;
+  }
+
+   // Add an entry behind the reference entry
+   LinkedListNode<E>* insert_after(const E& e, LinkedListNode<E>* ref_node) {
+     LinkedListNode<E>* node = this->new_node(e);
+     if (node == NULL) return NULL;
+     node->set_next(ref_node->next());
+     ref_node->set_next(node);
+     return node;
+   }
+
+   // Remove an entry from the linked list.
+   // Return true if the entry is successfully removed
+   virtual bool remove(const E& e) {
+     LinkedListNode<E>* tmp = this->head();
+     LinkedListNode<E>* prev = NULL;
+
+     while (tmp != NULL) {
+       if (tmp->peek()->equals(e)) {
+         return remove_after(prev);
+       }
+       prev = tmp;
+       tmp = tmp->next();
+     }
+     return false;
+  }
+
+  // Remove the node after the reference entry
+  virtual bool remove_after(LinkedListNode<E>* prev) {
+    LinkedListNode<E>* to_delete;
+    if (prev == NULL) {
+      to_delete = this->unlink_head();
+    } else {
+      to_delete = prev->next();
+      if (to_delete != NULL) {
+        prev->set_next(to_delete->next());
+      }
+    }
+
+    if (to_delete != NULL) {
+      delete_node(to_delete);
+      return true;
+    }
+    return false;
+  }
+
+  virtual bool remove(LinkedListNode<E>* node) {
+    LinkedListNode<E>* p = this->head();
+    while (p != NULL && p->next() != node) {
+      p = p->next();
+    }
+    if (p != NULL) {
+      p->set_next(node->next());
+      delete_node(node);
+      return true;
+    } else {
+      return false;
+    }
+  }
+
+  virtual bool remove_before(LinkedListNode<E>* ref) {
+    assert(ref != NULL, "NULL pointer");
+    LinkedListNode<E>* p = this->head();
+    LinkedListNode<E>* to_delete = NULL; // to be deleted
+    LinkedListNode<E>* prev = NULL;      // node before the node to be deleted
+    while (p != NULL && p != ref) {
+      prev = to_delete;
+      to_delete = p;
+      p = p->next();
+    }
+    if (p == NULL || to_delete == NULL) return false;
+    assert(to_delete->next() == ref, "Wrong node to delete");
+    assert(prev == NULL || prev->next() == to_delete,
+      "Sanity check");
+    if (prev == NULL) {
+      assert(to_delete == this->head(), "Must be head");
+      this->set_head(to_delete->next());
+    } else {
+      prev->set_next(to_delete->next());
+    }
+    delete_node(to_delete);
+    return true;
+  }
+
+  DEBUG_ONLY(ResourceObj::allocation_type storage_type() { return T; })
+ protected:
+  // Create new linked list node object in specified storage
+  LinkedListNode<E>* new_node(const E& e) const {
+     switch(T) {
+       case ResourceObj::ARENA: {
+         assert(_arena != NULL, "Arena not set");
+         return new(_arena) LinkedListNode<E>(e);
+       }
+       case ResourceObj::RESOURCE_AREA:
+       case ResourceObj::C_HEAP: {
+         if (alloc_failmode == AllocFailStrategy::RETURN_NULL) {
+           return new(std::nothrow, T, F) LinkedListNode<E>(e);
+         } else {
+           return new(T, F) LinkedListNode<E>(e);
+         }
+       }
+       default:
+         ShouldNotReachHere();
+     }
+     return NULL;
+  }
+
+  // Delete linked list node object
+  void delete_node(LinkedListNode<E>* node) {
+    if (T == ResourceObj::C_HEAP) {
+      delete node;
+    }
+  }
+};
+
+// Sorted linked list. The linked list maintains sorting order specified by the comparison
+// function
+template <class E, int (*FUNC)(const E&, const E&),
+  ResourceObj::allocation_type T = ResourceObj::C_HEAP,
+  MEMFLAGS F = mtNMT, AllocFailType alloc_failmode = AllocFailStrategy::RETURN_NULL>
+  class SortedLinkedList : public LinkedListImpl<E, T, F, alloc_failmode> {
+ public:
+  SortedLinkedList() { }
+  SortedLinkedList(Arena* a) : LinkedListImpl<E, T, F, alloc_failmode>(a) { }
+
+  virtual LinkedListNode<E>* add(const E& e) {
+    return LinkedListImpl<E, T, F, alloc_failmode>::add(e);
+  }
+
+  virtual void move(LinkedList<E>* list) {
+    assert(list->storage_type() == this->storage_type(), "Different storage type");
+    LinkedListNode<E>* node;
+    while ((node = list->unlink_head()) != NULL) {
+      this->add(node);
+    }
+    assert(list->is_empty(), "All entries are moved");
+  }
+
+  virtual void add(LinkedListNode<E>* node) {
+    assert(node != NULL, "NULL pointer");
+    LinkedListNode<E>* tmp = this->head();
+    LinkedListNode<E>* prev = NULL;
+
+    int cmp_val;
+    while (tmp != NULL) {
+      cmp_val = FUNC(*tmp->peek(), *node->peek());
+      if (cmp_val >= 0) {
+        break;
+      }
+      prev = tmp;
+      tmp = tmp->next();
+    }
+
+    if (prev != NULL) {
+      node->set_next(prev->next());
+      prev->set_next(node);
+    } else {
+      node->set_next(this->head());
+      this->set_head(node);
+    }
+  }
+
+  virtual bool add(const LinkedList<E>* list) {
+    return LinkedListImpl<E, T, F, alloc_failmode>::add(list);
+  }
+
+  virtual LinkedListNode<E>* find_node(const E& e) {
+    LinkedListNode<E>* p = this->head();
+
+    while (p != NULL) {
+      int comp_val = FUNC(*p->peek(), e);
+      if (comp_val == 0) {
+        return p;
+      } else if (comp_val > 0) {
+        return NULL;
+      }
+      p = p->next();
+    }
+    return NULL;
+  }
+};
+
+// Iterates all entries in the list
+template <class E> class LinkedListIterator : public StackObj {
+ private:
+  LinkedListNode<E>* _p;
+  bool               _is_empty;
+ public:
+  LinkedListIterator(LinkedListNode<E>* head) : _p(head) {
+    _is_empty = (head == NULL);
+  }
+
+  bool is_empty() const { return _is_empty; }
+
+  const E* next() {
+    if (_p == NULL) return NULL;
+    const E* e = _p->peek();
+    _p = _p->next();
+    return e;
+  }
+};
+
+#endif
diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.cpp b/hotspot/src/share/vm/utilities/nativeCallStack.cpp
new file mode 100644
index 0000000..aa3a1e6
--- /dev/null
+++ b/hotspot/src/share/vm/utilities/nativeCallStack.cpp
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#include "precompiled.hpp"
+#include "runtime/os.hpp"
+#include "utilities/globalDefinitions.hpp"
+#include "utilities/nativeCallStack.hpp"
+
+const NativeCallStack NativeCallStack::EMPTY_STACK(0, false);
+
+NativeCallStack::NativeCallStack(int toSkip, bool fillStack) :
+  _hash_value(0) {
+
+#if !PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
+  fillStack = false;
+#endif
+
+  if (fillStack) {
+    os::get_native_stack(_stack, NMT_TrackingStackDepth, toSkip);
+  } else {
+    for (int index = 0; index < NMT_TrackingStackDepth; index ++) {
+      _stack[index] = NULL;
+    }
+  }
+}
+
+NativeCallStack::NativeCallStack(address* pc, int frameCount) {
+  int frameToCopy = (frameCount < NMT_TrackingStackDepth) ?
+    frameCount : NMT_TrackingStackDepth;
+  int index;
+  for (index = 0; index < frameToCopy; index ++) {
+    _stack[index] = pc[index];
+  }
+  for (; index < NMT_TrackingStackDepth; index ++) {
+    _stack[index] = NULL;
+  }
+}
+
+// number of stack frames captured
+int NativeCallStack::frames() const {
+  int index;
+  for (index = 0; index < NMT_TrackingStackDepth; index ++) {
+    if (_stack[index] == NULL) {
+      break;
+    }
+  }
+  return index;
+}
+
+// Hash code. Any better algorithm?
+int NativeCallStack::hash() const {
+  long hash_val = _hash_value;
+  if (hash_val == 0) {
+    long pc;
+    int  index;
+    for (index = 0; index < NMT_TrackingStackDepth; index ++) {
+      pc = (long)_stack[index];
+      if (pc == 0) break;
+      hash_val += pc;
+    }
+
+    NativeCallStack* p = const_cast<NativeCallStack*>(this);
+    p->_hash_value = (int)(hash_val & 0xFFFFFFFF);
+  }
+  return _hash_value;
+}
+
+void NativeCallStack::print_on(outputStream* out) const {
+  print_on(out, 0);
+}
+
+// Decode and print this call path
+void NativeCallStack::print_on(outputStream* out, int indent) const {
+  address pc;
+  char    buf[1024];
+  int     offset;
+  if (is_empty()) {
+    for (int index = 0; index < indent; index ++) out->print(" ");
+#if PLATFORM_NATIVE_STACK_WALKING_SUPPORTED
+    out->print("[BOOTSTRAP]");
+#else
+    out->print("[No stack]");
+#endif
+  } else {
+    for (int frame = 0; frame < NMT_TrackingStackDepth; frame ++) {
+      pc = get_frame(frame);
+      if (pc == NULL) break;
+      // Print indent
+      for (int index = 0; index < indent; index ++) out->print(" ");
+      if (os::dll_address_to_function_name(pc, buf, sizeof(buf), &offset)) {
+        out->print_cr("[" PTR_FORMAT "] %s+0x%x", p2i(pc), buf, offset);
+      } else {
+        out->print_cr("[" PTR_FORMAT "]", p2i(pc));
+      }
+    }
+  }
+}
+
diff --git a/hotspot/src/share/vm/utilities/nativeCallStack.hpp b/hotspot/src/share/vm/utilities/nativeCallStack.hpp
new file mode 100644
index 0000000..b6d6a35
--- /dev/null
+++ b/hotspot/src/share/vm/utilities/nativeCallStack.hpp
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+#ifndef SHARE_VM_UTILITIES_NATIVE_CALL_STACK_HPP
+#define SHARE_VM_UTILITIES_NATIVE_CALL_STACK_HPP
+
+#include "memory/allocation.hpp"
+#include "services/nmtCommon.hpp"
+#include "utilities/ostream.hpp"
+
+/*
+ * This class represents a native call path (does not include Java frame)
+ *
+ * This class is developed in the context of native memory tracking, it can
+ * be an useful tool for debugging purpose.
+ *
+ * For example, following code should print out native call path:
+ *
+ *   ....
+ *   NativeCallStack here;
+ *   here.print_on(tty);
+ *   ....
+ *
+ * However, there are a couple of restrictions on this class. If the restrictions are
+ * not strictly followed, it may break native memory tracking badly.
+ *
+ * 1. Number of stack frames to capture, is defined by native memory tracking.
+ *    This number has impacts on how much memory to be used by native
+ *    memory tracking.
+ * 2. The class is strict stack object, no heap or virtual memory can be allocated
+ *    from it.
+ */
+class NativeCallStack : public StackObj {
+ public:
+  static const NativeCallStack EMPTY_STACK;
+
+ private:
+  address   _stack[NMT_TrackingStackDepth];
+  int       _hash_value;
+
+ public:
+  NativeCallStack(int toSkip = 0, bool fillStack = false);
+  NativeCallStack(address* pc, int frameCount);
+
+
+  // if it is an empty stack
+  inline bool is_empty() const {
+    return _stack[0] == NULL;
+  }
+
+  // number of stack frames captured
+  int frames() const;
+
+  inline int compare(const NativeCallStack& other) const {
+    return memcmp(_stack, other._stack, sizeof(_stack));
+  }
+
+  inline bool equals(const NativeCallStack& other) const {
+    // compare hash values
+    if (hash() != other.hash()) return false;
+    // compare each frame
+    return compare(other) == 0;
+  }
+
+  inline address get_frame(int index) const {
+    assert(index >= 0 && index < NMT_TrackingStackDepth, "Index out of bound");
+    return _stack[index];
+  }
+
+  // Hash code. Any better algorithm?
+  int hash() const;
+
+  void print_on(outputStream* out) const;
+  void print_on(outputStream* out, int indent) const;
+};
+
+#endif
diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp
index 0143e3f..772049a 100644
--- a/hotspot/src/share/vm/utilities/ostream.cpp
+++ b/hotspot/src/share/vm/utilities/ostream.cpp
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "compiler/compileLog.hpp"
+#include "gc_implementation/shared/gcId.hpp"
 #include "oops/oop.inline.hpp"
 #include "runtime/arguments.hpp"
 #include "utilities/defaultStream.hpp"
@@ -240,6 +241,14 @@
   return;
 }
 
+void outputStream::gclog_stamp(const GCId& gc_id) {
+  date_stamp(PrintGCDateStamps);
+  stamp(PrintGCTimeStamps);
+  if (PrintGCID) {
+    print("#%u: ", gc_id.id());
+  }
+}
+
 outputStream& outputStream::indent() {
   while (_position < _indentation) sp();
   return *this;
diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp
index 0ad5c20..6be7aa7 100644
--- a/hotspot/src/share/vm/utilities/ostream.hpp
+++ b/hotspot/src/share/vm/utilities/ostream.hpp
@@ -28,6 +28,7 @@
 #include "memory/allocation.hpp"
 #include "runtime/timer.hpp"
 
+class GCId;
 DEBUG_ONLY(class ResourceMark;)
 
 // Output streams for printing
@@ -107,6 +108,7 @@
    void date_stamp(bool guard) {
      date_stamp(guard, "", ": ");
    }
+   void gclog_stamp(const GCId& gc_id);
 
    // portable printing of 64 bit integers
    void print_jlong(jlong value);
diff --git a/hotspot/src/share/vm/utilities/taskqueue.hpp b/hotspot/src/share/vm/utilities/taskqueue.hpp
index 2577d79..fb9ea61 100644
--- a/hotspot/src/share/vm/utilities/taskqueue.hpp
+++ b/hotspot/src/share/vm/utilities/taskqueue.hpp
@@ -28,40 +28,8 @@
 #include "memory/allocation.hpp"
 #include "memory/allocation.inline.hpp"
 #include "runtime/mutex.hpp"
+#include "runtime/orderAccess.inline.hpp"
 #include "utilities/stack.hpp"
-#ifdef TARGET_OS_ARCH_linux_x86
-# include "orderAccess_linux_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_sparc
-# include "orderAccess_linux_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_zero
-# include "orderAccess_linux_zero.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_x86
-# include "orderAccess_solaris_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_solaris_sparc
-# include "orderAccess_solaris_sparc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_windows_x86
-# include "orderAccess_windows_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_arm
-# include "orderAccess_linux_arm.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_linux_ppc
-# include "orderAccess_linux_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_aix_ppc
-# include "orderAccess_aix_ppc.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_x86
-# include "orderAccess_bsd_x86.inline.hpp"
-#endif
-#ifdef TARGET_OS_ARCH_bsd_zero
-# include "orderAccess_bsd_zero.inline.hpp"
-#endif
 
 // Simple TaskQueue stats that are collected by default in debug builds.
 
diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp
index df0d344..2f7ceb7 100644
--- a/hotspot/src/share/vm/utilities/vmError.cpp
+++ b/hotspot/src/share/vm/utilities/vmError.cpp
@@ -30,7 +30,7 @@
 #include "runtime/frame.inline.hpp"
 #include "runtime/init.hpp"
 #include "runtime/os.hpp"
-#include "runtime/thread.hpp"
+#include "runtime/thread.inline.hpp"
 #include "runtime/vmThread.hpp"
 #include "runtime/vm_operations.hpp"
 #include "services/memTracker.hpp"
@@ -772,6 +772,11 @@
        st->cr();
      }
 
+  STEP(228, "(Native Memory Tracking)" )
+     if (_verbose) {
+       MemTracker::final_report(st);
+     }
+
   STEP(230, "" )
 
      if (_verbose) {
@@ -895,9 +900,6 @@
   static bool log_done = false;         // done saving error log
   static bool transmit_report_done = false; // done error reporting
 
-  // disble NMT to avoid further exception
-  MemTracker::shutdown(MemTracker::NMT_error_reporting);
-
   if (SuppressFatalErrorMessage) {
       os::abort();
   }
diff --git a/hotspot/test/Makefile b/hotspot/test/Makefile
index f29ef32..f81cc8d 100644
--- a/hotspot/test/Makefile
+++ b/hotspot/test/Makefile
@@ -147,6 +147,11 @@
 all: jtreg_tests
 	@$(ECHO) "Testing completed successfully"
 
+# Support "hotspot_" prefixed test make targets too
+# The hotspot_% targets are for example invoked by the top level Makefile
+hotspot_%:
+	$(MAKE) $*
+
 # Prep for output
 prep: clean
 	@$(MKDIR) -p $(ABS_TEST_OUTPUT_DIR)
diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT
index e646c1a..6bf9e9a 100644
--- a/hotspot/test/TEST.ROOT
+++ b/hotspot/test/TEST.ROOT
@@ -1,5 +1,5 @@
 # 
-# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2005, 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
@@ -27,6 +27,6 @@
 # It also contains test-suite configuration information.
 
 # The list of keywords supported in this test suite
-keys=cte_test jcmd nmt regression gc
+keys=cte_test jcmd nmt regression gc stress
 
 groups=TEST.groups [closed/TEST.groups]
diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups
index d526a64..f824411 100644
--- a/hotspot/test/TEST.groups
+++ b/hotspot/test/TEST.groups
@@ -73,15 +73,23 @@
   runtime/jsig/Test8017498.sh \
   runtime/Metaspace/FragmentMetaspace.java \
   runtime/NMT/BaselineWithParameter.java \
+  runtime/NMT/JcmdBaselineDetail.java \
+  runtime/NMT/JcmdDetailDiff.java \
+  runtime/NMT/JcmdScaleDetail.java \
   runtime/NMT/JcmdScale.java \
   runtime/NMT/JcmdWithNMTDisabled.java \
+  runtime/NMT/MallocRoundingReportTest.java \
+  runtime/NMT/MallocSiteHashOverflow.java \
+  runtime/NMT/MallocStressTest.java \
   runtime/NMT/MallocTestType.java \
   runtime/NMT/ReleaseCommittedMemory.java \
+  runtime/NMT/ReleaseNoCommit.java \
   runtime/NMT/ShutdownTwice.java \
   runtime/NMT/SummaryAfterShutdown.java \
   runtime/NMT/SummarySanityCheck.java \
   runtime/NMT/ThreadedMallocTestType.java \
   runtime/NMT/ThreadedVirtualAllocTestType.java \
+  runtime/NMT/VirtualAllocCommitUncommitRecommit.java \
   runtime/NMT/VirtualAllocTestType.java \
   runtime/RedefineObject/TestRedefineObject.java \
   runtime/Thread/TestThreadDumpMonitorContention.java \
@@ -169,6 +177,8 @@
 #
 needs_full_vm_compact1 = \
   runtime/NMT \
+  gc/class_unloading/TestCMSClassUnloadingDisabledHWM.java \
+  gc/class_unloading/TestG1ClassUnloadingHWM.java \
   gc/g1/TestRegionAlignment.java \
   gc/g1/TestShrinkToOneRegion.java \
   gc/metaspace/G1AddMetaspaceDependency.java \
diff --git a/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java
new file mode 100644
index 0000000..6fbaf9c
--- /dev/null
+++ b/hotspot/test/compiler/classUnloading/anonymousClass/TestAnonymousClassUnloading.java
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import sun.hotspot.WhiteBox;
+import sun.misc.Unsafe;
+import sun.misc.IOUtils;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLConnection;
+
+/*
+ * @test TestAnonymousClassUnloading
+ * @bug 8054402
+ * @summary "Tests unloading of anonymous classes."
+ * @library /testlibrary /testlibrary/whitebox
+ * @compile TestAnonymousClassUnloading.java
+ * @run main ClassFileInstaller TestAnonymousClassUnloading
+ *                              sun.hotspot.WhiteBox
+ *                              sun.hotspot.WhiteBox$WhiteBoxPermission
+ * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation TestAnonymousClassUnloading
+ */
+public class TestAnonymousClassUnloading {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static final Unsafe UNSAFE = Unsafe.getUnsafe();
+    private static int COMP_LEVEL_SIMPLE = 1;
+    private static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+
+    /**
+     * We override hashCode here to be able to access this implementation
+     * via an Object reference (we cannot cast to TestAnonymousClassUnloading).
+     */
+    @Override
+    public int hashCode() {
+        return 42;
+    }
+
+    /**
+     * Does some work by using the anonymousClass.
+     * @param anonymousClass Class performing some work (will be unloaded)
+     */
+    static private void doWork(Class<?> anonymousClass) throws InstantiationException, IllegalAccessException {
+        // Create a new instance
+        Object anon = anonymousClass.newInstance();
+        // We would like to call a method of anonymousClass here but we cannot cast because the class
+        // was loaded by a different class loader. One solution would be to use reflection but since
+        // we want C2 to implement the call as an IC we call Object::hashCode() here which actually
+        // calls anonymousClass::hashCode(). C2 will then implement this call as an IC.
+        if (anon.hashCode() != 42) {
+            new RuntimeException("Work not done");
+        }
+    }
+
+    /**
+     * Makes sure that method is compiled by forcing compilation if not yet compiled.
+     * @param m Method to be checked
+     */
+    static private void makeSureIsCompiled(Method m) {
+        // Make sure background compilation is disabled
+        if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
+            throw new RuntimeException("Background compilation enabled");
+        }
+
+        // Check if already compiled
+        if (!WHITE_BOX.isMethodCompiled(m)) {
+            // If not, try to compile it with C2
+            if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) {
+                // C2 compiler not available, try to compile with C1
+                WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE);
+            }
+            // Because background compilation is disabled, method should now be compiled
+            if(!WHITE_BOX.isMethodCompiled(m)) {
+                throw new RuntimeException(m + " not compiled");
+            }
+        }
+    }
+
+    /**
+     * This test creates stale Klass* metadata referenced by a compiled IC.
+     *
+     * The following steps are performed:
+     * (1) An anonymous version of TestAnonymousClassUnloading is loaded by a custom class loader
+     * (2) The method doWork that calls a method of the anonymous class is compiled. The call
+     *     is implemented as an IC referencing Klass* metadata of the anonymous class.
+     * (3) Unloading of the anonymous class is enforced. The IC now references dead metadata.
+     */
+    static public void main(String[] args) throws Exception {
+        // (1) Load an anonymous version of this class using the corresponding Unsafe method
+        URL classUrl = TestAnonymousClassUnloading.class.getResource("TestAnonymousClassUnloading.class");
+        URLConnection connection = classUrl.openConnection();
+        byte[] classBytes = IOUtils.readFully(connection.getInputStream(), connection.getContentLength(), true);
+        Class<?> anonymousClass = UNSAFE.defineAnonymousClass(TestAnonymousClassUnloading.class, classBytes, null);
+
+        // (2) Make sure all paths of doWork are profiled and compiled
+        for (int i = 0; i < 100000; ++i) {
+            doWork(anonymousClass);
+        }
+
+        // Make sure doWork is compiled now
+        Method doWork = TestAnonymousClassUnloading.class.getDeclaredMethod("doWork", Class.class);
+        makeSureIsCompiled(doWork);
+
+        // (3) Throw away reference to anonymousClass to allow unloading
+        anonymousClass = null;
+
+        // Force garbage collection to trigger unloading of anonymousClass
+        // Dead metadata reference to anonymousClass triggers JDK-8054402
+        WHITE_BOX.fullGC();
+    }
+}
diff --git a/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java
new file mode 100644
index 0000000..5e0c58f
--- /dev/null
+++ b/hotspot/test/compiler/classUnloading/methodUnloading/TestMethodUnloading.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import sun.hotspot.WhiteBox;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/*
+ * @test MethodUnloadingTest
+ * @bug 8029443
+ * @summary "Tests the unloading of methods to to class unloading"
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestMethodUnloading
+ * @build WorkerClass
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseCompressedOops -XX:+UseParallelGC -XX:CompileOnly=TestMethodUnloading::doWork TestMethodUnloading
+ */
+public class TestMethodUnloading {
+    private static final String workerClassName = "WorkerClass";
+    private static int work = -1;
+
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static int COMP_LEVEL_SIMPLE = 1;
+    private static int COMP_LEVEL_FULL_OPTIMIZATION = 4;
+
+    /**
+     * Does some work by either using the workerClass or locally producing values.
+     * @param workerClass Class performing some work (will be unloaded)
+     * @param useWorker If true the workerClass is used
+     */
+    static private void doWork(Class<?> workerClass, boolean useWorker) throws InstantiationException, IllegalAccessException {
+        if (useWorker) {
+            // Create a new instance
+            Object worker = workerClass.newInstance();
+            // We would like to call a method of WorkerClass here but we cannot cast to WorkerClass
+            // because the class was loaded by a different class loader. One solution would be to use
+            // reflection but since we want C2 to implement the call as an optimized IC we call
+            // Object::hashCode() here which actually calls WorkerClass::hashCode().
+            // C2 will then implement this call as an optimized IC that points to a to-interpreter stub
+            // referencing the Method* for WorkerClass::hashCode().
+            work = worker.hashCode();
+            if (work != 42) {
+                new RuntimeException("Work not done");
+            }
+        } else {
+            // Do some important work here
+            work = 1;
+        }
+    }
+
+    /**
+     * Makes sure that method is compiled by forcing compilation if not yet compiled.
+     * @param m Method to be checked
+     */
+    static private void makeSureIsCompiled(Method m) {
+        // Make sure background compilation is disabled
+        if (WHITE_BOX.getBooleanVMFlag("BackgroundCompilation")) {
+            throw new RuntimeException("Background compilation enabled");
+        }
+
+        // Check if already compiled
+        if (!WHITE_BOX.isMethodCompiled(m)) {
+            // If not, try to compile it with C2
+            if(!WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_FULL_OPTIMIZATION)) {
+                // C2 compiler not available, try to compile with C1
+                WHITE_BOX.enqueueMethodForCompilation(m, COMP_LEVEL_SIMPLE);
+            }
+            // Because background compilation is disabled, method should now be compiled
+            if(!WHITE_BOX.isMethodCompiled(m)) {
+                throw new RuntimeException(m + " not compiled");
+            }
+        }
+    }
+
+    /**
+     * This test creates stale Method* metadata in a to-interpreter stub of an optimized IC.
+     *
+     * The following steps are performed:
+     * (1) A workerClass is loaded by a custom class loader
+     * (2) The method doWork that calls a method of the workerClass is compiled. The call
+     *     is implemented as an optimized IC calling a to-interpreted stub. The to-interpreter
+     *     stub contains a Method* to a workerClass method.
+     * (3) Unloading of the workerClass is enforced. The to-interpreter stub now contains a dead Method*.
+     * (4) Depending on the implementation of the IC, the compiled version of doWork should still be
+     *     valid. We call it again without using the workerClass.
+     */
+    static public void main(String[] args) throws Exception {
+        // (1) Create a custom class loader with no parent class loader
+        URL url = TestMethodUnloading.class.getProtectionDomain().getCodeSource().getLocation();
+        URLClassLoader loader = new URLClassLoader(new URL[] {url}, null);
+
+        // Load worker class with custom class loader
+        Class<?> workerClass = Class.forName(workerClassName, true, loader);
+
+        // (2) Make sure all paths of doWork are profiled and compiled
+        for (int i = 0; i < 100000; ++i) {
+            doWork(workerClass, true);
+            doWork(workerClass, false);
+        }
+
+        // Make sure doWork is compiled now
+        Method doWork = TestMethodUnloading.class.getDeclaredMethod("doWork", Class.class, boolean.class);
+        makeSureIsCompiled(doWork);
+
+        // (3) Throw away class loader and reference to workerClass to allow unloading
+        loader.close();
+        loader = null;
+        workerClass = null;
+
+        // Force garbage collection to trigger unloading of workerClass
+        // Dead reference to WorkerClass::hashCode triggers JDK-8029443
+        WHITE_BOX.fullGC();
+
+        // (4) Depending on the implementation of the IC, the compiled version of doWork
+        // may still be valid here. Execute it without a workerClass.
+        doWork(null, false);
+        if (work != 1) {
+            throw new RuntimeException("Work not done");
+        }
+
+        doWork(Object.class, false);
+    }
+}
diff --git a/nashorn/test/script/maptests/property_delete.js b/hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java
similarity index 69%
copy from nashorn/test/script/maptests/property_delete.js
copy to hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java
index e2824dd..c67154f 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/hotspot/test/compiler/classUnloading/methodUnloading/WorkerClass.java
@@ -1,48 +1,37 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * Worker class that is dynamically loaded/unloaded by TestMethodUnloading.
  */
-
-load(__DIR__ + "maputil.js");
-
-function Foo() {
-    this.x = 33;
+public class WorkerClass {
+    /**
+     * We override hashCode here to be able to access this implementation
+     * via an Object reference (we cannot cast to WorkerClass).
+     */
+    @Override
+    public int hashCode() {
+        return 42;
+    }
 }
 
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/hotspot/test/compiler/intrinsics/sha/TestSHA.java b/hotspot/test/compiler/intrinsics/sha/TestSHA.java
new file mode 100644
index 0000000..08af909
--- /dev/null
+++ b/hotspot/test/compiler/intrinsics/sha/TestSHA.java
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 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.
+ *
+ */
+
+/**
+ * @test
+ * @bug 8035968
+ * @summary C2 support for SHA on SPARC
+ *
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1   TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-224 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-384 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-512 TestSHA
+ *
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1   -Doffset=1 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-224 -Doffset=1 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 -Doffset=1 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-384 -Doffset=1 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-512 -Doffset=1 TestSHA
+ *
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1   -Dalgorithm2=SHA-256 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1   -Dalgorithm2=SHA-512 TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-256 -Dalgorithm2=SHA-512 TestSHA
+ *
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=SHA-1   -Dalgorithm2=MD5     TestSHA
+ * @run main/othervm/timeout=600 -Xbatch -Dalgorithm=MD5     -Dalgorithm2=SHA-1   TestSHA
+ */
+
+import java.security.MessageDigest;
+import java.util.Arrays;
+
+public class TestSHA {
+    private static final int HASH_LEN = 64; /* up to 512-bit */
+    private static final int ALIGN = 8;     /* for different data alignments */
+
+    public static void main(String[] args) throws Exception {
+        String provider = System.getProperty("provider", "SUN");
+        String algorithm = System.getProperty("algorithm", "SHA-1");
+        String algorithm2 = System.getProperty("algorithm2", "");
+        int msgSize = Integer.getInteger("msgSize", 1024);
+        int offset = Integer.getInteger("offset", 0)  % ALIGN;
+        int iters = (args.length > 0 ? Integer.valueOf(args[0]) : 100000);
+        int warmupIters = (args.length > 1 ? Integer.valueOf(args[1]) : 20000);
+
+        testSHA(provider, algorithm, msgSize, offset, iters, warmupIters);
+
+        if (algorithm2.equals("") == false) {
+            testSHA(provider, algorithm2, msgSize, offset, iters, warmupIters);
+        }
+    }
+
+    static void testSHA(String provider, String algorithm, int msgSize,
+                        int offset, int iters, int warmupIters) throws Exception {
+        System.out.println("provider = " + provider);
+        System.out.println("algorithm = " + algorithm);
+        System.out.println("msgSize = " + msgSize + " bytes");
+        System.out.println("offset = " + offset);
+        System.out.println("iters = " + iters);
+
+        byte[] expectedHash = new byte[HASH_LEN];
+        byte[] hash = new byte[HASH_LEN];
+        byte[] data = new byte[msgSize + offset];
+        for (int i = 0; i < (msgSize + offset); i++) {
+            data[i] = (byte)(i & 0xff);
+        }
+
+        try {
+            MessageDigest sha = MessageDigest.getInstance(algorithm, provider);
+
+            /* do once, which doesn't use intrinsics */
+            sha.reset();
+            sha.update(data, offset, msgSize);
+            expectedHash = sha.digest();
+
+            /* warm up */
+            for (int i = 0; i < warmupIters; i++) {
+                sha.reset();
+                sha.update(data, offset, msgSize);
+                hash = sha.digest();
+            }
+
+            /* check result */
+            if (Arrays.equals(hash, expectedHash) == false) {
+                System.out.println("TestSHA Error: ");
+                showArray(expectedHash, "expectedHash");
+                showArray(hash,         "computedHash");
+                //System.exit(1);
+                throw new Exception("TestSHA Error");
+            } else {
+                showArray(hash, "hash");
+            }
+
+            /* measure performance */
+            long start = System.nanoTime();
+            for (int i = 0; i < iters; i++) {
+                sha.reset();
+                sha.update(data, offset, msgSize);
+                hash = sha.digest();
+            }
+            long end = System.nanoTime();
+            double total = (double)(end - start)/1e9;         /* in seconds */
+            double thruput = (double)msgSize*iters/1e6/total; /* in MB/s */
+            System.out.println("TestSHA runtime = " + total + " seconds");
+            System.out.println("TestSHA throughput = " + thruput + " MB/s");
+            System.out.println();
+        } catch (Exception e) {
+            System.out.println("Exception: " + e);
+            //System.exit(1);
+            throw new Exception(e);
+        }
+    }
+
+    static void showArray(byte b[], String name) {
+        System.out.format("%s [%d]: ", name, b.length);
+        for (int i = 0; i < Math.min(b.length, HASH_LEN); i++) {
+            System.out.format("%02x ", b[i] & 0xff);
+        }
+        System.out.println();
+    }
+}
diff --git a/hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java b/hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java
new file mode 100644
index 0000000..82bbfc2
--- /dev/null
+++ b/hotspot/test/compiler/osr/TestOSRWithNonEmptyStack.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+
+import jdk.internal.org.objectweb.asm.ClassWriter;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import static jdk.internal.org.objectweb.asm.Opcodes.*;
+
+/**
+ * @test
+ * @bug 8051344
+ * @summary Force OSR compilation with non-empty stack at the OSR entry point.
+ * @compile -XDignore.symbol.file TestOSRWithNonEmptyStack.java
+ * @run main/othervm -XX:CompileOnly=TestCase.test TestOSRWithNonEmptyStack
+ */
+public class TestOSRWithNonEmptyStack extends ClassLoader {
+    private static final int CLASS_FILE_VERSION = 52;
+    private static final String CLASS_NAME = "TestCase";
+    private static final String METHOD_NAME = "test";
+    private static final int ITERATIONS = 1_000_000;
+
+    private static byte[] generateTestClass() {
+        ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES);
+
+        cw.visit(TestOSRWithNonEmptyStack.CLASS_FILE_VERSION, ACC_PUBLIC,
+                TestOSRWithNonEmptyStack.CLASS_NAME, null, "java/lang/Object",
+                null);
+
+        TestOSRWithNonEmptyStack.generateConstructor(cw);
+        TestOSRWithNonEmptyStack.generateTestMethod(cw);
+
+        cw.visitEnd();
+        return cw.toByteArray();
+    }
+
+    private static void generateConstructor(ClassWriter classWriter) {
+        MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC, "<init>", "()V",
+                null, null);
+
+        mv.visitCode();
+
+        mv.visitVarInsn(ALOAD, 0);
+        mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
+                false);
+        mv.visitInsn(RETURN);
+
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+    private static void generateTestMethod(ClassWriter classWriter) {
+        MethodVisitor mv = classWriter.visitMethod(ACC_PUBLIC,
+                TestOSRWithNonEmptyStack.METHOD_NAME, "()V", null, null);
+        Label osrEntryPoint = new Label();
+
+        mv.visitCode();
+        // Push 'this' into stack before OSR entry point to bail out compilation
+        mv.visitVarInsn(ALOAD, 0);
+        // Setup loop counter
+        mv.visitInsn(ICONST_0);
+        mv.visitVarInsn(ISTORE, 1);
+        // Begin loop
+        mv.visitLabel(osrEntryPoint);
+        // Increment loop counter
+        mv.visitVarInsn(ILOAD, 1);
+        mv.visitInsn(ICONST_1);
+        mv.visitInsn(IADD);
+        // Duplicate it for loop condition check
+        mv.visitInsn(DUP);
+        mv.visitVarInsn(ISTORE, 1);
+        // Check loop condition
+        mv.visitLdcInsn(TestOSRWithNonEmptyStack.ITERATIONS);
+        mv.visitJumpInsn(IF_ICMPLT, osrEntryPoint);
+        // Pop 'this'.
+        mv.visitInsn(POP);
+        mv.visitInsn(RETURN);
+
+        mv.visitMaxs(0, 0);
+        mv.visitEnd();
+    }
+
+    private void run() {
+        byte[] bytecode = TestOSRWithNonEmptyStack.generateTestClass();
+
+        try {
+            Class klass = defineClass(TestOSRWithNonEmptyStack.CLASS_NAME,
+                    bytecode, 0, bytecode.length);
+
+            Constructor ctor = klass.getConstructor();
+            Method method = klass.getDeclaredMethod(
+                    TestOSRWithNonEmptyStack.METHOD_NAME);
+
+            Object testCase = ctor.newInstance();
+            method.invoke(testCase);
+        } catch (Exception e) {
+            throw new RuntimeException(
+                    "Test bug: generated class should be valid.", e);
+        }
+    }
+
+    public static void main(String args[]) {
+        new TestOSRWithNonEmptyStack().run();
+    }
+}
diff --git a/hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java b/hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java
index b1c29e6..0d4e52c 100644
--- a/hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java
+++ b/hotspot/test/compiler/rtm/cli/TestRTMRetryCountOption.java
@@ -35,7 +35,7 @@
     private static final String DEFAULT_VALUE = "5";
 
     private TestRTMRetryCountOption() {
-        super(Boolean.TRUE::booleanValue, "RTMRetryCount", false, true,
+        super(Boolean.TRUE::booleanValue, "RTMRetryCount", false, false,
                 TestRTMRetryCountOption.DEFAULT_VALUE,
                 "0", "10", "100", "1000");
     }
diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java
index 54a7d63..bd9d782 100644
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnSupportedConfig.java
@@ -50,38 +50,25 @@
 
     @Override
     public void runTestCases() throws Throwable {
-        String experimentalOptionError
-                = CommandLineOptionTest.getExperimentalOptionErrorMessage(
-                "UseRTMDeopt");
-        // verify that option is experimental
-        CommandLineOptionTest.verifySameJVMStartup(
-                new String[] { experimentalOptionError }, null, ExitCode.FAIL,
-                "-XX:+UseRTMDeopt");
         // verify that option could be turned on
-        CommandLineOptionTest.verifySameJVMStartup(null, null, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMDeopt");
+        CommandLineOptionTest.verifySameJVMStartup(
+                null, null, ExitCode.OK, "-XX:+UseRTMDeopt");
         // verify that option could be turned off
-        CommandLineOptionTest.verifySameJVMStartup(null, null, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:-UseRTMDeopt");
+        CommandLineOptionTest.verifySameJVMStartup(
+                null, null, ExitCode.OK, "-XX:-UseRTMDeopt");
+        // verify default value
+        CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt",
+                TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE);
         // verify default value
         CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt",
                 TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
-        // verify default value
-        CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt",
-                TestUseRTMDeoptOptionOnSupportedConfig.DEFAULT_VALUE,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
                 "-XX:+UseRTMLocking");
         // verify that option is off when UseRTMLocking is off
-        CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "false",
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:-UseRTMLocking", "-XX:+UseRTMDeopt");
+        CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt",
+                "false", "-XX:-UseRTMLocking", "-XX:+UseRTMDeopt");
         // verify that option could be turned on
-        CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt", "true",
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMLocking", "-XX:+UseRTMDeopt");
+        CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMDeopt",
+                "true", "-XX:+UseRTMLocking", "-XX:+UseRTMDeopt");
     }
 
     public static void main(String args[]) throws Throwable {
diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java
index 332bd45..2f3b836 100644
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMDeoptOptionOnUnsupportedConfig.java
@@ -48,7 +48,7 @@
     private TestUseRTMDeoptOptionOnUnsupportedConfig() {
         super(new NotPredicate(new AndPredicate(new SupportedCPU(),
                         new SupportedVM())),
-                "UseRTMDeopt", true, true,
+                "UseRTMDeopt", true, false,
                 TestUseRTMDeoptOptionOnUnsupportedConfig.DEFAULT_VALUE, "true");
     }
 
@@ -57,14 +57,11 @@
         super.verifyJVMStartup();
         // verify default value
         CommandLineOptionTest.verifyOptionValueForSameVM(optionName,
-                defaultValue,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
+                defaultValue);
         // verify that until RTMLocking is not used, value
         // will be set to default false.
         CommandLineOptionTest.verifyOptionValueForSameVM(optionName,
-                defaultValue,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMDeopt");
+                defaultValue, "-XX:+UseRTMDeopt");
     }
 
     public static void main(String args[]) throws Throwable {
diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java
index cf4861e..72af535 100644
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnSupportedConfig.java
@@ -51,43 +51,31 @@
     @Override
     public void runTestCases() throws Throwable {
         String unrecongnizedOption
-                = CommandLineOptionTest.getUnrecognizedOptionErrorMessage(
+                =  CommandLineOptionTest.getUnrecognizedOptionErrorMessage(
                 "UseRTMLocking");
-        String experimentalOptionError
-                = CommandLineOptionTest.getExperimentalOptionErrorMessage(
-                "UseRTMLocking");
-        // verify that options is experimental
-        CommandLineOptionTest.verifySameJVMStartup(
-                new String[] { experimentalOptionError }, null, ExitCode.FAIL,
-                "-XX:+UseRTMLocking");
         // verify that there are no warning or error in VM output
         CommandLineOptionTest.verifySameJVMStartup(null,
                 new String[]{
                         RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR,
                         unrecongnizedOption
-                }, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMLocking");
+                }, ExitCode.OK, "-XX:+UseRTMLocking"
+        );
 
         CommandLineOptionTest.verifySameJVMStartup(null,
                 new String[]{
                         RTMGenericCommandLineOptionTest.RTM_INSTR_ERROR,
                         unrecongnizedOption
-                }, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:-UseRTMLocking");
+                }, ExitCode.OK, "-XX:-UseRTMLocking"
+        );
         // verify that UseRTMLocking is of by default
         CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking",
-                TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
+                TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE);
         // verify that we can change UseRTMLocking value
         CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking",
                 TestUseRTMLockingOptionOnSupportedConfig.DEFAULT_VALUE,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
                 "-XX:-UseRTMLocking");
         CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking",
-                "true", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMLocking");
+                "true", "-XX:+UseRTMLocking");
     }
 
     public static void main(String args[]) throws Throwable {
diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java
index bbe6c03..6e10024 100644
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedCPU.java
@@ -63,9 +63,7 @@
             CommandLineOptionTest.verifySameJVMStartup(
                     new String[] { errorMessage },
                     new String[] { unrecongnizedOption },
-                    ExitCode.FAIL,
-                    CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                    "-XX:+UseRTMLocking");
+                    ExitCode.FAIL, "-XX:+UseRTMLocking");
             // verify that we can pass -UseRTMLocking without
             // getting any error messages
             CommandLineOptionTest.verifySameJVMStartup(
@@ -73,27 +71,20 @@
                     new String[]{
                             errorMessage,
                             unrecongnizedOption
-                    }, ExitCode.OK,
-                    CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                    "-XX:-UseRTMLocking");
+                    }, ExitCode.OK, "-XX:-UseRTMLocking");
 
             // verify that UseRTMLocking is false by default
             CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking",
-                    TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE,
-                    CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
+                    TestUseRTMLockingOptionOnUnsupportedCPU.DEFAULT_VALUE);
         } else {
             // verify that on non-x86 CPUs RTMLocking could not be used
             CommandLineOptionTest.verifySameJVMStartup(
                     new String[] { unrecongnizedOption },
-                    null, ExitCode.FAIL,
-                    CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                    "-XX:+UseRTMLocking");
+                    null, ExitCode.FAIL, "-XX:+UseRTMLocking");
 
             CommandLineOptionTest.verifySameJVMStartup(
                     new String[] { unrecongnizedOption },
-                    null, ExitCode.FAIL,
-                    CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                    "-XX:-UseRTMLocking");
+                    null, ExitCode.FAIL, "-XX:-UseRTMLocking");
         }
     }
 
diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java
index ad6e29f..0121856 100644
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionOnUnsupportedVM.java
@@ -53,27 +53,17 @@
     public void runTestCases() throws Throwable {
         String errorMessage
                 = RTMGenericCommandLineOptionTest.RTM_UNSUPPORTED_VM_ERROR;
-        String experimentalOptionError
-                = CommandLineOptionTest.getExperimentalOptionErrorMessage(
-                "UseRTMLocking");
-        // verify that options is experimental
-        CommandLineOptionTest.verifySameJVMStartup(
-                new String[] { experimentalOptionError }, null, ExitCode.FAIL,
-                "-XX:+UseRTMLocking");
         // verify that we can't use +UseRTMLocking
         CommandLineOptionTest.verifySameJVMStartup(
                 new String[] { errorMessage }, null, ExitCode.FAIL,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
                 "-XX:+UseRTMLocking");
         // verify that we can turn it off
         CommandLineOptionTest.verifySameJVMStartup(null,
                 new String[] { errorMessage }, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
                 "-XX:-UseRTMLocking");
         // verify that it is off by default
         CommandLineOptionTest.verifyOptionValueForSameVM("UseRTMLocking",
-                TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS);
+                TestUseRTMLockingOptionOnUnsupportedVM.DEFAULT_VALUE);
     }
 
     public static void main(String args[]) throws Throwable {
diff --git a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java
index 5551701..89b30bf 100644
--- a/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java
+++ b/hotspot/test/compiler/rtm/cli/TestUseRTMLockingOptionWithBiasedLocking.java
@@ -53,22 +53,18 @@
         // verify that we will not get a warning
         CommandLineOptionTest.verifySameJVMStartup(null,
                 new String[] { warningMessage }, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
                 "-XX:+UseRTMLocking", "-XX:-UseBiasedLocking");
         // verify that we will get a warning
         CommandLineOptionTest.verifySameJVMStartup(
                 new String[] { warningMessage }, null, ExitCode.OK,
-                CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
                 "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking");
         // verify that UseBiasedLocking is false when we use rtm locking
         CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking",
-                "false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMLocking");
+                "false", "-XX:+UseRTMLocking");
         // verify that we can't turn on biased locking when
         // using rtm locking
         CommandLineOptionTest.verifyOptionValueForSameVM("UseBiasedLocking",
-                "false", CommandLineOptionTest.UNLOCK_EXPERIMENTAL_VM_OPTIONS,
-                "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking");
+                "false", "-XX:+UseRTMLocking", "-XX:+UseBiasedLocking");
     }
 
     public static void main(String args[]) throws Throwable {
diff --git a/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java b/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java
index 6d36106..53728b8 100644
--- a/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java
+++ b/hotspot/test/gc/arguments/TestDynMaxHeapFreeRatio.java
@@ -21,6 +21,11 @@
  * questions.
  */
 
+import static com.oracle.java.testlibrary.Asserts.assertEQ;
+import static com.oracle.java.testlibrary.Asserts.assertFalse;
+import static com.oracle.java.testlibrary.Asserts.assertTrue;
+import com.oracle.java.testlibrary.DynamicVMOption;
+
 /**
  * @test TestDynMaxHeapFreeRatio
  * @bug 8028391
@@ -33,32 +38,45 @@
  * @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMaxHeapFreeRatio
  * @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMaxHeapFreeRatio
  */
-import com.oracle.java.testlibrary.TestDynamicVMOption;
-import com.oracle.java.testlibrary.DynamicVMOptionChecker;
-
-public class TestDynMaxHeapFreeRatio extends TestDynamicVMOption {
-
-    public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
-    public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
-
-    public TestDynMaxHeapFreeRatio() {
-        super(MaxFreeRatioFlagName);
-    }
-
-    public void test() {
-
-        int minHeapFreeValue = DynamicVMOptionChecker.getIntValue(MinFreeRatioFlagName);
-        System.out.println(MinFreeRatioFlagName + " = " + minHeapFreeValue);
-
-        testPercentageValues();
-
-        checkInvalidValue(Integer.toString(minHeapFreeValue - 1));
-        checkValidValue(Integer.toString(minHeapFreeValue));
-        checkValidValue("100");
-    }
+public class TestDynMaxHeapFreeRatio {
 
     public static void main(String args[]) throws Exception {
-        new TestDynMaxHeapFreeRatio().test();
-    }
 
+        // low boundary value
+        int minValue = DynamicVMOption.getInt("MinHeapFreeRatio");
+        System.out.println("MinHeapFreeRatio= " + minValue);
+
+        String badValues[] = {
+            null,
+            "",
+            "not a number",
+            "8.5", "-0.01",
+            Integer.toString(Integer.MIN_VALUE),
+            Integer.toString(Integer.MAX_VALUE),
+            Integer.toString(minValue - 1),
+            "-1024", "-1", "101", "1997"
+        };
+
+        String goodValues[] = {
+            Integer.toString(minValue),
+            Integer.toString(minValue + 1),
+            Integer.toString((minValue + 100) / 2),
+            "99", "100"
+        };
+
+        DynamicVMOption option = new DynamicVMOption("MaxHeapFreeRatio");
+
+        assertTrue(option.isWriteable(), "Option " + option.name
+                + " is expected to be writable");
+
+        for (String v : badValues) {
+            assertFalse(option.isValidValue(v),
+                    "'" + v + "' is expected to be illegal for flag " + option.name);
+        }
+        for (String v : goodValues) {
+            option.setValue(v);
+            String newValue = option.getValue();
+            assertEQ(v, newValue);
+        }
+    }
 }
diff --git a/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java b/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java
index 13132f0..bbf0ecf 100644
--- a/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java
+++ b/hotspot/test/gc/arguments/TestDynMinHeapFreeRatio.java
@@ -33,30 +33,52 @@
  * @run main/othervm -XX:MinHeapFreeRatio=51 -XX:MaxHeapFreeRatio=52 TestDynMinHeapFreeRatio
  * @run main/othervm -XX:MinHeapFreeRatio=75 -XX:MaxHeapFreeRatio=100 TestDynMinHeapFreeRatio
  */
-import com.oracle.java.testlibrary.TestDynamicVMOption;
-import com.oracle.java.testlibrary.DynamicVMOptionChecker;
+import static com.oracle.java.testlibrary.Asserts.assertEQ;
+import static com.oracle.java.testlibrary.Asserts.assertFalse;
+import static com.oracle.java.testlibrary.Asserts.assertTrue;
+import com.oracle.java.testlibrary.DynamicVMOption;
 
-public class TestDynMinHeapFreeRatio extends TestDynamicVMOption {
-
-    public static final String MinFreeRatioFlagName = "MinHeapFreeRatio";
-    public static final String MaxFreeRatioFlagName = "MaxHeapFreeRatio";
-
-    public TestDynMinHeapFreeRatio() {
-        super(MinFreeRatioFlagName);
-    }
-
-    public void test() {
-        int maxHeapFreeValue = DynamicVMOptionChecker.getIntValue(MaxFreeRatioFlagName);
-        System.out.println(MaxFreeRatioFlagName + " = " + maxHeapFreeValue);
-
-        testPercentageValues();
-
-        checkInvalidValue(Integer.toString(maxHeapFreeValue + 1));
-        checkValidValue(Integer.toString(maxHeapFreeValue));
-        checkValidValue("0");
-    }
+public class TestDynMinHeapFreeRatio {
 
     public static void main(String args[]) throws Exception {
-        new TestDynMinHeapFreeRatio().test();
+
+        // high boundary value
+        int maxValue = DynamicVMOption.getInt("MaxHeapFreeRatio");
+        System.out.println("MaxHeapFreeRatio= " + maxValue);
+
+        String badValues[] = {
+            null,
+            "",
+            "not a number",
+            "8.5", "-0.01",
+            Integer.toString(Integer.MIN_VALUE),
+            Integer.toString(Integer.MAX_VALUE),
+            Integer.toString(maxValue + 1),
+            "-1024", "-1", "101", "1997"
+        };
+
+        String goodValues[] = {
+            Integer.toString(maxValue),
+            Integer.toString(maxValue - 1),
+            Integer.toString(maxValue / 2),
+            "0", "1"
+        };
+
+        // option under test
+        DynamicVMOption option = new DynamicVMOption("MinHeapFreeRatio");
+
+        assertTrue(option.isWriteable(), "Option " + option.name
+                + " is expected to be writable");
+
+        for (String v : badValues) {
+            assertFalse(option.isValidValue(v),
+                    "'" + v + "' is expected to be illegal for flag " + option.name);
+        }
+
+        for (String v : goodValues) {
+            option.setValue(v);
+            String newValue = option.getValue();
+            assertEQ(v, newValue);
+        }
     }
 }
diff --git a/hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java b/hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java
new file mode 100644
index 0000000..4998fa8
--- /dev/null
+++ b/hotspot/test/gc/class_unloading/AllocateBeyondMetaspaceSize.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import sun.hotspot.WhiteBox;
+
+class AllocateBeyondMetaspaceSize {
+  public static Object dummy;
+
+  public static void main(String [] args) {
+    if (args.length != 2) {
+      throw new IllegalArgumentException("Usage: <MetaspaceSize> <YoungGenSize>");
+    }
+
+    long metaspaceSize = Long.parseLong(args[0]);
+    long youngGenSize = Long.parseLong(args[1]);
+
+    run(metaspaceSize, youngGenSize);
+  }
+
+  private static void run(long metaspaceSize, long youngGenSize) {
+    WhiteBox wb = WhiteBox.getWhiteBox();
+
+    long allocationBeyondMetaspaceSize  = metaspaceSize * 2;
+    long metaspace = wb.allocateMetaspace(null, allocationBeyondMetaspaceSize);
+
+    triggerYoungGC(youngGenSize);
+
+    wb.freeMetaspace(null, metaspace, metaspace);
+  }
+
+  private static void triggerYoungGC(long youngGenSize) {
+    long approxAllocSize = 32 * 1024;
+    long numAllocations  = 2 * youngGenSize / approxAllocSize;
+
+    for (long i = 0; i < numAllocations; i++) {
+      dummy = new byte[(int)approxAllocSize];
+    }
+  }
+}
diff --git a/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java
new file mode 100644
index 0000000..906ac0f
--- /dev/null
+++ b/hotspot/test/gc/class_unloading/TestCMSClassUnloadingEnabledHWM.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @key gc
+ * @bug 8049831
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestCMSClassUnloadingEnabledHWM AllocateBeyondMetaspaceSize
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestCMSClassUnloadingEnabledHWM
+ * @summary Test that -XX:-CMSClassUnloadingEnabled will trigger a Full GC when more than MetaspaceSize metadata is allocated.
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class TestCMSClassUnloadingEnabledHWM {
+  private static long MetaspaceSize = 32 * 1024 * 1024;
+  private static long YoungGenSize  = 32 * 1024 * 1024;
+
+  private static OutputAnalyzer run(boolean enableUnloading) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-Xbootclasspath/a:.",
+      "-XX:+UnlockDiagnosticVMOptions",
+      "-XX:+WhiteBoxAPI",
+      "-XX:MetaspaceSize=" + MetaspaceSize,
+      "-Xmn" + YoungGenSize,
+      "-XX:+UseConcMarkSweepGC",
+      "-XX:" + (enableUnloading ? "+" : "-") + "CMSClassUnloadingEnabled",
+      "-XX:+PrintHeapAtGC",
+      "-XX:+PrintGCDetails",
+      "AllocateBeyondMetaspaceSize",
+      "" + MetaspaceSize,
+      "" + YoungGenSize);
+    return new OutputAnalyzer(pb.start());
+  }
+
+  public static OutputAnalyzer runWithCMSClassUnloading() throws Exception {
+    return run(true);
+  }
+
+  public static OutputAnalyzer runWithoutCMSClassUnloading() throws Exception {
+    return run(false);
+  }
+
+  public static void testWithoutCMSClassUnloading() throws Exception {
+    // -XX:-CMSClassUnloadingEnabled is used, so we expect a full GC instead of a concurrent cycle.
+    OutputAnalyzer out = runWithoutCMSClassUnloading();
+
+    out.shouldMatch(".*Full GC.*");
+    out.shouldNotMatch(".*CMS Initial Mark.*");
+  }
+
+  public static void testWithCMSClassUnloading() throws Exception {
+    // -XX:+CMSClassUnloadingEnabled is used, so we expect a concurrent cycle instead of a full GC.
+    OutputAnalyzer out = runWithCMSClassUnloading();
+
+    out.shouldMatch(".*CMS Initial Mark.*");
+    out.shouldNotMatch(".*Full GC.*");
+  }
+
+  public static void main(String args[]) throws Exception {
+    testWithCMSClassUnloading();
+    testWithoutCMSClassUnloading();
+  }
+}
+
diff --git a/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java
new file mode 100644
index 0000000..f4c830a
--- /dev/null
+++ b/hotspot/test/gc/class_unloading/TestG1ClassUnloadingHWM.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @key gc
+ * @bug 8049831
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestG1ClassUnloadingHWM AllocateBeyondMetaspaceSize
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestG1ClassUnloadingHWM
+ * @summary Test that -XX:-ClassUnloadingWithConcurrentMark will trigger a Full GC when more than MetaspaceSize metadata is allocated.
+ */
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+public class TestG1ClassUnloadingHWM {
+  private static long MetaspaceSize = 32 * 1024 * 1024;
+  private static long YoungGenSize  = 32 * 1024 * 1024;
+
+  private static OutputAnalyzer run(boolean enableUnloading) throws Exception {
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+      "-Xbootclasspath/a:.",
+      "-XX:+UnlockDiagnosticVMOptions",
+      "-XX:+WhiteBoxAPI",
+      "-XX:MetaspaceSize=" + MetaspaceSize,
+      "-Xmn" + YoungGenSize,
+      "-XX:+UseG1GC",
+      "-XX:" + (enableUnloading ? "+" : "-") + "ClassUnloadingWithConcurrentMark",
+      "-XX:+PrintHeapAtGC",
+      "-XX:+PrintGCDetails",
+      "AllocateBeyondMetaspaceSize",
+      "" + MetaspaceSize,
+      "" + YoungGenSize);
+    return new OutputAnalyzer(pb.start());
+  }
+
+  public static OutputAnalyzer runWithG1ClassUnloading() throws Exception {
+    return run(true);
+  }
+
+  public static OutputAnalyzer runWithoutG1ClassUnloading() throws Exception {
+    return run(false);
+  }
+
+  public static void testWithoutG1ClassUnloading() throws Exception {
+    // -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC instead of a concurrent cycle.
+    OutputAnalyzer out = runWithoutG1ClassUnloading();
+
+    out.shouldMatch(".*Full GC.*");
+    out.shouldNotMatch(".*initial-mark.*");
+  }
+
+  public static void testWithG1ClassUnloading() throws Exception {
+    // -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle instead of a full GC.
+    OutputAnalyzer out = runWithG1ClassUnloading();
+
+    out.shouldMatch(".*initial-mark.*");
+    out.shouldNotMatch(".*Full GC.*");
+  }
+
+  public static void main(String args[]) throws Exception {
+    testWithG1ClassUnloading();
+    testWithoutG1ClassUnloading();
+  }
+}
+
diff --git a/hotspot/test/gc/g1/TestDeferredRSUpdate.java b/hotspot/test/gc/g1/TestDeferredRSUpdate.java
new file mode 100644
index 0000000..f00967d
--- /dev/null
+++ b/hotspot/test/gc/g1/TestDeferredRSUpdate.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestDeferredRSUpdate
+ * @bug 8040977 8052170
+ * @summary Ensure that running with -XX:-G1DeferredRSUpdate does not crash the VM
+ * @key gc
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class TestDeferredRSUpdate {
+  public static void main(String[] args) throws Exception {
+    GCTest.main(args);
+
+    ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
+                                                              "-Xmx10M",
+                                                              "-XX:+PrintGCDetails",
+                                                              // G1DeferredRSUpdate is a develop option, but we cannot limit execution of this test to only debug VMs.
+                                                              "-XX:+IgnoreUnrecognizedVMOptions",
+                                                              "-XX:-G1DeferredRSUpdate",
+                                                              GCTest.class.getName());
+
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    output.shouldHaveExitValue(0);
+  }
+
+  static class GCTest {
+    private static Object[] garbage = new Object[32];
+
+    public static void main(String [] args) {
+      System.out.println("Creating garbage");
+      // Create 128MB of garbage. This should result in at least one minor GC, with
+      // some objects copied to old gen. As references from old to young are installed,
+      // the crash due to the use before initialize occurs.
+      Object prev = null;
+      Object prevPrev = null;
+      for (int i = 0; i < 1024; i++) {
+        Object[] next = new Object[32 * 1024];
+        next[0] = prev;
+        next[1] = prevPrev;
+
+        Object[] cur = (Object[]) garbage[i % garbage.length];
+        if (cur != null) {
+          cur[0] = null;
+          cur[1] = null;
+        }
+        garbage[i % garbage.length] = next;
+
+        prevPrev = prev;
+        prev = next;
+      }
+      System.out.println("Done");
+    }
+  }
+}
diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java
new file mode 100644
index 0000000..b920e7a
--- /dev/null
+++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestEagerReclaimHumongousRegions
+ * @bug 8027959
+ * @summary Test to make sure that eager reclaim of humongous objects work. We simply try to fill
+ * up the heap with humongous objects that should be eagerly reclaimable to avoid Full GC.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.LinkedList;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.Asserts;
+
+class ReclaimRegionFast {
+    public static final int M = 1024*1024;
+
+    public static LinkedList<Object> garbageList = new LinkedList<Object>();
+
+    public static void genGarbage() {
+        for (int i = 0; i < 32*1024; i++) {
+            garbageList.add(new int[100]);
+        }
+        garbageList.clear();
+    }
+
+    // A large object referenced by a static.
+    static int[] filler = new int[10 * M];
+
+    public static void main(String[] args) {
+
+        int[] large = new int[M];
+
+        Object ref_from_stack = large;
+
+        for (int i = 0; i < 100; i++) {
+            // A large object that will be reclaimed eagerly.
+            large = new int[6*M];
+            genGarbage();
+            // Make sure that the compiler cannot completely remove
+            // the allocation of the large object until here.
+            System.out.println(large);
+        }
+
+        // Keep the reference to the first object alive.
+        System.out.println(ref_from_stack);
+    }
+}
+
+public class TestEagerReclaimHumongousRegions {
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UseG1GC",
+            "-Xms128M",
+            "-Xmx128M",
+            "-Xmn16M",
+            "-XX:+PrintGC",
+            ReclaimRegionFast.class.getName());
+
+        Pattern p = Pattern.compile("Full GC");
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+
+        int found = 0;
+        Matcher m = p.matcher(output.getStdout());
+        while (m.find()) { found++; }
+        System.out.println("Issued " + found + " Full GCs");
+        Asserts.assertLT(found, 10, "Found that " + found + " Full GCs were issued. This is larger than the bound. Eager reclaim seems to not work at all");
+
+        output.shouldHaveExitValue(0);
+    }
+}
diff --git a/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java
new file mode 100644
index 0000000..dafbde0
--- /dev/null
+++ b/hotspot/test/gc/g1/TestEagerReclaimHumongousRegions2.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestEagerReclaimHumongousRegions2
+ * @bug 8051973
+ * @summary Test to make sure that eager reclaim of humongous objects correctly clears
+ * mark bitmaps at reclaim.
+ * @key gc
+ * @library /testlibrary
+ */
+
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.Random;
+
+import com.oracle.java.testlibrary.OutputAnalyzer;
+import com.oracle.java.testlibrary.ProcessTools;
+
+// An object that has a few references to other instances to slow down marking.
+class ObjectWithSomeRefs {
+    public ObjectWithSomeRefs other1;
+    public ObjectWithSomeRefs other2;
+    public ObjectWithSomeRefs other3;
+    public ObjectWithSomeRefs other4;
+}
+
+class ReclaimRegionFast {
+    public static final long MAX_MILLIS_FOR_RUN = 50 * 1000; // The maximum runtime for the actual test.
+
+    public static final int M = 1024*1024;
+
+    public static LinkedList<Object> garbageList = new LinkedList<Object>();
+
+    public static void genGarbage(Object large) {
+        for (int i = 0; i < 64*1024; i++) {
+            Object[] garbage = new Object[50];
+            garbage[0] = large;
+            garbageList.add(garbage);
+        }
+        garbageList.clear();
+    }
+
+    public static ArrayList<ObjectWithSomeRefs> longList = new ArrayList<ObjectWithSomeRefs>();
+
+    public static void main(String[] args) {
+
+        for (int i = 0; i < 16*1024; i++) {
+             longList.add(new ObjectWithSomeRefs());
+        }
+
+        Random rnd = new Random();
+        for (int i = 0; i < longList.size(); i++) {
+             int len = longList.size();
+             longList.get(i).other1 = longList.get(rnd.nextInt(len));
+             longList.get(i).other2 = longList.get(rnd.nextInt(len));
+             longList.get(i).other3 = longList.get(rnd.nextInt(len));
+             longList.get(i).other4 = longList.get(rnd.nextInt(len));
+        }
+
+        int[] large1 = new int[M];
+        int[] large2 = null;
+        int[] large3 = null;
+        int[] large4 = null;
+
+        Object ref_from_stack = large1;
+
+        long start_millis = System.currentTimeMillis();
+
+        for (int i = 0; i < 20; i++) {
+            long current_millis = System.currentTimeMillis();
+            if ((current_millis - start_millis) > MAX_MILLIS_FOR_RUN) {
+              System.out.println("Finishing test because maximum runtime exceeded");
+              break;
+            }
+            // A set of large objects that will be reclaimed eagerly - and hopefully marked.
+            large1 = new int[M - 20];
+            large2 = new int[M - 20];
+            large3 = new int[M - 20];
+            large4 = new int[M - 20];
+            genGarbage(large1);
+            // Make sure that the compiler cannot completely remove
+            // the allocation of the large object until here.
+            System.out.println(large1 + " " + large2 + " " + large3 + " " + large4);
+        }
+
+        // Keep the reference to the first object alive.
+        System.out.println(ref_from_stack);
+    }
+}
+
+public class TestEagerReclaimHumongousRegions2 {
+    public static void main(String[] args) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-XX:+UseG1GC",
+            "-Xms128M",
+            "-Xmx128M",
+            "-Xmn2M",
+            "-XX:G1HeapRegionSize=1M",
+            "-XX:InitiatingHeapOccupancyPercent=0", // Want to have as much as possible initial marks.
+            "-XX:+PrintGC",
+            "-XX:+VerifyAfterGC",
+            "-XX:ConcGCThreads=1", // Want to make marking as slow as possible.
+            "-XX:+IgnoreUnrecognizedVMOptions", // G1VerifyBitmaps is develop only.
+            "-XX:+G1VerifyBitmaps",
+            ReclaimRegionFast.class.getName());
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        output.shouldHaveExitValue(0);
+    }
+}
+
diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java
index 06ce2ca..ee33801 100644
--- a/hotspot/test/gc/g1/TestGCLogMessages.java
+++ b/hotspot/test/gc/g1/TestGCLogMessages.java
@@ -22,8 +22,8 @@
  */
 
 /*
- * @test TestPrintGCDetails
- * @bug 8035406 8027295 8035398
+ * @test TestGCLogMessages
+ * @bug 8035406 8027295 8035398 8019342 8027959
  * @summary Ensure that the PrintGCDetails output for a minor GC with G1
  * includes the expected necessary messages.
  * @key gc
@@ -48,10 +48,13 @@
     OutputAnalyzer output = new OutputAnalyzer(pb.start());
 
     output.shouldNotContain("[Redirty Cards");
+    output.shouldNotContain("[Parallel Redirty");
+    output.shouldNotContain("[Redirtied Cards");
     output.shouldNotContain("[Code Root Purge");
     output.shouldNotContain("[String Dedup Fixup");
     output.shouldNotContain("[Young Free CSet");
     output.shouldNotContain("[Non-Young Free CSet");
+    output.shouldNotContain("[Humongous Reclaim");
     output.shouldHaveExitValue(0);
 
     pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
@@ -63,10 +66,16 @@
     output = new OutputAnalyzer(pb.start());
 
     output.shouldContain("[Redirty Cards");
+    output.shouldNotContain("[Parallel Redirty");
+    output.shouldNotContain("[Redirtied Cards");
     output.shouldContain("[Code Root Purge");
     output.shouldContain("[String Dedup Fixup");
     output.shouldNotContain("[Young Free CSet");
     output.shouldNotContain("[Non-Young Free CSet");
+    output.shouldContain("[Humongous Reclaim");
+    output.shouldNotContain("[Humongous Total");
+    output.shouldNotContain("[Humongous Candidate");
+    output.shouldNotContain("[Humongous Reclaimed");
     output.shouldHaveExitValue(0);
 
     pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
@@ -80,16 +89,16 @@
     output = new OutputAnalyzer(pb.start());
 
     output.shouldContain("[Redirty Cards");
+    output.shouldContain("[Parallel Redirty");
+    output.shouldContain("[Redirtied Cards");
     output.shouldContain("[Code Root Purge");
     output.shouldContain("[String Dedup Fixup");
     output.shouldContain("[Young Free CSet");
     output.shouldContain("[Non-Young Free CSet");
-
-    // also check evacuation failure messages once
-    output.shouldNotContain("[Evacuation Failure");
-    output.shouldNotContain("[Recalculate Used");
-    output.shouldNotContain("[Remove Self Forwards");
-    output.shouldNotContain("[Restore RemSet");
+    output.shouldContain("[Humongous Reclaim");
+    output.shouldContain("[Humongous Total");
+    output.shouldContain("[Humongous Candidate");
+    output.shouldContain("[Humongous Reclaimed");
     output.shouldHaveExitValue(0);
   }
 
diff --git a/hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java b/hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java
index 096a7c6..1ab8322 100644
--- a/hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java
+++ b/hotspot/test/gc/g1/TestSummarizeRSetStatsTools.java
@@ -88,7 +88,6 @@
         ArrayList<String> finalargs = new ArrayList<String>();
         String[] defaultArgs = new String[] {
             "-XX:+UseG1GC",
-            "-XX:+UseCompressedOops",
             "-Xmn4m",
             "-Xmx20m",
             "-XX:InitiatingHeapOccupancyPercent=100", // we don't want the additional GCs due to initial marking
diff --git a/hotspot/test/gc/logging/TestGCId.java b/hotspot/test/gc/logging/TestGCId.java
new file mode 100644
index 0000000..728a128
--- /dev/null
+++ b/hotspot/test/gc/logging/TestGCId.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestGCId
+ * @bug 8043607
+ * @summary Ensure that the GCId is logged
+ * @key gc
+ * @library /testlibrary
+ */
+
+import com.oracle.java.testlibrary.ProcessTools;
+import com.oracle.java.testlibrary.OutputAnalyzer;
+
+public class TestGCId {
+  public static void main(String[] args) throws Exception {
+    testGCId("UseParallelGC", "PrintGC");
+    testGCId("UseParallelGC", "PrintGCDetails");
+
+    testGCId("UseG1GC", "PrintGC");
+    testGCId("UseG1GC", "PrintGCDetails");
+
+    testGCId("UseConcMarkSweepGC", "PrintGC");
+    testGCId("UseConcMarkSweepGC", "PrintGCDetails");
+
+    testGCId("UseSerialGC", "PrintGC");
+    testGCId("UseSerialGC", "PrintGCDetails");
+  }
+
+  private static void verifyContainsGCIDs(OutputAnalyzer output) {
+    output.shouldMatch("^#0: \\[");
+    output.shouldMatch("^#1: \\[");
+    output.shouldHaveExitValue(0);
+  }
+
+  private static void verifyContainsNoGCIDs(OutputAnalyzer output) {
+    output.shouldNotMatch("^#[0-9]+: \\[");
+    output.shouldHaveExitValue(0);
+  }
+
+  private static void testGCId(String gcFlag, String logFlag) throws Exception {
+    // GCID logging enabled
+    ProcessBuilder pb_enabled =
+      ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-XX:+" + logFlag, "-Xmx10M", "-XX:+PrintGCID", GCTest.class.getName());
+    verifyContainsGCIDs(new OutputAnalyzer(pb_enabled.start()));
+
+    // GCID logging disabled
+    ProcessBuilder pb_disabled =
+      ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-XX:+" + logFlag, "-Xmx10M", "-XX:-PrintGCID", GCTest.class.getName());
+    verifyContainsNoGCIDs(new OutputAnalyzer(pb_disabled.start()));
+
+    // GCID logging default
+    ProcessBuilder pb_default =
+      ProcessTools.createJavaProcessBuilder("-XX:+" + gcFlag, "-XX:+" + logFlag, "-Xmx10M", GCTest.class.getName());
+    verifyContainsNoGCIDs(new OutputAnalyzer(pb_default.start()));
+  }
+
+  static class GCTest {
+    private static byte[] garbage;
+    public static void main(String [] args) {
+      System.out.println("Creating garbage");
+      // create 128MB of garbage. This should result in at least one GC
+      for (int i = 0; i < 1024; i++) {
+        garbage = new byte[128 * 1024];
+      }
+      // do a system gc to get one more gc
+      System.gc();
+      System.out.println("Done");
+    }
+  }
+}
diff --git a/hotspot/test/gc/whitebox/TestWBGC.java b/hotspot/test/gc/whitebox/TestWBGC.java
new file mode 100644
index 0000000..8cdb74b
--- /dev/null
+++ b/hotspot/test/gc/whitebox/TestWBGC.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test TestWBGC
+ * @bug 8055098
+ * @summary Test verify that WB methods isObjectInOldGen and youngGC works correctly.
+ * @library /testlibrary /testlibrary/whitebox
+ * @build TestWBGC
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run driver TestWBGC
+ */
+import com.oracle.java.testlibrary.*;
+import sun.hotspot.WhiteBox;
+
+public class TestWBGC {
+
+    public static void main(String args[]) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+                true,
+                "-Xbootclasspath/a:.",
+                "-XX:+UnlockDiagnosticVMOptions",
+                "-XX:+WhiteBoxAPI",
+                "-XX:MaxTenuringThreshold=1",
+                "-XX:+PrintGC",
+                GCYoungTest.class.getName());
+
+        OutputAnalyzer output = new OutputAnalyzer(pb.start());
+        System.out.println(output.getStdout());
+        output.shouldHaveExitValue(0);
+        output.shouldContain("WhiteBox Initiated Young GC");
+        output.shouldNotContain("Full");
+        // To be sure that we don't provoke Full GC additionaly to young
+    }
+
+    public static class GCYoungTest {
+        static WhiteBox wb = WhiteBox.getWhiteBox();
+        public static Object obj;
+
+        public static void main(String args[]) {
+            obj = new Object();
+            Asserts.assertFalse(wb.isObjectInOldGen(obj));
+            wb.youngGC();
+            wb.youngGC();
+            // 2 young GC is needed to promote object into OldGen
+            Asserts.assertTrue(wb.isObjectInOldGen(obj));
+        }
+    }
+}
diff --git a/hotspot/test/runtime/7116786/Test7116786.java b/hotspot/test/runtime/7116786/Test7116786.java
index b914019..48eaf44 100644
--- a/hotspot/test/runtime/7116786/Test7116786.java
+++ b/hotspot/test/runtime/7116786/Test7116786.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -147,7 +147,8 @@
                  "no stackmap frame at jump location or bad jump",
                  "Inconsistent stackmap frames at branch target "),
 
-        new Case("case15", "stackMapTable.cpp", true, "check_new_object",
+        /* Backward jump with uninit is allowed starting with JDK 8 */
+        new Case("case15", "stackMapTable.cpp", false, "check_new_object",
                  "backward jump with uninit",
                  "Uninitialized object exists on backward branch "),
 
diff --git a/hotspot/test/runtime/NMT/BaselineWithParameter.java b/hotspot/test/runtime/NMT/BaselineWithParameter.java
index ff10b28..ef34a11 100644
--- a/hotspot/test/runtime/NMT/BaselineWithParameter.java
+++ b/hotspot/test/runtime/NMT/BaselineWithParameter.java
@@ -27,6 +27,7 @@
  * @key nmt jcmd regression
  * @summary Regression test for invoking a jcmd with baseline=false, result was that the target VM crashed
  * @library /testlibrary
+ * @ignore
  * @run main/othervm -XX:NativeMemoryTracking=detail BaselineWithParameter
  */
 
diff --git a/hotspot/test/runtime/NMT/CommandLineDetail.java b/hotspot/test/runtime/NMT/CommandLineDetail.java
index 0151b48..4eb6aa7 100644
--- a/hotspot/test/runtime/NMT/CommandLineDetail.java
+++ b/hotspot/test/runtime/NMT/CommandLineDetail.java
@@ -26,6 +26,7 @@
  * @key nmt
  * @summary Running with NMT detail should not result in an error
  * @library /testlibrary
+ * @ignore
  */
 
 import com.oracle.java.testlibrary.*;
diff --git a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java
index 956cdd2..1c05a19 100644
--- a/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java
+++ b/hotspot/test/runtime/NMT/CommandLineEmptyArgument.java
@@ -26,6 +26,7 @@
  * @key nmt
  * @summary Empty argument to NMT should result in an informative error message
  * @library /testlibrary
+ * @ignore
  */
 
 import com.oracle.java.testlibrary.*;
diff --git a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java
index 79cc2de..6cc4510 100644
--- a/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java
+++ b/hotspot/test/runtime/NMT/CommandLineInvalidArgument.java
@@ -26,6 +26,7 @@
  * @key nmt
  * @summary Invalid argument to NMT should result in an informative error message
  * @library /testlibrary
+ * @ignore
  */
 
 import com.oracle.java.testlibrary.*;
diff --git a/hotspot/test/runtime/NMT/CommandLineSummary.java b/hotspot/test/runtime/NMT/CommandLineSummary.java
index 9680c34..7468a61 100644
--- a/hotspot/test/runtime/NMT/CommandLineSummary.java
+++ b/hotspot/test/runtime/NMT/CommandLineSummary.java
@@ -26,6 +26,7 @@
  * @key nmt
  * @summary Running with NMT summary should not result in an error
  * @library /testlibrary
+ * @ignore
  */
 
 import com.oracle.java.testlibrary.*;
diff --git a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java
index 7b8f8be..06962aa 100644
--- a/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java
+++ b/hotspot/test/runtime/NMT/CommandLineTurnOffNMT.java
@@ -26,6 +26,7 @@
  * @key nmt
  * @summary Turning off NMT should not result in an error
  * @library /testlibrary
+ * @ignore
  */
 
 import com.oracle.java.testlibrary.*;
diff --git a/hotspot/test/runtime/NMT/JcmdScale.java b/hotspot/test/runtime/NMT/JcmdScale.java
index e57d27b..42b7393 100644
--- a/hotspot/test/runtime/NMT/JcmdScale.java
+++ b/hotspot/test/runtime/NMT/JcmdScale.java
@@ -26,6 +26,7 @@
  * @key nmt jcmd
  * @summary Test the NMT scale parameter
  * @library /testlibrary
+ * @ignore
  * @run main/othervm -XX:NativeMemoryTracking=summary JcmdScale
  */
 
@@ -41,15 +42,15 @@
 
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=KB"});
     output = new OutputAnalyzer(pb.start());
-    output.shouldContain("KB,  committed=");
+    output.shouldContain("KB, committed=");
 
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=MB"});
     output = new OutputAnalyzer(pb.start());
-    output.shouldContain("MB,  committed=");
+    output.shouldContain("MB, committed=");
 
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=GB"});
     output = new OutputAnalyzer(pb.start());
-    output.shouldContain("GB,  committed=");
+    output.shouldContain("GB, committed=");
 
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "scale=apa"});
     output = new OutputAnalyzer(pb.start());
@@ -57,7 +58,7 @@
 
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=GB"});
     output = new OutputAnalyzer(pb.start());
-    output.shouldContain("GB,  committed=");
+    output.shouldContain("GB, committed=");
 
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary", "scale=apa"});
     output = new OutputAnalyzer(pb.start());
diff --git a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java
index 7b58a84..103a539 100644
--- a/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java
+++ b/hotspot/test/runtime/NMT/JcmdWithNMTDisabled.java
@@ -26,6 +26,7 @@
  * @key nmt jcmd
  * @summary Verify that jcmd correctly reports that NMT is not enabled
  * @library /testlibrary
+ * @ignore
  * First run without enabling NMT
  * @run main/othervm JcmdWithNMTDisabled
  * Then run with explicitly disabling NMT, should not be any difference
diff --git a/hotspot/test/runtime/NMT/MallocTestType.java b/hotspot/test/runtime/NMT/MallocTestType.java
index 8a39af7..444dfda 100644
--- a/hotspot/test/runtime/NMT/MallocTestType.java
+++ b/hotspot/test/runtime/NMT/MallocTestType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -27,6 +27,7 @@
  * @key nmt jcmd
  * @library /testlibrary /testlibrary/whitebox
  * @build MallocTestType
+ * @ignore
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTestType
  */
@@ -51,11 +52,6 @@
     long memAlloc1 = wb.NMTMalloc(512 * 1024);
     wb.NMTFree(memAlloc2);
 
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!wb.NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
-
     // Run 'jcmd <pid> VM.native_memory summary'
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
     output = new OutputAnalyzer(pb.start());
@@ -64,10 +60,6 @@
     // Free the memory allocated by NMTAllocTest
     wb.NMTFree(memAlloc1);
 
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!wb.NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
     output = new OutputAnalyzer(pb.start());
     output.shouldNotContain("Test (reserved=");
   }
diff --git a/hotspot/test/runtime/NMT/NMTWithCDS.java b/hotspot/test/runtime/NMT/NMTWithCDS.java
new file mode 100644
index 0000000..574143c
--- /dev/null
+++ b/hotspot/test/runtime/NMT/NMTWithCDS.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8055061
+ * @key nmt
+ * @library /testlibrary
+ * @ignore
+ * @run main NMTWithCDS
+ */
+import com.oracle.java.testlibrary.*;
+
+public class NMTWithCDS {
+
+  public static void main(String[] args) throws Exception {
+    ProcessBuilder pb;
+    pb = ProcessTools.createJavaProcessBuilder("-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump");
+    OutputAnalyzer output = new OutputAnalyzer(pb.start());
+    try {
+      output.shouldContain("Loading classes to share");
+      output.shouldHaveExitValue(0);
+
+      pb = ProcessTools.createJavaProcessBuilder(
+        "-XX:NativeMemoryTracking=detail", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version");
+      output = new OutputAnalyzer(pb.start());
+      output.shouldContain("sharing");
+      output.shouldHaveExitValue(0);
+
+    } catch (RuntimeException e) {
+      // Report 'passed' if CDS was turned off.
+      output.shouldContain("Unable to use shared archive");
+      output.shouldHaveExitValue(1);
+    }
+  }
+}
diff --git a/hotspot/test/runtime/NMT/PrintNMTStatistics.java b/hotspot/test/runtime/NMT/PrintNMTStatistics.java
index fc039d6..394094e 100644
--- a/hotspot/test/runtime/NMT/PrintNMTStatistics.java
+++ b/hotspot/test/runtime/NMT/PrintNMTStatistics.java
@@ -28,6 +28,7 @@
  * @summary Make sure PrintNMTStatistics works on normal JVM exit
  * @library /testlibrary /testlibrary/whitebox
  * @build PrintNMTStatistics
+ * @ignore
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main PrintNMTStatistics
  */
@@ -45,10 +46,6 @@
     // We start a new java process running with an argument and use WB API to ensure
     // we have data for NMT on VM exit
     if (args.length > 0) {
-      // Use WB API to ensure that all data has been merged before we continue
-      if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
-        throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-      }
       return;
     }
 
diff --git a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java
index 1c25f28..cdc3ded 100644
--- a/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java
+++ b/hotspot/test/runtime/NMT/PrintNMTStatisticsWithNMTDisabled.java
@@ -26,6 +26,7 @@
  * @key nmt
  * @summary Trying to enable PrintNMTStatistics should result in a warning
  * @library /testlibrary
+ * @ignore
  */
 
 import com.oracle.java.testlibrary.*;
diff --git a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java
index 66bc3b1..1f8592a 100644
--- a/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java
+++ b/hotspot/test/runtime/NMT/ReleaseCommittedMemory.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -28,6 +28,7 @@
  * @key nmt regression
  * @library /testlibrary /testlibrary/whitebox
  * @build ReleaseCommittedMemory
+ * @ignore
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ReleaseCommittedMemory
  */
@@ -44,7 +45,6 @@
     addr = wb.NMTReserveMemory(reserveSize);
     wb.NMTCommitMemory(addr, 128*1024);
     wb.NMTReleaseMemory(addr, reserveSize);
-    wb.NMTWaitForDataMerge();
   }
 }
 
diff --git a/hotspot/test/runtime/NMT/ShutdownTwice.java b/hotspot/test/runtime/NMT/ShutdownTwice.java
index 1bb327a..d6dcf80 100644
--- a/hotspot/test/runtime/NMT/ShutdownTwice.java
+++ b/hotspot/test/runtime/NMT/ShutdownTwice.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
  * @key nmt jcmd
  * @summary Run shutdown twice
  * @library /testlibrary
+ * @ignore
  * @run main/othervm -XX:NativeMemoryTracking=detail ShutdownTwice
  */
 
@@ -45,12 +46,12 @@
     output = new OutputAnalyzer(pb.start());
 
     // Verify that jcmd reports that NMT is shutting down
-    output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown");
+    output.shouldContain("Native memory tracking has been turned off");
 
     // Run shutdown again
     output = new OutputAnalyzer(pb.start());
 
     // Verify that jcmd reports that NMT has been shutdown already
-    output.shouldContain("Native memory tracking has been shutdown by user");
+    output.shouldContain("Native memory tracking has been shutdown");
   }
 }
diff --git a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java
index 96061f3..1baa484 100644
--- a/hotspot/test/runtime/NMT/SummaryAfterShutdown.java
+++ b/hotspot/test/runtime/NMT/SummaryAfterShutdown.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
  * @key nmt jcmd
  * @summary Verify that jcmd correctly reports that NMT is not enabled after a shutdown
  * @library /testlibrary
+ * @ignore
  * @run main/othervm -XX:NativeMemoryTracking=detail SummaryAfterShutdown
  */
 
@@ -44,13 +45,13 @@
     output = new OutputAnalyzer(pb.start());
 
     // Verify that jcmd reports that NMT is shutting down
-    output.shouldContain("Shutdown is in progress, it will take a few moments to completely shutdown");
+    output.shouldContain("Native memory tracking has been turned off");
 
     // Run 'jcmd <pid> VM.native_memory summary'
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
     output = new OutputAnalyzer(pb.start());
 
     // Verify that jcmd reports that NMT has been shutdown
-    output.shouldContain("Native memory tracking has been shutdown by user");
+    output.shouldContain("Native memory tracking has been shutdown");
   }
 }
diff --git a/hotspot/test/runtime/NMT/SummarySanityCheck.java b/hotspot/test/runtime/NMT/SummarySanityCheck.java
index 221ad93..1f37e47 100644
--- a/hotspot/test/runtime/NMT/SummarySanityCheck.java
+++ b/hotspot/test/runtime/NMT/SummarySanityCheck.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -27,6 +27,7 @@
  * @summary Sanity check the output of NMT
  * @library /testlibrary /testlibrary/whitebox
  * @build SummarySanityCheck
+ * @ignore
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:NativeMemoryTracking=summary -XX:+WhiteBoxAPI SummarySanityCheck
  */
@@ -44,11 +45,6 @@
     // Grab my own PID
     String pid = Integer.toString(ProcessTools.getProcessId());
 
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!WhiteBox.getWhiteBox().NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
-
     ProcessBuilder pb = new ProcessBuilder();
 
     // Run  'jcmd <pid> VM.native_memory summary scale=KB'
@@ -69,13 +65,13 @@
     // Match '- <mtType> (reserved=<reserved>KB, committed=<committed>KB)
     Pattern mtTypePattern = Pattern.compile("-\\s+(?<typename>[\\w\\s]+)\\(reserved=(?<reserved>\\d+)KB,\\scommitted=(?<committed>\\d+)KB\\)");
     // Match 'Total: reserved=<reserved>KB, committed=<committed>KB'
-    Pattern totalMemoryPattern = Pattern.compile("Total\\:\\s\\sreserved=(?<reserved>\\d+)KB,\\s\\scommitted=(?<committed>\\d+)KB");
+    Pattern totalMemoryPattern = Pattern.compile("Total\\:\\sreserved=(?<reserved>\\d+)KB,\\scommitted=(?<committed>\\d+)KB");
 
     for (int i = 0; i < lines.length; i++) {
       if (lines[i].startsWith("Total")) {
         Matcher totalMemoryMatcher = totalMemoryPattern.matcher(lines[i]);
 
-        if (totalMemoryMatcher.matches() && totalMemoryMatcher.groupCount() == 2) {
+        if (totalMemoryMatcher.matches()) {
           totalCommitted = Integer.parseInt(totalMemoryMatcher.group("committed"));
           totalReserved = Integer.parseInt(totalMemoryMatcher.group("reserved"));
         } else {
diff --git a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java
index eadb719..82d98c5 100644
--- a/hotspot/test/runtime/NMT/ThreadedMallocTestType.java
+++ b/hotspot/test/runtime/NMT/ThreadedMallocTestType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
  * @key nmt jcmd
  * @library /testlibrary /testlibrary/whitebox
  * @build ThreadedMallocTestType
+ * @ignore
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedMallocTestType
  */
@@ -58,11 +59,6 @@
     allocThread.start();
     allocThread.join();
 
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!wb.NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
-
     // Run 'jcmd <pid> VM.native_memory summary'
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary"});
     output = new OutputAnalyzer(pb.start());
@@ -80,11 +76,6 @@
     freeThread.start();
     freeThread.join();
 
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!wb.NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
-    }
-
     output = new OutputAnalyzer(pb.start());
     output.shouldNotContain("Test (reserved=");
   }
diff --git a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java
index 1a7b929..3f9ab7c 100644
--- a/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java
+++ b/hotspot/test/runtime/NMT/ThreadedVirtualAllocTestType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
  * @key nmt jcmd
  * @library /testlibrary /testlibrary/whitebox
  * @build ThreadedVirtualAllocTestType
+ * @ignore
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail ThreadedVirtualAllocTestType
  */
@@ -60,8 +61,6 @@
     reserveThread.start();
     reserveThread.join();
 
-    mergeData();
-
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
     output = new OutputAnalyzer(pb.start());
     output.shouldContain("Test (reserved=512KB, committed=0KB)");
@@ -77,8 +76,6 @@
     commitThread.start();
     commitThread.join();
 
-    mergeData();
-
     output = new OutputAnalyzer(pb.start());
     output.shouldContain("Test (reserved=512KB, committed=128KB)");
     if (has_nmt_detail) {
@@ -93,8 +90,6 @@
     uncommitThread.start();
     uncommitThread.join();
 
-    mergeData();
-
     output = new OutputAnalyzer(pb.start());
     output.shouldContain("Test (reserved=512KB, committed=0KB)");
     output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
@@ -107,17 +102,9 @@
     releaseThread.start();
     releaseThread.join();
 
-    mergeData();
-
     output = new OutputAnalyzer(pb.start());
     output.shouldNotContain("Test (reserved=");
     output.shouldNotContain("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
   }
 
-  public static void mergeData() throws Exception {
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!wb.NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
     }
-  }
-}
diff --git a/hotspot/test/runtime/NMT/VirtualAllocTestType.java b/hotspot/test/runtime/NMT/VirtualAllocTestType.java
index 86e751c..f69f5ba 100644
--- a/hotspot/test/runtime/NMT/VirtualAllocTestType.java
+++ b/hotspot/test/runtime/NMT/VirtualAllocTestType.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,6 +26,7 @@
  * @summary Test Reserve/Commit/Uncommit/Release of virtual memory and that we track it correctly
  * @key nmt jcmd
  * @library /testlibrary /testlibrary/whitebox
+ * @ignore
  * @build VirtualAllocTestType
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail VirtualAllocTestType
@@ -54,7 +55,6 @@
     }
 
     addr = wb.NMTReserveMemory(reserveSize);
-    mergeData();
     pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "detail"});
 
     output = new OutputAnalyzer(pb.start());
@@ -65,7 +65,6 @@
 
     wb.NMTCommitMemory(addr, commitSize);
 
-    mergeData();
 
     output = new OutputAnalyzer(pb.start());
     output.shouldContain("Test (reserved=256KB, committed=128KB)");
@@ -75,24 +74,15 @@
 
     wb.NMTUncommitMemory(addr, commitSize);
 
-    mergeData();
 
     output = new OutputAnalyzer(pb.start());
     output.shouldContain("Test (reserved=256KB, committed=0KB)");
     output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + commitSize) + "\\] committed");
 
     wb.NMTReleaseMemory(addr, reserveSize);
-    mergeData();
 
     output = new OutputAnalyzer(pb.start());
     output.shouldNotContain("Test (reserved=");
     output.shouldNotMatch("\\[0x[0]*" + Long.toHexString(addr) + " - 0x[0]*" + Long.toHexString(addr + reserveSize) + "\\] reserved");
   }
-
-  public static void mergeData() throws Exception {
-    // Use WB API to ensure that all data has been merged before we continue
-    if (!wb.NMTWaitForDataMerge()) {
-      throw new Exception("Call to WB API NMTWaitForDataMerge() failed");
     }
-  }
-}
diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOption.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOption.java
new file mode 100644
index 0000000..49671ef
--- /dev/null
+++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOption.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 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.
+ */
+package com.oracle.java.testlibrary;
+
+import com.sun.management.HotSpotDiagnosticMXBean;
+import java.lang.management.ManagementFactory;
+
+/**
+ * A utility class to work with VM options which could be altered during
+ * execution.
+ *
+ * This class is a wrapper around {@code com.sun.management.VMOption}.
+ * It provides more convenient interface to read/write the values.
+ *
+ */
+public class DynamicVMOption {
+
+    private final HotSpotDiagnosticMXBean mxBean;
+
+    /**
+     * VM option name, like "MinHeapFreeRatio".
+     */
+    public final String name;
+
+    /**
+     * Creates an instance of DynamicVMOption.
+     *
+     * @param name the VM option name
+     */
+    public DynamicVMOption(String name) {
+        this.name = name;
+        mxBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class);
+    }
+
+    /**
+     * Sets a new value for the option.
+     * Trying to set not applicable value will cause IllegalArgumentException.
+     * Behavior with null is undefined, most likely NPE will be thrown.
+     *
+     * @param newValue the value to be set
+     * @see #getValue()
+     * @throws IllegalArgumentException if newValue is not applicable to the option
+     */
+    public final void setValue(String newValue) {
+        mxBean.setVMOption(name, newValue);
+    }
+
+    /**
+     * Returns the value of option.
+     *
+     * @return the current option value
+     * @see #setValue(java.lang.String)
+     */
+    public final String getValue() {
+        return mxBean.getVMOption(name).getValue();
+    }
+
+    /**
+     * Returns true, if option is writable, false otherwise.
+     *
+     * @return true, if option is writable, false otherwise
+     */
+    public final boolean isWriteable() {
+        return mxBean.getVMOption(name).isWriteable();
+    }
+
+    /**
+     * Checks if the given value is applicable for the option.
+     *
+     * This method tries to set the option to the new value. If no exception
+     * has been thrown the value is treated as valid.
+     *
+     * Calling this method will not change the option value. After an attempt
+     * to set a new value, the option will be restored to its previous value.
+     *
+     * @param value the value to verify
+     * @return true if option could be set to the given value
+     */
+    public boolean isValidValue(String value) {
+        boolean isValid = true;
+        String oldValue = getValue();
+        try {
+            setValue(value);
+        } catch (NullPointerException e) {
+            if (value == null) {
+                isValid = false;
+            }
+        } catch (IllegalArgumentException e) {
+            isValid = false;
+        } finally {
+            setValue(oldValue);
+        }
+        return isValid;
+    }
+
+    /**
+     * Returns the value of the given VM option as String.
+     *
+     * This is a simple shortcut for {@code new DynamicVMOption(name).getValue()}
+     *
+     * @param name the name of VM option
+     * @return value as a string
+     * @see #getValue()
+     */
+    public static String getString(String name) {
+        return new DynamicVMOption(name).getValue();
+    }
+
+    /**
+     * Returns the value of the given option as int.
+     *
+     * @param name the name of VM option
+     * @return value parsed as integer
+     * @see #getString(java.lang.String)
+     *
+     */
+    public static int getInt(String name) {
+        return Integer.parseInt(getString(name));
+    }
+
+    /**
+     * Sets the VM option to a new value.
+     *
+     * This is a simple shortcut for {@code new DynamicVMOption(name).setValue(value)}
+     *
+     * @param name the name of VM option
+     * @param value the value to be set
+     * @see #setValue(java.lang.String)
+     */
+    public static void setString(String name, String value) {
+        new DynamicVMOption(name).setValue(value);
+    }
+
+    /**
+     * Sets the VM option value to a new integer value.
+     *
+     * @param name the name of VM option
+     * @param value the integer value to be set
+     * @see #setString(java.lang.String, java.lang.String)
+     */
+    public static void setInt(String name, int value) {
+        new DynamicVMOption(name).setValue(Integer.toString(value));
+    }
+
+}
diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOptionChecker.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOptionChecker.java
deleted file mode 100644
index baa717d..0000000
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/DynamicVMOptionChecker.java
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package com.oracle.java.testlibrary;
-
-import com.sun.management.HotSpotDiagnosticMXBean;
-import com.sun.management.VMOption;
-import java.lang.management.ManagementFactory;
-
-/**
- * Simple class to check writeability, invalid and valid values for VMOption
- */
-public class DynamicVMOptionChecker {
-
-    /**
-     * Reads VM option from PlatformMXBean and parse it to integer value
-     *
-     * @param name of option
-     * @return parsed value
-     */
-    public static int getIntValue(String name) {
-
-        VMOption option = ManagementFactory.
-                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
-                getVMOption(name);
-
-        return Integer.parseInt(option.getValue());
-    }
-
-    /**
-     * Sets VM option value
-     *
-     * @param name of option
-     * @param value to set
-     */
-    public static void setIntValue(String name, int value) {
-        ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class).setVMOption(name, Integer.toString(value));
-    }
-
-    /**
-     * Checks that VM option is dynamically writable
-     *
-     * @param name
-     * @throws RuntimeException if option if not writable
-     * @return always true
-     */
-    public static boolean checkIsWritable(String name) {
-        VMOption option = ManagementFactory.
-                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
-                getVMOption(name);
-
-        if (!option.isWriteable()) {
-            throw new RuntimeException(name + " is not writable");
-        }
-
-        return true;
-    }
-
-    /**
-     * Checks that value cannot be set
-     *
-     * @param name of flag
-     * @param value string representation of value to set
-     * @throws RuntimeException on error - when expected exception hasn't been thrown
-     */
-    public static void checkInvalidValue(String name, String value) {
-        // should throw
-        try {
-            ManagementFactory.
-                    getPlatformMXBean(HotSpotDiagnosticMXBean.class).
-                    setVMOption(name, value);
-
-        } catch (IllegalArgumentException e) {
-            return;
-        }
-
-        throw new RuntimeException("Expected IllegalArgumentException was not thrown, " + name + "= " + value);
-    }
-
-    /**
-     * Checks that value can be set
-     *
-     * @param name of flag to set
-     * @param value string representation of value to set
-     * @throws RuntimeException on error - when value in VM is not equal to origin
-     */
-    public static void checkValidValue(String name, String value) {
-        ManagementFactory.
-                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
-                setVMOption(name, value);
-
-        VMOption option = ManagementFactory.
-                getPlatformMXBean(HotSpotDiagnosticMXBean.class).
-                getVMOption(name);
-
-        if (!option.getValue().equals(value)) {
-            throw new RuntimeException("Actual value of " + name + " \"" + option.getValue()
-                    + "\" not equal origin \"" + value + "\"");
-        }
-    }
-
-}
diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/TestDynamicVMOption.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/TestDynamicVMOption.java
deleted file mode 100644
index 2c16459..0000000
--- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/TestDynamicVMOption.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright (c) 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.
- */
-package com.oracle.java.testlibrary;
-
-/**
- * Simple class to check writeability, invalid and valid values for concrete VMOption
- */
-public class TestDynamicVMOption {
-
-    private final String name;
-    private final int value;
-
-    /**
-     * Constructor
-     *
-     * @param name of VM option to test
-     */
-    public TestDynamicVMOption(String name) {
-        this.name = name;
-        this.value = DynamicVMOptionChecker.getIntValue(name);
-        System.out.println(this.name + " = " + this.value);
-    }
-
-    /**
-     * Checks that this value can accept valid percentage values and cannot accept invalid percentage values
-     *
-     * @throws RuntimeException
-     */
-    public void testPercentageValues() {
-        checkInvalidValue(Integer.toString(Integer.MIN_VALUE));
-        checkInvalidValue(Integer.toString(Integer.MAX_VALUE));
-        checkInvalidValue("-10");
-        checkInvalidValue("190");
-    }
-
-    /**
-     * Reads VM option from PlatformMXBean and parse it to integer value
-     *
-     * @return value
-     */
-    public int getIntValue() {
-        return DynamicVMOptionChecker.getIntValue(this.name);
-    }
-
-    /**
-     * Sets VM option value
-     *
-     * @param value to set
-     */
-    public void setIntValue(int value) {
-        DynamicVMOptionChecker.setIntValue(this.name, value);
-    }
-
-    /**
-     * Checks that this VM option is dynamically writable
-     *
-     * @throws RuntimeException if option if not writable
-     * @return true
-     */
-    public boolean checkIsWritable() throws RuntimeException {
-        return DynamicVMOptionChecker.checkIsWritable(this.name);
-    }
-
-    /**
-     * Checks that value for this VM option cannot be set
-     *
-     * @param value to check
-     * @throws RuntimeException on error - when expected exception hasn't been thrown
-     */
-    public void checkInvalidValue(String value) {
-        DynamicVMOptionChecker.checkInvalidValue(this.name, value);
-    }
-
-    /**
-     * Checks that value for this VM option can be set
-     *
-     * @param value to check
-     * @throws RuntimeException on error - when value in VM is not equal to origin
-     */
-    public void checkValidValue(String value) {
-        DynamicVMOptionChecker.checkValidValue(this.name, value);
-    }
-
-}
diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
index e35260c..360d702 100644
--- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
+++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java
@@ -25,6 +25,10 @@
 package sun.hotspot;
 
 import java.lang.reflect.Executable;
+import java.util.Arrays;
+import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Stream;
 import java.security.BasicPermission;
 import sun.hotspot.parser.DiagnosticCommand;
 
@@ -69,6 +73,8 @@
   // Memory
   public native long getObjectAddress(Object o);
   public native int  getHeapOopSize();
+  public native boolean isObjectInOldGen(Object o);
+  public native long getObjectSize(Object o);
 
   // Runtime
   // Make sure class name is in the correct format
@@ -91,7 +97,8 @@
   public native void NMTCommitMemory(long addr, long size);
   public native void NMTUncommitMemory(long addr, long size);
   public native void NMTReleaseMemory(long addr, long size);
-  public native boolean NMTWaitForDataMerge();
+  public native void NMTOverflowHashBucket(long num);
+  public native long NMTMallocWithPseudoStack(long size, int index);
   public native boolean NMTIsDetailSupported();
 
   // Compiler
@@ -129,7 +136,7 @@
   }
   public native int     getCompileQueueSize(int compLevel);
   public native boolean testSetForceInlineMethod(Executable method, boolean value);
-  public boolean        enqueueMethodForCompilation(Executable method, int compLevel) {
+  public        boolean enqueueMethodForCompilation(Executable method, int compLevel) {
     return enqueueMethodForCompilation(method, compLevel, -1 /*InvocationEntryBci*/);
   }
   public native boolean enqueueMethodForCompilation(Executable method, int compLevel, int entry_bci);
@@ -142,6 +149,11 @@
 
   // Memory
   public native void readReservedMemory();
+  public native long allocateMetaspace(ClassLoader classLoader, long size);
+  public native void freeMetaspace(ClassLoader classLoader, long addr, long size);
+
+  // force Young GC
+  public native void youngGC();
 
   // force Full GC
   public native void fullGC();
@@ -150,8 +162,34 @@
   public native int stressVirtualSpaceResize(long reservedSpaceSize, long magnitude, long iterations);
   public native void runMemoryUnitTests();
   public native void readFromNoaccessArea();
+  public native long getThreadStackSize();
+  public native long getThreadRemainingStackSize();
 
   // CPU features
   public native String getCPUFeatures();
 
+  // VM flags
+  public native void    setBooleanVMFlag(String name, boolean value);
+  public native void    setIntxVMFlag(String name, long value);
+  public native void    setUintxVMFlag(String name, long value);
+  public native void    setUint64VMFlag(String name, long value);
+  public native void    setStringVMFlag(String name, String value);
+  public native void    setDoubleVMFlag(String name, double value);
+  public native Boolean getBooleanVMFlag(String name);
+  public native Long    getIntxVMFlag(String name);
+  public native Long    getUintxVMFlag(String name);
+  public native Long    getUint64VMFlag(String name);
+  public native String  getStringVMFlag(String name);
+  public native Double  getDoubleVMFlag(String name);
+  private final List<Function<String,Object>> flagsGetters = Arrays.asList(
+    this::getBooleanVMFlag, this::getIntxVMFlag, this::getUintxVMFlag,
+    this::getUint64VMFlag, this::getStringVMFlag, this::getDoubleVMFlag);
+
+  public Object getVMFlag(String name) {
+    return flagsGetters.stream()
+                       .map(f -> f.apply(name))
+                       .filter(x -> x != null)
+                       .findAny()
+                       .orElse(null);
+  }
 }
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java
new file mode 100644
index 0000000..cf313c3
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/BooleanTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test BooleanTest
+ * @bug 8028756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build BooleanTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI BooleanTest
+ * @summary testing of WB::set/getBooleanVMFlag()
+ * @author igor.ignatyev@oracle.com
+ */
+
+import sun.hotspot.WhiteBox;
+import com.oracle.java.testlibrary.*;
+import sun.management.*;
+import com.sun.management.*;
+
+public class BooleanTest {
+    private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+    private static final Boolean[] TESTS = {true, false, true, true, false};
+    private static final String TEST_NAME = "BooleanTest";
+    private static final String FLAG_NAME = "PrintCompilation";
+    private static final String METHOD = TEST_NAME + "::method";
+    private static final String METHOD1 = METHOD + "1";
+    private static final String METHOD2 = METHOD + "2";
+
+    public static void main(String[] args) throws Exception {
+        if (args.length == 0) {
+            VmFlagTest.runTest(FLAG_NAME, TESTS,
+                VmFlagTest.WHITE_BOX::setBooleanVMFlag,
+                VmFlagTest.WHITE_BOX::getBooleanVMFlag);
+            testFunctional(false);
+            testFunctional(true);
+        } else {
+            boolean value = Boolean.valueOf(args[0]);
+            method1();
+            VmFlagTest.WHITE_BOX.setBooleanVMFlag(FLAG_NAME, value);
+            method2();
+        }
+    }
+
+    private static void testFunctional(boolean value) throws Exception {
+        ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
+            "-Xbootclasspath/a:.",
+            "-XX:+UnlockDiagnosticVMOptions",
+            "-XX:+WhiteBoxAPI",
+            "-Xcomp",
+            "-XX:CompileCommand=compileonly," + METHOD + "*",
+            "-XX:" + (value ? "-" : "+") + FLAG_NAME,
+            TEST_NAME,
+            "" + value);
+        OutputAnalyzer out = new OutputAnalyzer(pb.start());
+        if (value) {
+            out.shouldNotContain(METHOD1);
+            out.shouldContain(METHOD2);
+        } else {
+            out.shouldContain(METHOD1);
+            out.shouldNotContain(METHOD2);
+        }
+    }
+
+    private static void method1() { }
+    private static void method2() { }
+}
+
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java
new file mode 100644
index 0000000..2110fb9
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/DoubleTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test DoubleTest
+ * @bug 8028756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build DoubleTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI DoubleTest
+ * @summary testing of WB::set/getDoubleVMFlag()
+ * @author igor.ignatyev@oracle.com
+ */
+
+public class DoubleTest {
+    private static final String FLAG_NAME = null;
+    private static final Double[] TESTS = {0d, -0d, -1d, 1d,
+            Double.MAX_VALUE, Double.MIN_VALUE, Double.NaN,
+            Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY};
+
+    public static void main(String[] args) throws Exception {
+        VmFlagTest.runTest(FLAG_NAME, TESTS,
+            VmFlagTest.WHITE_BOX::setDoubleVMFlag,
+            VmFlagTest.WHITE_BOX::getDoubleVMFlag);
+    }
+}
+
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java
new file mode 100644
index 0000000..6ffbd83
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/IntxTest.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test IntxTest
+ * @bug 8028756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build IntxTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI IntxTest
+ * @summary testing of WB::set/getIntxVMFlag()
+ * @author igor.ignatyev@oracle.com
+ */
+
+public class IntxTest {
+    private static final String FLAG_NAME = "OnStackReplacePercentage";
+    private static final Long[] TESTS = {0L, 100L, -1L,
+            (long) Integer.MAX_VALUE, (long) Integer.MIN_VALUE};
+
+    public static void main(String[] args) throws Exception {
+        VmFlagTest.runTest(FLAG_NAME, TESTS,
+            VmFlagTest.WHITE_BOX::setIntxVMFlag,
+            VmFlagTest.WHITE_BOX::getIntxVMFlag);
+    }
+}
+
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java
new file mode 100644
index 0000000..70aa066
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/StringTest.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test StringTest
+ * @bug 8028756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build StringTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI StringTest
+ * @summary testing of WB::set/getStringVMFlag()
+ * @author igor.ignatyev@oracle.com
+ */
+
+public class StringTest {
+    private static final String FLAG_NAME = "CompileOnly";
+    private static final String[] TESTS = {"StringTest::*", ""};
+
+    public static void main(String[] args) throws Exception {
+        VmFlagTest.runTest(FLAG_NAME, TESTS,
+            VmFlagTest.WHITE_BOX::setStringVMFlag,
+            VmFlagTest.WHITE_BOX::getStringVMFlag);
+    }
+}
+
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java
new file mode 100644
index 0000000..2f616d4
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/Uint64Test.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test Uint64Test
+ * @bug 8028756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build Uint64Test
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI Uint64Test
+ * @summary testing of WB::set/getUint64VMFlag()
+ * @author igor.ignatyev@oracle.com
+ */
+
+public class Uint64Test {
+    private static final String FLAG_NAME = "MaxRAM";
+    private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
+            -1L, Long.MAX_VALUE, Long.MIN_VALUE};
+
+    public static void main(String[] args) throws Exception {
+        VmFlagTest.runTest(FLAG_NAME, TESTS,
+            VmFlagTest.WHITE_BOX::setUint64VMFlag,
+            VmFlagTest.WHITE_BOX::getUint64VMFlag);
+    }
+}
+
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java
new file mode 100644
index 0000000..688962f
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/UintxTest.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test UintxTest
+ * @bug 8028756
+ * @library /testlibrary /testlibrary/whitebox
+ * @build UintxTest
+ * @run main ClassFileInstaller sun.hotspot.WhiteBox
+ * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI UintxTest
+ * @summary testing of WB::set/getUintxVMFlag()
+ * @author igor.ignatyev@oracle.com
+ */
+import com.oracle.java.testlibrary.Platform;
+
+public class UintxTest {
+    private static final String FLAG_NAME = "TypeProfileLevel";
+    private static final Long[] TESTS = {0L, 100L, (long) Integer.MAX_VALUE,
+        (1L << 32L) - 1L, 1L << 32L};
+    private static final Long[] EXPECTED_64 = TESTS;
+    private static final Long[] EXPECTED_32 = {0L, 100L,
+        (long) Integer.MAX_VALUE, (1L << 32L) - 1L, 0L};
+
+    public static void main(String[] args) throws Exception {
+        VmFlagTest.runTest(FLAG_NAME, TESTS,
+            Platform.is64bit() ? EXPECTED_64 : EXPECTED_32,
+            VmFlagTest.WHITE_BOX::setUintxVMFlag,
+            VmFlagTest.WHITE_BOX::getUintxVMFlag);
+    }
+}
+
diff --git a/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java b/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java
new file mode 100644
index 0000000..fa8915f
--- /dev/null
+++ b/hotspot/test/testlibrary_tests/whitebox/vm_flags/VmFlagTest.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 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.
+ */
+
+import java.util.Objects;
+import java.util.function.BiConsumer;
+import java.util.function.Function;
+import sun.hotspot.WhiteBox;
+import sun.management.*;
+import com.sun.management.*;
+import com.oracle.java.testlibrary.*;
+
+public final class VmFlagTest<T> {
+    public static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox();
+
+    private static final String NONEXISTENT_FLAG = "NonexistentFlag";
+    private final String flagName;
+    private final BiConsumer<T, T> test;
+    private final BiConsumer<String, T> set;
+    private final Function<String, T> get;
+
+    protected VmFlagTest(String flagName, BiConsumer<String, T> set,
+            Function<String, T> get, boolean isPositive) {
+        this.flagName = flagName;
+        this.set = set;
+        this.get = get;
+        if (isPositive) {
+            test = this::testPositive;
+        } else {
+            test = this::testNegative;
+        }
+    }
+
+    private void setNewValue(T value) {
+        set.accept(flagName, value);
+    }
+
+    private T getValue() {
+        T t = get.apply(flagName);
+        System.out.println("T = " + t);
+        return t;
+    }
+
+    protected static <T> void runTest(String existentFlag, T[] tests,
+            BiConsumer<String, T> set, Function<String, T> get) {
+        runTest(existentFlag, tests, tests, set, get);
+    }
+
+    protected static <T> void runTest(String existentFlag, T[] tests,
+            T[] results, BiConsumer<String, T> set, Function<String, T> get) {
+        if (existentFlag != null) {
+            new VmFlagTest(existentFlag, set, get, true).test(tests, results);
+        }
+        new VmFlagTest(NONEXISTENT_FLAG, set, get, false).test(tests, results);
+    }
+
+    public final void test(T[] tests, T[] results) {
+        Asserts.assertEQ(tests.length, results.length, "[TESTBUG] tests.length != results.length");
+        for (int i = 0, n = tests.length ; i < n; ++i) {
+            test.accept(tests[i], results[i]);
+        }
+    }
+
+    protected String getVMOptionAsString() {
+        HotSpotDiagnosticMXBean diagnostic
+                = ManagementFactoryHelper.getDiagnosticMXBean();
+        VMOption tmp;
+        try {
+            tmp = diagnostic.getVMOption(flagName);
+        } catch (IllegalArgumentException e) {
+            tmp = null;
+        }
+        return tmp == null ? null : tmp.getValue();
+    }
+
+    private void testPositive(T value, T expected) {
+        Asserts.assertEQ(getVMOptionAsString(), asString(getValue()));
+        setNewValue(value);
+        String newValue = getVMOptionAsString();
+        Asserts.assertEQ(newValue, asString(expected));
+        Asserts.assertEQ(getVMOptionAsString(), asString(getValue()));
+    }
+
+    private void testNegative(T value, T expected) {
+        String oldValue = getVMOptionAsString();
+        Asserts.assertEQ(oldValue, asString(getValue()));
+        setNewValue(value);
+        String newValue = getVMOptionAsString();
+        Asserts.assertEQ(oldValue, newValue);
+    }
+
+    private String asString(Object value) {
+        return value == null ? null : "" + value;
+    }
+}
+
diff --git a/jaxp/.hgtags b/jaxp/.hgtags
index 65ce842..4a2bc38 100644
--- a/jaxp/.hgtags
+++ b/jaxp/.hgtags
@@ -313,3 +313,8 @@
 d6ded60cfdc53861ae7d1a010f95b5036d610e80 jdk8u20-b23
 dd09d8b9edefb5684941941e5d9b35c84ee066f3 jdk8u20-b24
 dd09d8b9edefb5684941941e5d9b35c84ee066f3 jdk8u20-b25
+938b9d502c2b0f9684151e1b1f47cf7052db1502 jdk8u20-b26
+3a1bba8076da4e54882123e98e219eab1c31ccef jdk8u40-b00
+f219da378d0768ff042d77221e5d20676ecc16f0 jdk8u40-b01
+16ef2134c32a4e60b5a60105b371163aa5936278 jdk8u40-b02
+d73144ee471d4d4c49db94b3cc8990479961499a jdk8u40-b03
diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java
index d37a030..8694de8 100644
--- a/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java
+++ b/jaxp/src/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaLoader.java
@@ -54,6 +54,7 @@
 import com.sun.org.apache.xerces.internal.util.SymbolTable;
 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
 import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
+import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
 import com.sun.org.apache.xerces.internal.xni.XNIException;
 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
@@ -983,6 +984,18 @@
      */
     public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
 
+        XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
+        if (spm == null) {
+            spm = new XMLSecurityPropertyManager();
+            setProperty(XML_SECURITY_PROPERTY_MANAGER, spm);
+        }
+
+        XMLSecurityManager sm = (XMLSecurityManager)componentManager.getProperty(SECURITY_MANAGER);
+        if (sm == null)
+            setProperty(SECURITY_MANAGER,new XMLSecurityManager(true));
+
+        faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
+
         fGrammarBucket.reset();
 
         fSubGroupHandler.reset();
@@ -1066,9 +1079,6 @@
         // get generate-synthetic-annotations feature
         fSchemaHandler.setGenerateSyntheticAnnotations(componentManager.getFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false));
         fSchemaHandler.reset(componentManager);
-
-        XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
-        faccessExternalSchema = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
     }
 
     private void initGrammarBucket(){
diff --git a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java
index f2dadd0..4e57170 100644
--- a/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java
+++ b/jaxp/src/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java
@@ -453,7 +453,8 @@
     }
 
     private void propagateFeatures(AbstractXMLSchema schema) {
-        schema.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, fSecurityManager != null);
+        schema.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING,
+                (fSecurityManager != null && fSecurityManager.isSecureProcessing()));
         schema.setFeature(Constants.ORACLE_FEATURE_SERVICE_MECHANISM, fUseServicesMechanism);
         String[] features = fXMLSchemaLoader.getRecognizedFeatures();
         for (int i = 0; i < features.length; ++i) {
diff --git a/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java b/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java
index 526f5e1..ea0e9b7 100644
--- a/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java
+++ b/jaxp/src/com/sun/org/apache/xml/internal/dtm/ref/sax2dtm/SAX2DTM2.java
@@ -3145,7 +3145,11 @@
                                   m_data.elementAt(-dataIndex+1));
       }
     }
-    else if (DTM.ELEMENT_NODE == type || DTM.DOCUMENT_FRAGMENT_NODE == type
+    else if (DTM.ELEMENT_NODE == type)
+    {
+      return getStringValueX(nodeHandle);
+    }
+    else if (DTM.DOCUMENT_FRAGMENT_NODE == type
              || DTM.DOCUMENT_NODE == type)
     {
       return null;
diff --git a/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java b/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java
index c5740cb..bd14b28 100644
--- a/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java
+++ b/jaxp/src/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java
@@ -57,7 +57,6 @@
  * <p>The selection of CatalogParsers is made on the basis of the QName
  * of the root element of the document.</p>
  *
- * <p>This class requires the <a href="http://java.sun.com/aboutJava/communityprocess/final/jsr005/index.html">Java API for XML Parsing</a>.</p>
  *
  * @see Catalog
  * @see CatalogReader
diff --git a/jaxp/src/org/w3c/dom/package.html b/jaxp/src/org/w3c/dom/package.html
index def37a3..362b1ff 100644
--- a/jaxp/src/org/w3c/dom/package.html
+++ b/jaxp/src/org/w3c/dom/package.html
@@ -3,12 +3,10 @@
 <title>org.w3c.dom package</title>
 </head>
 <body bgcolor="white">
-Provides the interfaces for the Document Object Model (DOM) which is a
-component API of the <a href="http://java.sun.com/xml">Java API for XML
-Processing</a>.  The Document Object Model Level 2 Core API allows programs
-to dynamically access and update the content and structure of documents.
-See the <a href="http://www.w3.org/TR/DOM-Level-2-Core/">specification</a>
-for more information.
+Provides the interfaces for the Document Object Model (DOM). Supports the
+<a href="http://www.w3.org/TR/DOM-Level-2-Core/">Document Object Model Level 2 Core APIi</a>, 
+<a href="http://www.w3.org/TR/DOM-Level-3-Core">Document Object Model (DOM) Level 3 Core</a>, 
+and <a href="http://www.w3.org/TR/DOM-Level-3-LS">Document Object Model (DOM) Level 3 Load and Save</a>.
 
 @since JDK1.4
 </body>
diff --git a/jaxws/.hgtags b/jaxws/.hgtags
index ca1be9d..07026e7 100644
--- a/jaxws/.hgtags
+++ b/jaxws/.hgtags
@@ -311,3 +311,8 @@
 f3bf1b270fea8b17aa2846f962f7514b6f772ab4 jdk8u20-b23
 1277c0d492fd9253f1ea2730eb160953397bd939 jdk8u20-b24
 1277c0d492fd9253f1ea2730eb160953397bd939 jdk8u20-b25
+7025a2c10ea4116ce8f31bb1e305f732aa1025f0 jdk8u20-b26
+31d43d250c836c13fcc87025837783788c5cd0de jdk8u40-b00
+262fb5353ffa661f88b4a9cf2581fcad8c2a43f7 jdk8u40-b01
+8043f77ef8a4ded9505269a356c4e2f4f9604cd9 jdk8u40-b02
+27bcab54f36afc2340adf525fa2a8de1b1c356ca jdk8u40-b03
diff --git a/jdk/.hgtags b/jdk/.hgtags
index 3b55eb9..6d6aabc 100644
--- a/jdk/.hgtags
+++ b/jdk/.hgtags
@@ -316,3 +316,4 @@
 6e223d48080ef40f4ec11ecbcd19b4a20813b9eb jdk8u40-b01
 4797cd0713b44b009525f1276d571ade7e24f3f5 jdk8u40-b02
 c67acfb24eed87629887128df51007218ddf1f60 jdk8u40-b03
+dde62d949f7847469b2ede2ca4190c95066adc91 jdk8u40-b04
diff --git a/langtools/.hgtags b/langtools/.hgtags
index 59e50e2..e0ad4ee 100644
--- a/langtools/.hgtags
+++ b/langtools/.hgtags
@@ -311,3 +311,8 @@
 5c1d6da1445aa3a2e5cf6101c70e79bfbe2745a5 jdk8u20-b23
 9239118487dfb47ee850d2cc9b10a0a2e510da3c jdk8u20-b24
 9239118487dfb47ee850d2cc9b10a0a2e510da3c jdk8u20-b25
+5e6d409a72327a31b8a8f9aa0b32ef213c8b629c jdk8u20-b26
+d231957fe3103e790465fcf058fb8cb33bbc4c4e jdk8u40-b00
+bf89a471779d13a9407f7d1c86f7716258bc4aa6 jdk8u40-b01
+0b6cc4ea670f5d17b56c088f202869bdbb80a5ce jdk8u40-b02
+5183e8b58a03206ca65b4b211be85b3740a70c39 jdk8u40-b03
diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java
index 4216df5..ab15d6d 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Source.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Source.java
@@ -233,6 +233,9 @@
     public boolean allowFunctionalInterfaceMostSpecific() {
         return compareTo(JDK1_8) >= 0;
     }
+    public boolean allowPostApplicabilityVarargsAccessCheck() {
+        return compareTo(JDK1_8) >= 0;
+    }
     public static SourceVersion toSourceVersion(Source source) {
         switch(source) {
         case JDK1_2:
diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
index a38f788..48bcc9c 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java
@@ -1305,7 +1305,8 @@
                 UndetVar undetvar = (UndetVar)t;
                 WildcardType wt = (WildcardType)s.unannotatedType();
                 switch(wt.kind) {
-                    case UNBOUND: //similar to ? extends Object
+                    case UNBOUND:
+                        break;
                     case EXTENDS: {
                         Type bound = wildUpperBound(s);
                         undetvar.addBound(InferenceBound.UPPER, bound, this);
@@ -1396,6 +1397,7 @@
                 else {
 //                    debugContainsType(t, s);
                     return isSameWildcard(t, s)
+                        || t.type == s
                         || isCaptureOf(s, t)
                         || ((t.isExtendsBound() || isSubtypeNoCapture(wildLowerBound(t), cvarLowerBound(wildLowerBound(s)))) &&
                             // TODO: JDK-8039214, cvarUpperBound call here is incorrect
@@ -2954,6 +2956,12 @@
         }
 
         @Override
+        public Type visitUndetVar(UndetVar t, Void ignored) {
+            //do nothing - we should not replace inside undet variables
+            return t;
+        }
+
+        @Override
         public Type visitClassType(ClassType t, Void ignored) {
             if (!t.isCompound()) {
                 List<Type> typarams = t.getTypeArguments();
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
index 41511da..8eb976d 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -252,36 +252,30 @@
      */
     Type check(final JCTree tree, final Type found, final int ownkind, final ResultInfo resultInfo) {
         InferenceContext inferenceContext = resultInfo.checkContext.inferenceContext();
-        Type owntype = found;
-        if (!owntype.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) {
-            if (allowPoly && inferenceContext.free(found)) {
-                if ((ownkind & ~resultInfo.pkind) == 0) {
-                    owntype = resultInfo.check(tree, inferenceContext.asUndetVar(owntype));
-                } else {
-                    log.error(tree.pos(), "unexpected.type",
-                            kindNames(resultInfo.pkind),
-                            kindName(ownkind));
-                    owntype = types.createErrorType(owntype);
-                }
+        Type owntype;
+        if (!found.hasTag(ERROR) && !resultInfo.pt.hasTag(METHOD) && !resultInfo.pt.hasTag(FORALL)) {
+            if ((ownkind & ~resultInfo.pkind) != 0) {
+                log.error(tree.pos(), "unexpected.type",
+                        kindNames(resultInfo.pkind),
+                        kindName(ownkind));
+                owntype = types.createErrorType(found);
+            } else if (allowPoly && inferenceContext.free(found)) {
+                //delay the check if there are inference variables in the found type
+                //this means we are dealing with a partially inferred poly expression
+                owntype = resultInfo.pt;
                 inferenceContext.addFreeTypeListener(List.of(found, resultInfo.pt), new FreeTypeListener() {
                     @Override
                     public void typesInferred(InferenceContext inferenceContext) {
                         ResultInfo pendingResult =
-                                    resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
+                                resultInfo.dup(inferenceContext.asInstType(resultInfo.pt));
                         check(tree, inferenceContext.asInstType(found), ownkind, pendingResult);
                     }
                 });
-                return tree.type = resultInfo.pt;
             } else {
-                if ((ownkind & ~resultInfo.pkind) == 0) {
-                    owntype = resultInfo.check(tree, owntype);
-                } else {
-                    log.error(tree.pos(), "unexpected.type",
-                            kindNames(resultInfo.pkind),
-                            kindName(ownkind));
-                    owntype = types.createErrorType(owntype);
-                }
+                owntype = resultInfo.check(tree, found);
             }
+        } else {
+            owntype = found;
         }
         tree.type = owntype;
         return owntype;
@@ -2335,6 +2329,7 @@
                     currentTarget = infer.instantiateFunctionalInterface(that,
                             currentTarget, explicitParamTypes, resultInfo.checkContext);
                 }
+                currentTarget = types.removeWildcards(currentTarget);
                 lambdaType = types.findDescriptorType(currentTarget);
             } else {
                 currentTarget = Type.recoveryType;
@@ -2727,7 +2722,7 @@
                     resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK &&
                     isSerializable(currentTarget);
             if (currentTarget != Type.recoveryType) {
-                currentTarget = targetChecker.visit(currentTarget, that);
+                currentTarget = types.removeWildcards(targetChecker.visit(currentTarget, that));
                 desc = types.findDescriptorType(currentTarget);
             } else {
                 currentTarget = Type.recoveryType;
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
index b52f9af..141b557 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java
@@ -531,8 +531,8 @@
 
     Type checkType(final DiagnosticPosition pos, final Type found, final Type req, final CheckContext checkContext) {
         final Infer.InferenceContext inferenceContext = checkContext.inferenceContext();
-        if (inferenceContext.free(req)) {
-            inferenceContext.addFreeTypeListener(List.of(req), new FreeTypeListener() {
+        if (inferenceContext.free(req) || inferenceContext.free(found)) {
+            inferenceContext.addFreeTypeListener(List.of(req, found), new FreeTypeListener() {
                 @Override
                 public void typesInferred(InferenceContext inferenceContext) {
                     checkType(pos, inferenceContext.asInstType(found), inferenceContext.asInstType(req), checkContext);
@@ -1715,7 +1715,12 @@
 
         // Warn if a deprecated method overridden by a non-deprecated one.
         if (!isDeprecatedOverrideIgnorable(other, origin)) {
-            checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other);
+            Lint prevLint = setLint(lint.augment(m));
+            try {
+                checkDeprecated(TreeInfo.diagnosticPositionFor(m, tree), m, other);
+            } finally {
+                setLint(prevLint);
+            }
         }
     }
     // where
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
index dc7f9f1..9a932ce 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java
@@ -353,6 +353,7 @@
             Type to, Attr.ResultInfo resultInfo,
             InferenceContext inferenceContext) {
         inferenceContext.solve(List.of(from.qtype), new Warner());
+        inferenceContext.notifyChange();
         Type capturedType = resultInfo.checkContext.inferenceContext()
                 .cachedCapture(tree, from.inst, false);
         if (types.isConvertible(capturedType,
@@ -449,7 +450,7 @@
         class ImplicitArgType extends DeferredAttr.DeferredTypeMap {
 
             public ImplicitArgType(Symbol msym, Resolve.MethodResolutionPhase phase) {
-                rs.deferredAttr.super(AttrMode.SPECULATIVE, msym, phase);
+                (rs.deferredAttr).super(AttrMode.SPECULATIVE, msym, phase);
             }
 
             public Type apply(Type t) {
@@ -517,6 +518,8 @@
                 //or if it's not a subtype of the original target, issue an error
                 checkContext.report(pos, diags.fragment("no.suitable.functional.intf.inst", funcInterface));
             }
+            //propagate constraints as per JLS 18.2.1
+            checkContext.compatible(owntype, funcInterface, types.noWarnings);
             return owntype;
         }
     }
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
index e176e92..980843f 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java
@@ -1994,7 +1994,11 @@
                 // If instance access isn't needed, make it static.
                 // Interface instance methods must be default methods.
                 // Lambda methods are private synthetic.
+                // Inherit ACC_STRICT from the enclosing method, or, for clinit,
+                // from the class.
                 translatedSym.flags_field = SYNTHETIC | LAMBDA_METHOD |
+                        owner.flags_field & STRICTFP |
+                        owner.owner.flags_field & STRICTFP |
                         PRIVATE |
                         (thisReferenced? (inInterface? DEFAULT : 0) : STATIC);
 
diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
index 1535e1d..ef50a2a 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java
@@ -96,6 +96,7 @@
     public final boolean varargsEnabled;
     public final boolean allowMethodHandles;
     public final boolean allowFunctionalInterfaceMostSpecific;
+    public final boolean checkVarargsAccessAfterResolution;
     private final boolean debugResolve;
     private final boolean compactMethodDiags;
     final EnumSet<VerboseResolutionMode> verboseResolutionMode;
@@ -137,6 +138,8 @@
         Target target = Target.instance(context);
         allowMethodHandles = target.hasMethodHandles();
         allowFunctionalInterfaceMostSpecific = source.allowFunctionalInterfaceMostSpecific();
+        checkVarargsAccessAfterResolution =
+                source.allowPostApplicabilityVarargsAccessCheck();
         polymorphicSignatureScope = new Scope(syms.noSymbol);
 
         inapplicableMethodException = new InapplicableMethodException(diags);
@@ -835,9 +838,15 @@
             super.argumentsAcceptable(env, deferredAttrContext, argtypes, formals, warn);
             //should we expand formals?
             if (deferredAttrContext.phase.isVarargsRequired()) {
-                //check varargs element type accessibility
-                varargsAccessible(env, types.elemtype(formals.last()),
-                        deferredAttrContext.inferenceContext);
+                Type typeToCheck = null;
+                if (!checkVarargsAccessAfterResolution) {
+                    typeToCheck = types.elemtype(formals.last());
+                } else if (deferredAttrContext.mode == AttrMode.CHECK) {
+                    typeToCheck = types.erasure(types.elemtype(formals.last()));
+                }
+                if (typeToCheck != null) {
+                    varargsAccessible(env, typeToCheck, deferredAttrContext.inferenceContext);
+                }
             }
         }
 
@@ -948,9 +957,10 @@
         }
 
         public boolean compatible(Type found, Type req, Warner warn) {
+            InferenceContext inferenceContext = deferredAttrContext.inferenceContext;
             return strict ?
-                    types.isSubtypeUnchecked(found, deferredAttrContext.inferenceContext.asUndetVar(req), warn) :
-                    types.isConvertible(found, deferredAttrContext.inferenceContext.asUndetVar(req), warn);
+                    types.isSubtypeUnchecked(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn) :
+                    types.isConvertible(inferenceContext.asUndetVar(found), inferenceContext.asUndetVar(req), warn);
         }
 
         public void report(DiagnosticPosition pos, JCDiagnostic details) {
diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
index 5e32dc4..044a998 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java
@@ -1953,12 +1953,12 @@
             }
         }
 
-        public void closeRange(char end) {
-            if (isLastRangeInitialized()) {
+        public void closeRange(char length) {
+            if (isLastRangeInitialized() && length > 0) {
                 Range range = lastRange();
                 if (range != null) {
                     if (range.length == Character.MAX_VALUE) {
-                        range.length = end;
+                        range.length = length;
                     }
                 }
             } else {
@@ -2022,7 +2022,7 @@
                 }
                 if (localVar.sym == aliveLocal && localVar.lastRange() != null) {
                     char length = (char)(closingCP - localVar.lastRange().start_pc);
-                    if (length > 0 && length < Character.MAX_VALUE) {
+                    if (length < Character.MAX_VALUE) {
                         localVar.closeRange(length);
                     }
                 }
@@ -2093,7 +2093,7 @@
             lvar[adr].isLastRangeInitialized()) {
             LocalVar v = lvar[adr];
             char length = (char)(curCP() - v.lastRange().start_pc);
-            if (length > 0 && length < Character.MAX_VALUE) {
+            if (length < Character.MAX_VALUE) {
                 lvar[adr] = v.dup();
                 v.closeRange(length);
                 putVar(v);
diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
index 83981bb..0bf2b9e 100644
--- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
+++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java
@@ -1194,7 +1194,7 @@
                              boolean testFirst) {
             Env<GenContext> loopEnv = env.dup(loop, new GenContext());
             int startpc = code.entryPoint();
-            if (testFirst) {
+            if (testFirst) { //while or for loop
                 CondItem c;
                 if (cond != null) {
                     code.statBegin(cond.pos);
@@ -1240,6 +1240,9 @@
                 code.resolve(c.falseJumps);
             }
             code.resolve(loopEnv.info.exit);
+            if (loopEnv.info.exit != null) {
+                loopEnv.info.exit.state.defined.excludeFrom(code.nextreg);
+            }
         }
 
         private enum LoopLocalVarRangeEndingPoint {
@@ -2786,7 +2789,7 @@
 
             boolean trackVar(VarSymbol var) {
                 return (var.owner.kind == MTH &&
-                        (var.flags() & (PARAMETER | HASINIT)) == 0 &&
+                        (var.flags() & PARAMETER) == 0 &&
                         analyzer.trackable(var));
             }
 
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/Analyzer.java b/langtools/src/share/classes/com/sun/tools/jdeps/Analyzer.java
index fffe754..afaa38e 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/Analyzer.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/Analyzer.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -24,10 +24,8 @@
  */
 package com.sun.tools.jdeps;
 
-import com.sun.tools.classfile.Dependency.Location;
-import com.sun.tools.jdeps.PlatformClassPath.JDKArchive;
-import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
@@ -37,6 +35,9 @@
 import java.util.TreeMap;
 import java.util.TreeSet;
 
+import com.sun.tools.classfile.Dependency.Location;
+import com.sun.tools.jdeps.PlatformClassPath.JDKArchive;
+
 /**
  * Dependency Analyzer.
  */
@@ -52,7 +53,16 @@
         VERBOSE
     };
 
+    /**
+     * Filter to be applied when analyzing the dependencies from the given archives.
+     * Only the accepted dependencies are recorded.
+     */
+    interface Filter {
+        boolean accepts(Location origin, Archive originArchive, Location target, Archive targetArchive);
+    }
+
     private final Type type;
+    private final Filter filter;
     private final Map<Archive, ArchiveDeps> results = new HashMap<>();
     private final Map<Location, Archive> map = new HashMap<>();
     private final Archive NOT_FOUND
@@ -62,9 +72,11 @@
      * Constructs an Analyzer instance.
      *
      * @param type Type of the dependency analysis
+     * @param filter
      */
-    public Analyzer(Type type) {
+    public Analyzer(Type type, Filter filter) {
         this.type = type;
+        this.filter = filter;
     }
 
     /**
@@ -72,6 +84,18 @@
      */
     public void run(List<Archive> archives) {
         // build a map from Location to Archive
+        buildLocationArchiveMap(archives);
+
+        // traverse and analyze all dependencies
+        for (Archive archive : archives) {
+            ArchiveDeps deps = new ArchiveDeps(archive, type);
+            archive.visitDependences(deps);
+            results.put(archive, deps);
+        }
+    }
+
+    private void buildLocationArchiveMap(List<Archive> archives) {
+        // build a map from Location to Archive
         for (Archive archive: archives) {
             for (Location l: archive.getClasses()) {
                 if (!map.containsKey(l)) {
@@ -81,190 +105,236 @@
                 }
             }
         }
-        // traverse and analyze all dependencies
-        for (Archive archive : archives) {
-            ArchiveDeps deps;
-            if (type == Type.CLASS || type == Type.VERBOSE) {
-                deps = new ClassVisitor(archive);
-            } else {
-                deps = new PackageVisitor(archive);
-            }
-            archive.visitDependences(deps);
-            results.put(archive, deps);
-        }
     }
 
     public boolean hasDependences(Archive archive) {
         if (results.containsKey(archive)) {
-            return results.get(archive).deps.size() > 0;
+            return results.get(archive).dependencies().size() > 0;
         }
         return false;
     }
 
-    public interface Visitor {
-        /**
-         * Visits the source archive to its destination archive of
-         * a recorded dependency.
-         */
-        void visitArchiveDependence(Archive origin, Archive target, Profile profile);
-        /**
-         * Visits a recorded dependency from origin to target which can be
-         * a fully-qualified classname, a package name, a profile or
-         * archive name depending on the Analyzer's type.
-         */
-        void visitDependence(String origin, Archive source, String target, Archive archive, Profile profile);
+    public Set<String> dependences(Archive source) {
+        ArchiveDeps result = results.get(source);
+        return result.targetDependences();
     }
 
-    public void visitArchiveDependences(Archive source, Visitor v) {
-        ArchiveDeps r = results.get(source);
-        for (ArchiveDeps.Dep d: r.requireArchives()) {
-            v.visitArchiveDependence(r.archive, d.archive, d.profile);
+    public interface Visitor {
+        /**
+         * Visits a recorded dependency from origin to target which can be
+         * a fully-qualified classname, a package name, a module or
+         * archive name depending on the Analyzer's type.
+         */
+        public void visitDependence(String origin, Archive originArchive,
+                                    String target, Archive targetArchive);
+    }
+
+    /**
+     * Visit the dependencies of the given source.
+     * If the requested level is SUMMARY, it will visit the required archives list.
+     */
+    public void visitDependences(Archive source, Visitor v, Type level) {
+        if (level == Type.SUMMARY) {
+            final ArchiveDeps result = results.get(source);
+            SortedMap<String, Archive> sorted = new TreeMap<>();
+            for (Archive a : result.requires()) {
+                sorted.put(a.getName(), a);
+            }
+            for (Archive archive : sorted.values()) {
+                Profile profile = result.getTargetProfile(archive);
+                v.visitDependence(source.getName(), source,
+                                  profile != null ? profile.profileName() : archive.getName(), archive);
+            }
+        } else {
+            ArchiveDeps result = results.get(source);
+            if (level != type) {
+                // requesting different level of analysis
+                result = new ArchiveDeps(source, level);
+                source.visitDependences(result);
+            }
+            SortedSet<Dep> sorted = new TreeSet<>(result.dependencies());
+            for (Dep d : sorted) {
+                v.visitDependence(d.origin(), d.originArchive(), d.target(), d.targetArchive());
+            }
         }
     }
 
     public void visitDependences(Archive source, Visitor v) {
-        ArchiveDeps r = results.get(source);
-        for (Map.Entry<String, SortedSet<ArchiveDeps.Dep>> e: r.deps.entrySet()) {
-            String origin = e.getKey();
-            for (ArchiveDeps.Dep d: e.getValue()) {
-                // filter intra-dependency unless in verbose mode
-                if (type == Type.VERBOSE || d.archive != source) {
-                    v.visitDependence(origin, source, d.target, d.archive, d.profile);
-                }
-            }
-        }
+        visitDependences(source, v, type);
     }
 
     /**
-     * ArchiveDeps contains the dependencies for an Archive that
-     * can have one or more classes.
+     * ArchiveDeps contains the dependencies for an Archive that can have one or
+     * more classes.
      */
-    private abstract class ArchiveDeps implements Archive.Visitor {
-        final Archive archive;
-        final SortedMap<String, SortedSet<Dep>> deps;
-        ArchiveDeps(Archive archive) {
+    class ArchiveDeps implements Archive.Visitor {
+        protected final Archive archive;
+        protected final Set<Archive> requires;
+        protected final Set<Dep> deps;
+        protected final Type level;
+        private Profile profile;
+        ArchiveDeps(Archive archive, Type level) {
             this.archive = archive;
-            this.deps = new TreeMap<>();
+            this.deps = new HashSet<>();
+            this.requires = new HashSet<>();
+            this.level = level;
         }
 
-        void add(String origin, String target, Archive targetArchive, String pkgName) {
-            SortedSet<Dep> set = deps.get(origin);
-            if (set == null) {
-                deps.put(origin, set = new TreeSet<>());
+        Set<Dep> dependencies() {
+            return deps;
+        }
+
+        Set<String> targetDependences() {
+            Set<String> targets = new HashSet<>();
+            for (Dep d : deps) {
+                targets.add(d.target());
             }
-            Profile p = targetArchive instanceof JDKArchive
-                            ? Profile.getProfile(pkgName) : null;
-            set.add(new Dep(target, targetArchive, p));
+            return targets;
         }
 
-        /**
-         * Returns the list of Archive dependences.  The returned
-         * list contains one {@code Dep} instance per one archive
-         * and with the minimum profile this archive depends on.
-         */
-        List<Dep> requireArchives() {
-            Map<Archive,Profile> map = new HashMap<>();
-            for (Set<Dep> set: deps.values()) {
-                for (Dep d: set) {
-                    if (this.archive != d.archive) {
-                        Profile p = map.get(d.archive);
-                        if (p == null || (d.profile != null && p.profile < d.profile.profile)) {
-                            map.put(d.archive, d.profile);
-                        }
+        Set<Archive> requires() {
+            return requires;
+        }
+
+        Profile getTargetProfile(Archive target) {
+            return JDKArchive.isProfileArchive(target) ? profile : null;
+        }
+
+        Archive findArchive(Location t) {
+            Archive target = archive.getClasses().contains(t) ? archive : map.get(t);
+            if (target == null) {
+                map.put(t, target = NOT_FOUND);
+            }
+            return target;
+        }
+
+        // return classname or package name depedning on the level
+        private String getLocationName(Location o) {
+            if (level == Type.CLASS || level == Type.VERBOSE) {
+                return o.getClassName();
+            } else {
+                String pkg = o.getPackageName();
+                return pkg.isEmpty() ? "<unnamed>" : pkg;
+            }
+        }
+
+        @Override
+        public void visit(Location o, Location t) {
+            Archive targetArchive = findArchive(t);
+            if (filter.accepts(o, archive, t, targetArchive)) {
+                addDep(o, t);
+                if (!requires.contains(targetArchive)) {
+                    requires.add(targetArchive);
+                }
+            }
+            if (targetArchive instanceof JDKArchive) {
+                Profile p = Profile.getProfile(t.getPackageName());
+                if (profile == null || (p != null && p.compareTo(profile) > 0)) {
+                    profile = p;
+                }
+            }
+        }
+
+        private Dep curDep;
+        protected Dep addDep(Location o, Location t) {
+            String origin = getLocationName(o);
+            String target = getLocationName(t);
+            Archive targetArchive = findArchive(t);
+            if (curDep != null &&
+                    curDep.origin().equals(origin) &&
+                    curDep.originArchive() == archive &&
+                    curDep.target().equals(target) &&
+                    curDep.targetArchive() == targetArchive) {
+                return curDep;
+            }
+
+            Dep e = new Dep(origin, archive, target, targetArchive);
+            if (deps.contains(e)) {
+                for (Dep e1 : deps) {
+                    if (e.equals(e1)) {
+                        curDep = e1;
                     }
                 }
+            } else {
+                deps.add(e);
+                curDep = e;
             }
-            List<Dep> list = new ArrayList<>();
-            for (Map.Entry<Archive,Profile> e: map.entrySet()) {
-                list.add(new Dep("", e.getKey(), e.getValue()));
-            }
-            return list;
+            return curDep;
+        }
+    }
+
+    /*
+     * Class-level or package-level dependency
+     */
+    class Dep implements Comparable<Dep> {
+        final String origin;
+        final Archive originArchive;
+        final String target;
+        final Archive targetArchive;
+
+        Dep(String origin, Archive originArchive, String target, Archive targetArchive) {
+            this.origin = origin;
+            this.originArchive = originArchive;
+            this.target = target;
+            this.targetArchive = targetArchive;
         }
 
-        /**
-         * Dep represents a dependence where the target can be
-         * a classname or packagename and the archive and profile
-         * the target belongs to.
-         */
-        class Dep implements Comparable<Dep> {
-            final String target;
-            final Archive archive;
-            final Profile profile;
-            Dep(String target, Archive archive, Profile p) {
-                this.target = target;
-                this.archive = archive;
-                this.profile = p;
-            }
+        String origin() {
+            return origin;
+        }
 
-            @Override
-            public boolean equals(Object o) {
-                if (o instanceof Dep) {
-                    Dep d = (Dep)o;
-                    return this.archive == d.archive && this.target.equals(d.target);
-                }
-                return false;
-            }
+        Archive originArchive() {
+            return originArchive;
+        }
 
-            @Override
-            public int hashCode() {
-                int hash = 3;
-                hash = 17 * hash + Objects.hashCode(this.archive);
-                hash = 17 * hash + Objects.hashCode(this.target);
-                return hash;
-            }
+        String target() {
+            return target;
+        }
 
-            @Override
-            public int compareTo(Dep o) {
+        Archive targetArchive() {
+            return targetArchive;
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public boolean equals(Object o) {
+            if (o instanceof Dep) {
+                Dep d = (Dep) o;
+                return this.origin.equals(d.origin) &&
+                        this.originArchive == d.originArchive &&
+                        this.target.equals(d.target) &&
+                        this.targetArchive == d.targetArchive;
+            }
+            return false;
+        }
+
+        @Override
+        public int hashCode() {
+            int hash = 7;
+            hash = 67*hash + Objects.hashCode(this.origin)
+                           + Objects.hashCode(this.originArchive)
+                           + Objects.hashCode(this.target)
+                           + Objects.hashCode(this.targetArchive);
+            return hash;
+        }
+
+        @Override
+        public int compareTo(Dep o) {
+            if (this.origin.equals(o.origin)) {
                 if (this.target.equals(o.target)) {
-                    if (this.archive == o.archive) {
+                    if (this.originArchive == o.originArchive &&
+                            this.targetArchive == o.targetArchive) {
                         return 0;
+                    } else if (this.originArchive == o.originArchive) {
+                        return this.targetArchive.getPathName().compareTo(o.targetArchive.getPathName());
                     } else {
-                        return this.archive.getFileName().compareTo(o.archive.getFileName());
+                        return this.originArchive.getPathName().compareTo(o.originArchive.getPathName());
                     }
+                } else {
+                    return this.target.compareTo(o.target);
                 }
-                return this.target.compareTo(o.target);
             }
-        }
-        public abstract void visit(Location o, Location t);
-    }
-
-    private class ClassVisitor extends ArchiveDeps {
-        ClassVisitor(Archive archive) {
-            super(archive);
-        }
-        @Override
-        public void visit(Location o, Location t) {
-            Archive targetArchive =
-                this.archive.getClasses().contains(t) ? this.archive : map.get(t);
-            if (targetArchive == null) {
-                map.put(t, targetArchive = NOT_FOUND);
-            }
-
-            String origin = o.getClassName();
-            String target = t.getClassName();
-            add(origin, target, targetArchive, t.getPackageName());
-        }
-    }
-
-    private class PackageVisitor extends ArchiveDeps {
-        PackageVisitor(Archive archive) {
-            super(archive);
-        }
-        @Override
-        public void visit(Location o, Location t) {
-            Archive targetArchive =
-                this.archive.getClasses().contains(t) ? this.archive : map.get(t);
-            if (targetArchive == null) {
-                map.put(t, targetArchive = NOT_FOUND);
-            }
-
-            String origin = packageOf(o);
-            String target = packageOf(t);
-            add(origin, target, targetArchive, t.getPackageName());
-        }
-        public String packageOf(Location o) {
-            String pkg = o.getPackageName();
-            return pkg.isEmpty() ? "<unnamed>" : pkg;
+            return this.origin.compareTo(o.origin);
         }
     }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/Archive.java b/langtools/src/share/classes/com/sun/tools/jdeps/Archive.java
index cc2963b..669575d 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/Archive.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/Archive.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -25,28 +25,34 @@
 package com.sun.tools.jdeps;
 
 import com.sun.tools.classfile.Dependency.Location;
+
+import java.io.IOException;
 import java.nio.file.Path;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 
 /**
  * Represents the source of the class files.
  */
 public class Archive {
+    public static Archive getInstance(Path p) throws IOException {
+        return new Archive(p, ClassFileReader.newInstance(p));
+    }
+
     private final Path path;
     private final String filename;
     private final ClassFileReader reader;
-    private final Map<Location, Set<Location>> deps = new HashMap<>();
+    protected Map<Location, Set<Location>> deps = new ConcurrentHashMap<>();
 
-    public Archive(String name) {
+    protected Archive(String name) {
         this.path = null;
         this.filename = name;
         this.reader = null;
     }
 
-    public Archive(Path p, ClassFileReader reader) {
+    protected Archive(Path p, ClassFileReader reader) {
         this.path = p;
         this.filename = path.getFileName().toString();
         this.reader = reader;
@@ -56,7 +62,7 @@
         return reader;
     }
 
-    public String getFileName() {
+    public String getName() {
         return filename;
     }
 
@@ -89,6 +95,10 @@
         }
     }
 
+    public boolean isEmpty() {
+        return getClasses().isEmpty();
+    }
+
     public String getPathName() {
         return path != null ? path.toString() : filename;
     }
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java b/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java
index 6f34dc6..435045b 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/ClassFileReader.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -68,7 +68,8 @@
 
     protected final Path path;
     protected final String baseFileName;
-    private ClassFileReader(Path path) {
+    protected final List<String> skippedEntries = new ArrayList<>();
+    protected ClassFileReader(Path path) {
         this.path = path;
         this.baseFileName = path.getFileName() != null
                                 ? path.getFileName().toString()
@@ -79,6 +80,10 @@
         return baseFileName;
     }
 
+    public List<String> skippedEntries() {
+        return skippedEntries;
+    }
+
     /**
      * Returns the ClassFile matching the given binary name
      * or a fully-qualified class name.
@@ -232,11 +237,12 @@
         }
     }
 
-    private static class JarFileReader extends ClassFileReader {
-        final JarFile jarfile;
+    static class JarFileReader extends ClassFileReader {
+        private final JarFile jarfile;
         JarFileReader(Path path) throws IOException {
-            this(path, new JarFile(path.toFile()));
+            this(path, new JarFile(path.toFile(), false));
         }
+
         JarFileReader(Path path, JarFile jf) throws IOException {
             super(path);
             this.jarfile = jf;
@@ -252,18 +258,18 @@
                             + entryName.substring(i + 1, entryName.length()));
                 }
                 if (e != null) {
-                    return readClassFile(e);
+                    return readClassFile(jarfile, e);
                 }
             } else {
                 JarEntry e = jarfile.getJarEntry(name + ".class");
                 if (e != null) {
-                    return readClassFile(e);
+                    return readClassFile(jarfile, e);
                 }
             }
             return null;
         }
 
-        private ClassFile readClassFile(JarEntry e) throws IOException {
+        protected ClassFile readClassFile(JarFile jarfile, JarEntry e) throws IOException {
             InputStream is = null;
             try {
                 is = jarfile.getInputStream(e);
@@ -277,60 +283,76 @@
         }
 
         public Iterable<ClassFile> getClassFiles() throws IOException {
-            final Iterator<ClassFile> iter = new JarFileIterator();
+            final Iterator<ClassFile> iter = new JarFileIterator(this, jarfile);
             return new Iterable<ClassFile>() {
                 public Iterator<ClassFile> iterator() {
                     return iter;
                 }
             };
         }
+    }
 
-        class JarFileIterator implements Iterator<ClassFile> {
-            private Enumeration<JarEntry> entries;
-            private JarEntry nextEntry;
-            JarFileIterator() {
-                this.entries = jarfile.entries();
-                while (entries.hasMoreElements()) {
-                    JarEntry e = entries.nextElement();
-                    String name = e.getName();
-                    if (name.endsWith(".class")) {
-                        this.nextEntry = e;
-                        break;
-                    }
-                }
+    class JarFileIterator implements Iterator<ClassFile> {
+        protected final JarFileReader reader;
+        protected Enumeration<JarEntry> entries;
+        protected JarFile jf;
+        protected JarEntry nextEntry;
+        protected ClassFile cf;
+        JarFileIterator(JarFileReader reader) {
+            this(reader, null);
+        }
+        JarFileIterator(JarFileReader reader, JarFile jarfile) {
+            this.reader = reader;
+            setJarFile(jarfile);
+        }
+
+        void setJarFile(JarFile jarfile) {
+            if (jarfile == null) return;
+
+            this.jf = jarfile;
+            this.entries = jf.entries();
+            this.nextEntry = nextEntry();
+        }
+
+        public boolean hasNext() {
+            if (nextEntry != null && cf != null) {
+                return true;
             }
-
-            public boolean hasNext() {
-                return nextEntry != null;
-            }
-
-            public ClassFile next() {
-                if (!hasNext()) {
-                    throw new NoSuchElementException();
-                }
-
-                ClassFile cf;
+            while (nextEntry != null) {
                 try {
-                    cf = readClassFile(nextEntry);
-                } catch (IOException ex) {
-                    throw new ClassFileError(ex);
+                    cf = reader.readClassFile(jf, nextEntry);
+                    return true;
+                } catch (ClassFileError | IOException ex) {
+                    skippedEntries.add(nextEntry.getName());
                 }
-                JarEntry entry = nextEntry;
-                nextEntry = null;
-                while (entries.hasMoreElements()) {
-                    JarEntry e = entries.nextElement();
-                    String name = e.getName();
-                    if (name.endsWith(".class")) {
-                        nextEntry = e;
-                        break;
-                    }
-                }
-                return cf;
+                nextEntry = nextEntry();
             }
+            return false;
+        }
 
-            public void remove() {
-                throw new UnsupportedOperationException("Not supported yet.");
+        public ClassFile next() {
+            if (!hasNext()) {
+                throw new NoSuchElementException();
             }
+            ClassFile classFile = cf;
+            cf = null;
+            nextEntry = nextEntry();
+            return classFile;
+        }
+
+        protected JarEntry nextEntry() {
+            while (entries.hasMoreElements()) {
+                JarEntry e = entries.nextElement();
+                String name = e.getName();
+                if (name.endsWith(".class")) {
+                    return e;
+                }
+            }
+            return null;
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException("Not supported yet.");
         }
     }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java b/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java
index 38a519c..e75e9c7 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/JdepsTask.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -30,7 +30,9 @@
 import com.sun.tools.classfile.Dependencies;
 import com.sun.tools.classfile.Dependencies.ClassFileError;
 import com.sun.tools.classfile.Dependency;
+import com.sun.tools.classfile.Dependency.Location;
 import com.sun.tools.jdeps.PlatformClassPath.JDKArchive;
+import static com.sun.tools.jdeps.Analyzer.Type.*;
 import java.io.*;
 import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
@@ -110,7 +112,7 @@
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 Path p = Paths.get(arg);
                 if (Files.exists(p) && (!Files.isDirectory(p) || !Files.isWritable(p))) {
-                    throw new BadArgs("err.dot.output.path", arg);
+                    throw new BadArgs("err.invalid.path", arg);
                 }
                 task.options.dotOutputDir = arg;
             }
@@ -118,25 +120,26 @@
         new Option(false, "-s", "-summary") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.showSummary = true;
-                task.options.verbose = Analyzer.Type.SUMMARY;
+                task.options.verbose = SUMMARY;
             }
         },
         new Option(false, "-v", "-verbose",
                           "-verbose:package",
-                          "-verbose:class")
-        {
+                          "-verbose:class") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 switch (opt) {
                     case "-v":
                     case "-verbose":
-                        task.options.verbose = Analyzer.Type.VERBOSE;
+                        task.options.verbose = VERBOSE;
+                        task.options.filterSameArchive = false;
+                        task.options.filterSamePackage = false;
                         break;
                     case "-verbose:package":
-                            task.options.verbose = Analyzer.Type.PACKAGE;
-                            break;
+                        task.options.verbose = PACKAGE;
+                        break;
                     case "-verbose:class":
-                            task.options.verbose = Analyzer.Type.CLASS;
-                            break;
+                        task.options.verbose = CLASS;
+                        break;
                     default:
                         throw new BadArgs("err.invalid.arg.for.option", opt);
                 }
@@ -157,6 +160,32 @@
                 task.options.regex = arg;
             }
         },
+
+        new Option(true, "-f", "-filter") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.filterRegex = arg;
+            }
+        },
+        new Option(false, "-filter:package",
+                          "-filter:archive",
+                          "-filter:none") {
+            void process(JdepsTask task, String opt, String arg) {
+                switch (opt) {
+                    case "-filter:package":
+                        task.options.filterSamePackage = true;
+                        task.options.filterSameArchive = false;
+                        break;
+                    case "-filter:archive":
+                        task.options.filterSameArchive = true;
+                        task.options.filterSamePackage = false;
+                        break;
+                    case "-filter:none":
+                        task.options.filterSameArchive = false;
+                        task.options.filterSamePackage = false;
+                        break;
+                }
+            }
+        },
         new Option(true, "-include") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 task.options.includePattern = Pattern.compile(arg);
@@ -178,12 +207,15 @@
         new Option(false, "-R", "-recursive") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.depth = 0;
+                // turn off filtering
+                task.options.filterSameArchive = false;
+                task.options.filterSamePackage = false;
             }
         },
         new Option(false, "-jdkinternals") {
             void process(JdepsTask task, String opt, String arg) {
                 task.options.findJDKInternals = true;
-                task.options.verbose = Analyzer.Type.CLASS;
+                task.options.verbose = CLASS;
                 if (task.options.includePattern == null) {
                     task.options.includePattern = Pattern.compile(".*");
                 }
@@ -204,6 +236,11 @@
                 task.options.showLabel = true;
             }
         },
+        new HiddenOption(false, "-q", "-quiet") {
+            void process(JdepsTask task, String opt, String arg) {
+                task.options.nowarning = true;
+            }
+        },
         new HiddenOption(true, "-depth") {
             void process(JdepsTask task, String opt, String arg) throws BadArgs {
                 try {
@@ -217,7 +254,7 @@
 
     private static final String PROGNAME = "jdeps";
     private final Options options = new Options();
-    private final List<String> classes = new ArrayList<String>();
+    private final List<String> classes = new ArrayList<>();
 
     private PrintWriter log;
     void setLog(PrintWriter out) {
@@ -262,7 +299,7 @@
                 showHelp();
                 return EXIT_CMDERR;
             }
-            if (options.showSummary && options.verbose != Analyzer.Type.SUMMARY) {
+            if (options.showSummary && options.verbose != SUMMARY) {
                 showHelp();
                 return EXIT_CMDERR;
             }
@@ -283,9 +320,30 @@
 
     private final List<Archive> sourceLocations = new ArrayList<>();
     private boolean run() throws IOException {
+        // parse classfiles and find all dependencies
         findDependencies();
-        Analyzer analyzer = new Analyzer(options.verbose);
+
+        Analyzer analyzer = new Analyzer(options.verbose, new Analyzer.Filter() {
+            @Override
+            public boolean accepts(Location origin, Archive originArchive,
+                                   Location target, Archive targetArchive)
+            {
+                if (options.findJDKInternals) {
+                    // accepts target that is JDK class but not exported
+                    return isJDKArchive(targetArchive) &&
+                              !((JDKArchive) targetArchive).isExported(target.getClassName());
+                } else if (options.filterSameArchive) {
+                    // accepts origin and target that from different archive
+                    return originArchive != targetArchive;
+                }
+                return true;
+            }
+        });
+
+        // analyze the dependencies
         analyzer.run(sourceLocations);
+
+        // output result
         if (options.dotOutputDir != null) {
             Path dir = Paths.get(options.dotOutputDir);
             Files.createDirectories(dir);
@@ -293,30 +351,41 @@
         } else {
             printRawOutput(log, analyzer);
         }
+
+        if (options.findJDKInternals && !options.nowarning) {
+            showReplacements(analyzer);
+        }
         return true;
     }
 
-    private void generateDotFiles(Path dir, Analyzer analyzer) throws IOException {
+    private void generateSummaryDotFile(Path dir, Analyzer analyzer) throws IOException {
+        // If verbose mode (-v or -verbose option),
+        // the summary.dot file shows package-level dependencies.
+        Analyzer.Type summaryType =
+            (options.verbose == PACKAGE || options.verbose == SUMMARY) ? SUMMARY : PACKAGE;
         Path summary = dir.resolve("summary.dot");
-        boolean verbose = options.verbose == Analyzer.Type.VERBOSE;
-        DotGraph<?> graph = verbose ? new DotSummaryForPackage()
-                                    : new DotSummaryForArchive();
-        for (Archive archive : sourceLocations) {
-            analyzer.visitArchiveDependences(archive, graph);
-            if (verbose || options.showLabel) {
-                // traverse detailed dependences to generate package-level
-                // summary or build labels for edges
-                analyzer.visitDependences(archive, graph);
+        try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary));
+             SummaryDotFile dotfile = new SummaryDotFile(sw, summaryType)) {
+            for (Archive archive : sourceLocations) {
+                if (!archive.isEmpty()) {
+                    if (options.verbose == PACKAGE || options.verbose == SUMMARY) {
+                        if (options.showLabel) {
+                            // build labels listing package-level dependencies
+                            analyzer.visitDependences(archive, dotfile.labelBuilder(), PACKAGE);
+                        }
+                    }
+                    analyzer.visitDependences(archive, dotfile, summaryType);
+                }
             }
         }
-        try (PrintWriter sw = new PrintWriter(Files.newOutputStream(summary))) {
-            graph.writeTo(sw);
-        }
+    }
+
+    private void generateDotFiles(Path dir, Analyzer analyzer) throws IOException {
         // output individual .dot file for each archive
-        if (options.verbose != Analyzer.Type.SUMMARY) {
+        if (options.verbose != SUMMARY) {
             for (Archive archive : sourceLocations) {
                 if (analyzer.hasDependences(archive)) {
-                    Path dotfile = dir.resolve(archive.getFileName() + ".dot");
+                    Path dotfile = dir.resolve(archive.getName() + ".dot");
                     try (PrintWriter pw = new PrintWriter(Files.newOutputStream(dotfile));
                          DotFileFormatter formatter = new DotFileFormatter(pw, archive)) {
                         analyzer.visitDependences(archive, formatter);
@@ -324,17 +393,23 @@
                 }
             }
         }
+        // generate summary dot file
+        generateSummaryDotFile(dir, analyzer);
     }
 
     private void printRawOutput(PrintWriter writer, Analyzer analyzer) {
+        RawOutputFormatter depFormatter = new RawOutputFormatter(writer);
+        RawSummaryFormatter summaryFormatter = new RawSummaryFormatter(writer);
         for (Archive archive : sourceLocations) {
-            RawOutputFormatter formatter = new RawOutputFormatter(writer);
-            analyzer.visitArchiveDependences(archive, formatter);
-            if (options.verbose != Analyzer.Type.SUMMARY) {
-                analyzer.visitDependences(archive, formatter);
+            if (!archive.isEmpty()) {
+                analyzer.visitDependences(archive, summaryFormatter, SUMMARY);
+                if (analyzer.hasDependences(archive) && options.verbose != SUMMARY) {
+                    analyzer.visitDependences(archive, depFormatter);
+                }
             }
         }
     }
+
     private boolean isValidClassName(String name) {
         if (!Character.isJavaIdentifierStart(name.charAt(0))) {
             return false;
@@ -348,21 +423,54 @@
         return true;
     }
 
-    private Dependency.Filter getDependencyFilter() {
-         if (options.regex != null) {
-            return Dependencies.getRegexFilter(Pattern.compile(options.regex));
-        } else if (options.packageNames.size() > 0) {
-            return Dependencies.getPackageFilter(options.packageNames, false);
-        } else {
-            return new Dependency.Filter() {
-                @Override
-                public boolean accepts(Dependency dependency) {
-                    return !dependency.getOrigin().equals(dependency.getTarget());
-                }
-            };
+    /*
+     * Dep Filter configured based on the input jdeps option
+     * 1. -p and -regex to match target dependencies
+     * 2. -filter:package to filter out same-package dependencies
+     *
+     * This filter is applied when jdeps parses the class files
+     * and filtered dependencies are not stored in the Analyzer.
+     *
+     * -filter:archive is applied later in the Analyzer as the
+     * containing archive of a target class may not be known until
+     * the entire archive
+     */
+    class DependencyFilter implements Dependency.Filter {
+        final Dependency.Filter filter;
+        final Pattern filterPattern;
+        DependencyFilter() {
+            if (options.regex != null) {
+                this.filter = Dependencies.getRegexFilter(Pattern.compile(options.regex));
+            } else if (options.packageNames.size() > 0) {
+                this.filter = Dependencies.getPackageFilter(options.packageNames, false);
+            } else {
+                this.filter = null;
+            }
+
+            this.filterPattern =
+                options.filterRegex != null ? Pattern.compile(options.filterRegex) : null;
+        }
+        @Override
+        public boolean accepts(Dependency d) {
+            if (d.getOrigin().equals(d.getTarget())) {
+                return false;
+            }
+            String pn = d.getTarget().getPackageName();
+            if (options.filterSamePackage && d.getOrigin().getPackageName().equals(pn)) {
+                return false;
+            }
+
+            if (filterPattern != null && filterPattern.matcher(pn).matches()) {
+                return false;
+            }
+            return filter != null ? filter.accepts(d) : true;
         }
     }
 
+    /**
+     * Tests if the given class matches the pattern given in the -include option
+     * or if it's a public class if -apionly option is specified
+     */
     private boolean matches(String classname, AccessFlags flags) {
         if (options.apiOnly && !flags.is(AccessFlags.ACC_PUBLIC)) {
             return false;
@@ -377,14 +485,14 @@
         Dependency.Finder finder =
             options.apiOnly ? Dependencies.getAPIFinder(AccessFlags.ACC_PROTECTED)
                             : Dependencies.getClassDependencyFinder();
-        Dependency.Filter filter = getDependencyFilter();
+        Dependency.Filter filter = new DependencyFilter();
 
         List<Archive> archives = new ArrayList<>();
         Deque<String> roots = new LinkedList<>();
         for (String s : classes) {
             Path p = Paths.get(s);
             if (Files.exists(p)) {
-                archives.add(new Archive(p, ClassFileReader.newInstance(p)));
+                archives.add(Archive.getInstance(p));
             } else {
                 if (isValidClassName(s)) {
                     roots.add(s);
@@ -421,20 +529,27 @@
                     throw new ClassFileError(e);
                 }
 
-                if (matches(classFileName, cf.access_flags)) {
-                    if (!doneClasses.contains(classFileName)) {
-                        doneClasses.add(classFileName);
-                    }
-                    for (Dependency d : finder.findDependencies(cf)) {
-                        if (filter.accepts(d)) {
-                            String cn = d.getTarget().getName();
-                            if (!doneClasses.contains(cn) && !deque.contains(cn)) {
-                                deque.add(cn);
-                            }
-                            a.addClass(d.getOrigin(), d.getTarget());
+                // tests if this class matches the -include or -apiOnly option if specified
+                if (!matches(classFileName, cf.access_flags)) {
+                    continue;
+                }
+
+                if (!doneClasses.contains(classFileName)) {
+                    doneClasses.add(classFileName);
+                }
+
+                for (Dependency d : finder.findDependencies(cf)) {
+                    if (filter.accepts(d)) {
+                        String cn = d.getTarget().getName();
+                        if (!doneClasses.contains(cn) && !deque.contains(cn)) {
+                            deque.add(cn);
                         }
+                        a.addClass(d.getOrigin(), d.getTarget());
                     }
                 }
+                for (String name : a.reader().skippedEntries()) {
+                    warning("warn.skipped.entry", name, a.getPathName());
+                }
             }
         }
 
@@ -462,6 +577,10 @@
                             // if name is a fully-qualified class name specified
                             // from command-line, this class might already be parsed
                             doneClasses.add(classFileName);
+                            // process @jdk.Exported for JDK classes
+                            if (isJDKArchive(a)) {
+                                ((JDKArchive)a).processJdkExported(cf);
+                            }
                             for (Dependency d : finder.findDependencies(cf)) {
                                 if (depth == 0) {
                                     // ignore the dependency
@@ -544,7 +663,7 @@
         for (Option o : recognizedOptions) {
             String name = o.aliases[0].substring(1); // there must always be at least one name
             name = name.charAt(0) == '-' ? name.substring(1) : name;
-            if (o.isHidden() || name.equals("h")) {
+            if (o.isHidden() || name.equals("h") || name.startsWith("filter:")) {
                 continue;
             }
             log.println(getMessage("main.opt." + name));
@@ -582,14 +701,19 @@
         boolean fullVersion;
         boolean showProfile;
         boolean showSummary;
-        boolean wildcard;
         boolean apiOnly;
         boolean showLabel;
         boolean findJDKInternals;
+        boolean nowarning;
+        // default is to show package-level dependencies
+        // and filter references from same package
+        Analyzer.Type verbose = PACKAGE;
+        boolean filterSamePackage = true;
+        boolean filterSameArchive = false;
+        String filterRegex;
         String dotOutputDir;
         String classpath = "";
         int depth = 1;
-        Analyzer.Type verbose = Analyzer.Type.PACKAGE;
         Set<String> packageNames = new HashSet<>();
         String regex;             // apply to the dependences
         Pattern includePattern;   // apply to classes
@@ -597,6 +721,7 @@
     private static class ResourceBundleHelper {
         static final ResourceBundle versionRB;
         static final ResourceBundle bundle;
+        static final ResourceBundle jdkinternals;
 
         static {
             Locale locale = Locale.getDefault();
@@ -610,20 +735,12 @@
             } catch (MissingResourceException e) {
                 throw new InternalError("version.resource.missing");
             }
-        }
-    }
-
-    private List<Archive> getArchives(List<String> filenames) throws IOException {
-        List<Archive> result = new ArrayList<Archive>();
-        for (String s : filenames) {
-            Path p = Paths.get(s);
-            if (Files.exists(p)) {
-                result.add(new Archive(p, ClassFileReader.newInstance(p)));
-            } else {
-                warning("warn.file.not.exist", s);
+            try {
+                jdkinternals = ResourceBundle.getBundle("com.sun.tools.jdeps.resources.jdkinternals");
+            } catch (MissingResourceException e) {
+                throw new InternalError("Cannot find jdkinternals resource bundle");
             }
         }
-        return result;
     }
 
     private List<Archive> getClassPathArchives(String paths) throws IOException {
@@ -648,7 +765,7 @@
                 }
                 for (Path f : files) {
                     if (Files.exists(f)) {
-                        result.add(new Archive(f, ClassFileReader.newInstance(f)));
+                        result.add(Archive.getInstance(f));
                     }
                 }
             }
@@ -656,81 +773,50 @@
         return result;
     }
 
-    /**
-     * If the given archive is JDK archive and non-null Profile,
-     * this method returns the profile name only if -profile option is specified;
-     * a null profile indicates it accesses a private JDK API and this method
-     * will return "JDK internal API".
-     *
-     * For non-JDK archives, this method returns the file name of the archive.
-     */
-    private String getProfileArchiveInfo(Archive source, Profile profile) {
-        if (options.showProfile && profile != null)
-            return profile.toString();
-
-        if (source instanceof JDKArchive) {
-            return profile == null ? "JDK internal API (" + source.getFileName() + ")" : "";
-        }
-        return source.getFileName();
-    }
-
-    /**
-     * Returns the profile name or "JDK internal API" for JDK archive;
-     * otherwise empty string.
-     */
-    private String profileName(Archive archive, Profile profile) {
-        if (archive instanceof JDKArchive) {
-            return Objects.toString(profile, "JDK internal API");
-        } else {
-            return "";
-        }
-    }
-
     class RawOutputFormatter implements Analyzer.Visitor {
         private final PrintWriter writer;
+        private String pkg = "";
         RawOutputFormatter(PrintWriter writer) {
             this.writer = writer;
         }
-
-        private String pkg = "";
         @Override
-        public void visitDependence(String origin, Archive source,
-                                    String target, Archive archive, Profile profile) {
-            if (options.findJDKInternals &&
-                    !(archive instanceof JDKArchive && profile == null)) {
-                // filter dependences other than JDK internal APIs
-                return;
-            }
-            if (options.verbose == Analyzer.Type.VERBOSE) {
-                writer.format("   %-50s -> %-50s %s%n",
-                              origin, target, getProfileArchiveInfo(archive, profile));
+        public void visitDependence(String origin, Archive originArchive,
+                                    String target, Archive targetArchive) {
+            String tag = toTag(target, targetArchive);
+            if (options.verbose == VERBOSE) {
+                writer.format("   %-50s -> %-50s %s%n", origin, target, tag);
             } else {
                 if (!origin.equals(pkg)) {
                     pkg = origin;
-                    writer.format("   %s (%s)%n", origin, source.getFileName());
+                    writer.format("   %s (%s)%n", origin, originArchive.getName());
                 }
-                writer.format("      -> %-50s %s%n",
-                              target, getProfileArchiveInfo(archive, profile));
-            }
-        }
-
-        @Override
-        public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
-            writer.format("%s -> %s", origin.getPathName(), target.getPathName());
-            if (options.showProfile && profile != null) {
-                writer.format(" (%s)%n", profile);
-            } else {
-                writer.format("%n");
+                writer.format("      -> %-50s %s%n", target, tag);
             }
         }
     }
 
-    class DotFileFormatter extends DotGraph<String> implements AutoCloseable {
+    class RawSummaryFormatter implements Analyzer.Visitor {
+        private final PrintWriter writer;
+        RawSummaryFormatter(PrintWriter writer) {
+            this.writer = writer;
+        }
+        @Override
+        public void visitDependence(String origin, Archive originArchive,
+                                    String target, Archive targetArchive) {
+            writer.format("%s -> %s", originArchive.getName(), targetArchive.getPathName());
+            if (options.showProfile && JDKArchive.isProfileArchive(targetArchive)) {
+                writer.format(" (%s)", target);
+            }
+            writer.format("%n");
+        }
+    }
+
+    class DotFileFormatter implements Analyzer.Visitor, AutoCloseable {
         private final PrintWriter writer;
         private final String name;
         DotFileFormatter(PrintWriter writer, Archive archive) {
             this.writer = writer;
-            this.name = archive.getFileName();
+            this.name = archive.getName();
             writer.format("digraph \"%s\" {%n", name);
             writer.format("    // Path: %s%n", archive.getPathName());
         }
@@ -741,173 +827,176 @@
         }
 
         @Override
-        public void visitDependence(String origin, Archive source,
-                                    String target, Archive archive, Profile profile) {
-            if (options.findJDKInternals &&
-                    !(archive instanceof JDKArchive && profile == null)) {
-                // filter dependences other than JDK internal APIs
-                return;
-            }
-            // if -P option is specified, package name -> profile will
-            // be shown and filter out multiple same edges.
-            String name = getProfileArchiveInfo(archive, profile);
-            writeEdge(writer, new Edge(origin, target, getProfileArchiveInfo(archive, profile)));
-        }
-        @Override
-        public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
-            throw new UnsupportedOperationException();
+        public void visitDependence(String origin, Archive originArchive,
+                                    String target, Archive targetArchive) {
+            String tag = toTag(target, targetArchive);
+            writer.format("   %-50s -> \"%s\";%n",
+                          String.format("\"%s\"", origin),
+                          tag.isEmpty() ? target
+                                        : String.format("%s (%s)", target, tag));
         }
     }
 
-    class DotSummaryForArchive extends DotGraph<Archive> {
-        @Override
-        public void visitDependence(String origin, Archive source,
-                                    String target, Archive archive, Profile profile) {
-            Edge e = findEdge(source, archive);
-            assert e != null;
-            // add the dependency to the label if enabled and not compact1
-            if (profile == Profile.COMPACT1) {
-                return;
-            }
-            e.addLabel(origin, target, profileName(archive, profile));
-        }
-        @Override
-        public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
-            // add an edge with the archive's name with no tag
-            // so that there is only one node for each JDK archive
-            // while there may be edges to different profiles
-            Edge e = addEdge(origin, target, "");
-            if (target instanceof JDKArchive) {
-                // add a label to print the profile
-                if (profile == null) {
-                    e.addLabel("JDK internal API");
-                } else if (options.showProfile && !options.showLabel) {
-                    e.addLabel(profile.toString());
-                }
-            }
-        }
-    }
-
-    // DotSummaryForPackage generates the summary.dot file for verbose mode
-    // (-v or -verbose option) that includes all class dependencies.
-    // The summary.dot file shows package-level dependencies.
-    class DotSummaryForPackage extends DotGraph<String> {
-        private String packageOf(String cn) {
-            int i = cn.lastIndexOf('.');
-            return i > 0 ? cn.substring(0, i) : "<unnamed>";
-        }
-        @Override
-        public void visitDependence(String origin, Archive source,
-                                    String target, Archive archive, Profile profile) {
-            // add a package dependency edge
-            String from = packageOf(origin);
-            String to = packageOf(target);
-            Edge e = addEdge(from, to, getProfileArchiveInfo(archive, profile));
-
-            // add the dependency to the label if enabled and not compact1
-            if (!options.showLabel || profile == Profile.COMPACT1) {
-                return;
-            }
-
-            // trim the package name of origin to shorten the label
-            int i = origin.lastIndexOf('.');
-            String n1 = i < 0 ? origin : origin.substring(i+1);
-            e.addLabel(n1, target, profileName(archive, profile));
-        }
-        @Override
-        public void visitArchiveDependence(Archive origin, Archive target, Profile profile) {
-            // nop
-        }
-    }
-    abstract class DotGraph<T> implements Analyzer.Visitor  {
-        private final Set<Edge> edges = new LinkedHashSet<>();
-        private Edge curEdge;
-        public void writeTo(PrintWriter writer) {
+    class SummaryDotFile implements Analyzer.Visitor, AutoCloseable {
+        private final PrintWriter writer;
+        private final Analyzer.Type type;
+        private final Map<Archive, Map<Archive,StringBuilder>> edges = new HashMap<>();
+        SummaryDotFile(PrintWriter writer, Analyzer.Type type) {
+            this.writer = writer;
+            this.type = type;
             writer.format("digraph \"summary\" {%n");
-            for (Edge e: edges) {
-                writeEdge(writer, e);
-            }
+        }
+
+        @Override
+        public void close() {
             writer.println("}");
         }
 
-        void writeEdge(PrintWriter writer, Edge e) {
-            writer.format("   %-50s -> \"%s\"%s;%n",
-                          String.format("\"%s\"", e.from.toString()),
-                          e.tag.isEmpty() ? e.to
-                                          : String.format("%s (%s)", e.to, e.tag),
-                          getLabel(e));
+        @Override
+        public void visitDependence(String origin, Archive originArchive,
+                                    String target, Archive targetArchive) {
+            String targetName = type == PACKAGE ? target : targetArchive.getName();
+            if (type == PACKAGE) {
+                String tag = toTag(target, targetArchive, type);
+                if (!tag.isEmpty())
+                    targetName += " (" + tag + ")";
+            } else if (options.showProfile && JDKArchive.isProfileArchive(targetArchive)) {
+                targetName += " (" + target + ")";
+            }
+            String label = getLabel(originArchive, targetArchive);
+            writer.format("  %-50s -> \"%s\"%s;%n",
+                          String.format("\"%s\"", origin), targetName, label);
         }
 
-        Edge addEdge(T origin, T target, String tag) {
-            Edge e = new Edge(origin, target, tag);
-            if (e.equals(curEdge)) {
-                return curEdge;
-            }
+        String getLabel(Archive origin, Archive target) {
+            if (edges.isEmpty())
+                return "";
 
-            if (edges.contains(e)) {
-                for (Edge e1 : edges) {
-                   if (e.equals(e1)) {
-                       curEdge = e1;
-                   }
+            StringBuilder label = edges.get(origin).get(target);
+            return label == null ? "" : String.format(" [label=\"%s\",fontsize=9]", label.toString());
+        }
+
+        Analyzer.Visitor labelBuilder() {
+            // show the package-level dependencies as labels in the dot graph
+            return new Analyzer.Visitor() {
+                @Override
+                public void visitDependence(String origin, Archive originArchive,
+                                            String target, Archive targetArchive)
+                {
+                    Map<Archive,StringBuilder> labels = edges.get(originArchive);
+                    if (!edges.containsKey(originArchive)) {
+                        edges.put(originArchive, labels = new HashMap<>());
+                    }
+                    StringBuilder sb = labels.get(targetArchive);
+                    if (sb == null) {
+                        labels.put(targetArchive, sb = new StringBuilder());
+                    }
+                    String tag = toTag(target, targetArchive, PACKAGE);
+                    addLabel(sb, origin, target, tag);
                 }
-            } else {
-                edges.add(e);
-                curEdge = e;
-            }
-            return curEdge;
+
+                void addLabel(StringBuilder label, String origin, String target, String tag) {
+                    label.append(origin).append(" -> ").append(target);
+                    if (!tag.isEmpty()) {
+                        label.append(" (" + tag + ")");
+                    }
+                    label.append("\\n");
+                }
+            };
+        }
+    }
+
+    /**
+     * Test if the given archive is part of the JDK
+     */
+    private boolean isJDKArchive(Archive archive) {
+        return JDKArchive.class.isInstance(archive);
+    }
+
+    /**
+     * If the given archive is JDK archive, this method returns the profile name
+     * only if -profile option is specified; it accesses a private JDK API and
+     * the returned value will have "JDK internal API" prefix
+     *
+     * For non-JDK archives, this method returns the file name of the archive.
+     */
+    private String toTag(String name, Archive source, Analyzer.Type type) {
+        if (!isJDKArchive(source)) {
+            return source.getName();
         }
 
-        Edge findEdge(T origin, T target) {
-            for (Edge e : edges) {
-                if (e.from.equals(origin) && e.to.equals(target)) {
-                    return e;
+        JDKArchive jdk = (JDKArchive)source;
+        boolean isExported = false;
+        if (type == CLASS || type == VERBOSE) {
+            isExported = jdk.isExported(name);
+        } else {
+            isExported = jdk.isExportedPackage(name);
+        }
+        Profile p = getProfile(name, type);
+        if (isExported) {
+            // exported API
+            return options.showProfile && p != null ? p.profileName() : "";
+        } else {
+            return "JDK internal API (" + source.getName() + ")";
+        }
+    }
+
+    private String toTag(String name, Archive source) {
+        return toTag(name, source, options.verbose);
+    }
+
+    private Profile getProfile(String name, Analyzer.Type type) {
+        String pn = name;
+        if (type == CLASS || type == VERBOSE) {
+            int i = name.lastIndexOf('.');
+            pn = i > 0 ? name.substring(0, i) : "";
+        }
+        return Profile.getProfile(pn);
+    }
+
+    /**
+     * Returns the recommended replacement API for the given classname;
+     * or return null if replacement API is not known.
+     */
+    private String replacementFor(String cn) {
+        String name = cn;
+        String value = null;
+        while (value == null && name != null) {
+            try {
+                value = ResourceBundleHelper.jdkinternals.getString(name);
+            } catch (MissingResourceException e) {
+                // go up one subpackage level
+                int i = name.lastIndexOf('.');
+                name = i > 0 ? name.substring(0, i) : null;
+            }
+        }
+        return value;
+    };
+
+    private void showReplacements(Analyzer analyzer) {
+        Map<String,String> jdkinternals = new TreeMap<>();
+        boolean useInternals = false;
+        for (Archive source : sourceLocations) {
+            useInternals = useInternals || analyzer.hasDependences(source);
+            for (String cn : analyzer.dependences(source)) {
+                String repl = replacementFor(cn);
+                if (repl != null && !jdkinternals.containsKey(cn)) {
+                    jdkinternals.put(cn, repl);
                 }
             }
-            return null;
+        }
+        if (useInternals) {
+            log.println();
+            warning("warn.replace.useJDKInternals", getMessage("jdeps.wiki.url"));
+        }
+        if (!jdkinternals.isEmpty()) {
+            log.println();
+            log.format("%-40s %s%n", "JDK Internal API", "Suggested Replacement");
+            log.format("%-40s %s%n", "----------------", "---------------------");
+            for (Map.Entry<String,String> e : jdkinternals.entrySet()) {
+                log.format("%-40s %s%n", e.getKey(), e.getValue());
+            }
         }
 
-        String getLabel(Edge e) {
-            String label = e.label.toString();
-            return label.isEmpty() ? "" : String.format("[label=\"%s\",fontsize=9]", label);
-        }
-
-        class Edge {
-            final T from;
-            final T to;
-            final String tag;  // optional tag
-            final StringBuilder label = new StringBuilder();
-            Edge(T from, T to, String tag) {
-                this.from = from;
-                this.to = to;
-                this.tag = tag;
-            }
-            void addLabel(String s) {
-                label.append(s).append("\\n");
-            }
-            void addLabel(String origin, String target, String profile) {
-                label.append(origin).append(" -> ").append(target);
-                if (!profile.isEmpty()) {
-                    label.append(" (" + profile + ")");
-                }
-                label.append("\\n");
-            }
-            @Override @SuppressWarnings("unchecked")
-            public boolean equals(Object o) {
-                if (o instanceof DotGraph<?>.Edge) {
-                    DotGraph<?>.Edge e = (DotGraph<?>.Edge)o;
-                    return this.from.equals(e.from) &&
-                           this.to.equals(e.to) &&
-                           this.tag.equals(e.tag);
-                }
-                return false;
-            }
-            @Override
-            public int hashCode() {
-                int hash = 7;
-                hash = 67 * hash + Objects.hashCode(this.from) +
-                       Objects.hashCode(this.to) + Objects.hashCode(this.tag);
-                return hash;
-            }
-        }
     }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/Main.java b/langtools/src/share/classes/com/sun/tools/jdeps/Main.java
index 863815f..a693062 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/Main.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/Main.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -63,4 +63,3 @@
         return t.run(args);
     }
 }
-
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java b/langtools/src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
index 3c1950a..55b9e8a 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/PlatformClassPath.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -24,6 +24,12 @@
  */
 package com.sun.tools.jdeps;
 
+import com.sun.tools.classfile.Annotation;
+import com.sun.tools.classfile.ClassFile;
+import com.sun.tools.classfile.ConstantPool;
+import com.sun.tools.classfile.ConstantPoolException;
+import com.sun.tools.classfile.RuntimeAnnotations_attribute;
+import com.sun.tools.classfile.Dependencies.ClassFileError;
 import java.io.IOException;
 import java.nio.file.FileVisitResult;
 import java.nio.file.Files;
@@ -33,11 +39,15 @@
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.*;
 
+import static com.sun.tools.classfile.Attribute.*;
+
 /**
  * ClassPath for Java SE and JDK
  */
 class PlatformClassPath {
-    private final static List<Archive> javaHomeArchives = init();
+    private static final List<String> NON_PLATFORM_JARFILES =
+        Arrays.asList("alt-rt.jar", "jfxrt.jar", "ant-javafx.jar", "javafx-mx.jar");
+    private static final List<Archive> javaHomeArchives = init();
 
     static List<Archive> getArchives() {
         return javaHomeArchives;
@@ -50,12 +60,19 @@
             if (home.endsWith("jre")) {
                 // jar files in <javahome>/jre/lib
                 result.addAll(addJarFiles(home.resolve("lib")));
+                if (home.getParent() != null) {
+                    // add tools.jar and other JDK jar files
+                    Path lib = home.getParent().resolve("lib");
+                    if (Files.exists(lib)) {
+                        result.addAll(addJarFiles(lib));
+                    }
+                }
             } else if (Files.exists(home.resolve("lib"))) {
                 // either a JRE or a jdk build image
                 Path classes = home.resolve("classes");
                 if (Files.isDirectory(classes)) {
                     // jdk build outputdir
-                    result.add(new JDKArchive(classes, ClassFileReader.newInstance(classes)));
+                    result.add(new JDKArchive(classes));
                 }
                 // add other JAR files
                 result.addAll(addJarFiles(home.resolve("lib")));
@@ -91,9 +108,9 @@
                 if (fn.endsWith(".jar")) {
                     // JDK may cobundle with JavaFX that doesn't belong to any profile
                     // Treat jfxrt.jar as regular Archive
-                    result.add(fn.equals("jfxrt.jar")
-                        ? new Archive(p, ClassFileReader.newInstance(p))
-                        : new JDKArchive(p, ClassFileReader.newInstance(p)));
+                    result.add(NON_PLATFORM_JARFILES.contains(fn)
+                                   ? Archive.getInstance(p)
+                                   : new JDKArchive(p));
                 }
                 return FileVisitResult.CONTINUE;
             }
@@ -106,8 +123,91 @@
      * or implementation classes (i.e. JDK internal API)
      */
     static class JDKArchive extends Archive {
-        JDKArchive(Path p, ClassFileReader reader) {
-            super(p, reader);
+        private static List<String> PROFILE_JARS = Arrays.asList("rt.jar", "jce.jar");
+        public static boolean isProfileArchive(Archive archive) {
+            if (archive instanceof JDKArchive) {
+                return PROFILE_JARS.contains(archive.getName());
+            }
+            return false;
+        }
+
+        private final Map<String,Boolean> exportedPackages = new HashMap<>();
+        private final Map<String,Boolean> exportedTypes = new HashMap<>();
+        JDKArchive(Path p) throws IOException {
+            super(p, ClassFileReader.newInstance(p));
+        }
+
+        /**
+         * Tests if a given fully-qualified name is an exported type.
+         */
+        public boolean isExported(String cn) {
+            int i = cn.lastIndexOf('.');
+            String pn = i > 0 ? cn.substring(0, i) : "";
+
+            boolean isJdkExported = isExportedPackage(pn);
+            if (exportedTypes.containsKey(cn)) {
+                return exportedTypes.get(cn);
+            }
+            return isJdkExported;
+        }
+
+        /**
+         * Tests if a given package name is exported.
+         */
+        public boolean isExportedPackage(String pn) {
+            if (Profile.getProfile(pn) != null) {
+                return true;
+            }
+            return exportedPackages.containsKey(pn) ? exportedPackages.get(pn) : false;
+        }
+
+        private static final String JDK_EXPORTED_ANNOTATION = "Ljdk/Exported;";
+        private Boolean isJdkExported(ClassFile cf) throws ConstantPoolException {
+            RuntimeAnnotations_attribute attr = (RuntimeAnnotations_attribute)
+                    cf.attributes.get(RuntimeVisibleAnnotations);
+            if (attr != null) {
+                for (int i = 0; i < attr.annotations.length; i++) {
+                    Annotation ann = attr.annotations[i];
+                    String annType = cf.constant_pool.getUTF8Value(ann.type_index);
+                    if (JDK_EXPORTED_ANNOTATION.equals(annType)) {
+                        boolean isJdkExported = true;
+                        for (int j = 0; j < ann.num_element_value_pairs; j++) {
+                            Annotation.element_value_pair pair = ann.element_value_pairs[j];
+                            Annotation.Primitive_element_value ev = (Annotation.Primitive_element_value) pair.value;
+                            ConstantPool.CONSTANT_Integer_info info = (ConstantPool.CONSTANT_Integer_info)
+                                    cf.constant_pool.get(ev.const_value_index);
+                            isJdkExported = info.value != 0;
+                        }
+                        return Boolean.valueOf(isJdkExported);
+                    }
+                }
+            }
+            return null;
+        }
+
+        void processJdkExported(ClassFile cf) throws IOException {
+            try {
+                String cn = cf.getName();
+                String pn = cn.substring(0, cn.lastIndexOf('/')).replace('/', '.');
+
+                Boolean b = isJdkExported(cf);
+                if (b != null) {
+                    exportedTypes.put(cn.replace('/', '.'), b);
+                }
+                if (!exportedPackages.containsKey(pn)) {
+                    // check if package-info.class has @jdk.Exported
+                    Boolean isJdkExported = null;
+                    ClassFile pcf = reader().getClassFile(cn.substring(0, cn.lastIndexOf('/')+1) + "package-info");
+                    if (pcf != null) {
+                        isJdkExported = isJdkExported(pcf);
+                    }
+                    if (isJdkExported != null) {
+                        exportedPackages.put(pn, isJdkExported);
+                    }
+                }
+            } catch (ConstantPoolException e) {
+                throw new ClassFileError(e);
+            }
         }
     }
 }
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/Profile.java b/langtools/src/share/classes/com/sun/tools/jdeps/Profile.java
index 4d35855..d78b5c4 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/Profile.java
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/Profile.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -43,7 +43,6 @@
  * Build the profile information from ct.sym if exists.
  */
 enum Profile {
-
     COMPACT1("compact1", 1),
     COMPACT2("compact2", 2),
     COMPACT3("compact3", 3),
@@ -61,8 +60,7 @@
         this.proprietaryPkgs = new HashSet<>();
     }
 
-    @Override
-    public String toString() {
+    public String profileName() {
         return name;
     }
 
@@ -77,7 +75,7 @@
     public static Profile getProfile(String pn) {
         Profile profile = PackageToProfile.map.get(pn);
         return (profile != null && profile.packages.contains(pn))
-                ? profile : null;
+                    ? profile : null;
     }
 
     static class PackageToProfile {
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
index ca7493e79..ccd14ab 100644
--- a/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdeps.properties
@@ -1,6 +1,6 @@
 main.usage.summary=\
 Usage: {0} <options> <classes...>\n\
-use -h, -? or --help for a list of possible options
+use -h, -? or -help for a list of possible options
 
 main.usage=\
 Usage: {0} <options> <classes...>\n\
@@ -18,20 +18,29 @@
 
 main.opt.v=\
 \  -v           -verbose              Print all class level dependencies\n\
+\                                     Equivalent to -verbose:class -filter:none.\n\
 \  -verbose:package                   Print package-level dependencies excluding\n\
-\                                     dependencies within the same archive\n\
+\                                     dependencies within the same package by default\n\
 \  -verbose:class                     Print class-level dependencies excluding\n\
-\                                     dependencies within the same archive
+\                                     dependencies within the same package by default
+
+main.opt.f=\
+\  -f <regex>   -filter <regex>       Filter dependences matching the given pattern\n\
+\                                     If given multiple times, the last one will be used.\n\
+\  -filter:package                    Filter dependences within the same package (default)\n\
+\  -filter:archive                    Filter dependences within the same archive\n\
+\  -filter:none                       No -filter:package and -filter:archive filtering\n\
+\                                     Filtering specified via the -filter option still applies.
 
 main.opt.s=\
 \  -s           -summary              Print dependency summary only
 
 main.opt.p=\
-\  -p <pkgname> -package <pkgname>    Finds dependences in the given package\n\
+\  -p <pkgname> -package <pkgname>    Finds dependences matching the given package name\n\
 \                                     (may be given multiple times)
 
 main.opt.e=\
-\  -e <regex>   -regex <regex>        Finds dependences in packages matching pattern\n\
+\  -e <regex>   -regex <regex>        Finds dependences matching the given pattern\n\
 \                                     (-p and -e are exclusive)
 
 main.opt.include=\
@@ -47,7 +56,10 @@
 \  -cp <path>   -classpath <path>     Specify where to find class files
 
 main.opt.R=\
-\  -R           -recursive            Recursively traverse all dependencies
+\  -R           -recursive            Recursively traverse all dependencies.\n\
+\                                     The -R option implies -filter:none.  If -p, -e, -f\n\
+\                                     option is specified, only the matching dependences\n\
+\                                     are analyzed.
 
 main.opt.apionly=\
 \  -apionly                           Restrict analysis to APIs i.e. dependences\n\
@@ -74,13 +86,19 @@
 
 err.unknown.option=unknown option: {0}
 err.missing.arg=no value given for {0}
-err.internal.error=internal error: {0} {1} {2}
 err.invalid.arg.for.option=invalid argument for option: {0}
 err.option.after.class=option must be specified before classes: {0}
 err.option.unsupported={0} not supported: {1}
 err.profiles.msg=No profile information
-err.dot.output.path=invalid path: {0}
+err.invalid.path=invalid path: {0}
 warn.invalid.arg=Invalid classname or pathname not exist: {0}
 warn.split.package=package {0} defined in {1} {2}
+warn.replace.useJDKInternals=\
+JDK internal APIs are unsupported and private to JDK implementation that are\n\
+subject to be removed or changed incompatibly and could break your application.\n\
+Please modify your code to eliminate dependency on any JDK internal APIs.\n\
+For the most recent update on JDK internal API replacements, please check:\n\
+{0}
 
 artifact.not.found=not found
+jdeps.wiki.url=https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool
diff --git a/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
new file mode 100644
index 0000000..56d7d0a
--- /dev/null
+++ b/langtools/src/share/classes/com/sun/tools/jdeps/resources/jdkinternals.properties
@@ -0,0 +1,22 @@
+// No translation needed
+com.sun.crypto.provider.SunJCE=Use java.security.Security.getProvider(provider-name) @since 1.3
+com.sun.image.codec=Use javax.imageio @since 1.4
+com.sun.org.apache.xml.internal.security=Use java.xml.crypto @since 1.6
+com.sun.org.apache.xml.internal.security.utils.Base64=Use java.util.Base64 @since 1.8
+com.sun.net.ssl=Use javax.net.ssl @since 1.4
+com.sun.net.ssl.internal.ssl.Provider=Use java.security.Security.getProvider(provider-name) @since 1.3
+com.sun.rowset=Use javax.sql.rowset.RowSetProvider @since 1.7
+com.sun.tools.javac.tree=Use com.sun.source @since 1.6
+com.sun.tools.javac=Use javax.tools and javax.lang.model @since 1.6
+sun.awt.image.codec=Use javax.imageio @since 1.4
+sun.misc.BASE64Encoder=Use java.util.Base64 @since 1.8
+sun.misc.BASE64Decoder=Use java.util.Base64 @since 1.8
+sun.misc.Cleaner=Use java.lang.ref.PhantomReference @since 1.2
+sun.misc.Service=Use java.util.ServiceLoader @since 1.6
+sun.security.action=Use java.security.PrivilegedAction @since 1.1
+sun.security.krb5=Use com.sun.security.jgss
+sun.security.provider.PolicyFile=Use java.security.Policy.getInstance("JavaPolicy", new URIParameter(uri)) @since 1.6
+sun.security.provider.Sun=Use java.security.Security.getProvider(provider-name) @since 1.3
+sun.security.util.SecurityConstants=Use appropriate java.security.Permission subclass @since 1.1
+sun.security.x509.X500Name=Use javax.security.auth.x500.X500Principal @since 1.4
+sun.tools.jar=Use java.util.jar or jar tool @since 1.2
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/T8050386/WrongStackframeGenerationTest1.java
similarity index 64%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/T8050386/WrongStackframeGenerationTest1.java
index e2824dd..92dd32a 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/T8050386/WrongStackframeGenerationTest1.java
@@ -1,48 +1,47 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
-/**
+/*
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8050386
+ * @summary Verification error due to a bad stackmap frame generated by javac
  */
 
-load(__DIR__ + "maputil.js");
+public class WrongStackframeGenerationTest1 {
+    public static void main(String[] args) {}
 
-function Foo() {
-    this.x = 33;
+    static void foo(){
+        while (true) {
+            int i = 0;
+            break;
+        }
+        switch (1) {
+            case 1:
+                int j = 0;
+            case 2:
+                bar();
+        }
+    }
+
+    static void bar() {}
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/T8050386/WrongStackframeGenerationTest2.java
similarity index 62%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/T8050386/WrongStackframeGenerationTest2.java
index e2824dd..bf4b31a 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/T8050386/WrongStackframeGenerationTest2.java
@@ -1,48 +1,50 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
-/**
+/*
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8050386
+ * @summary Verification error due to a bad stackmap frame generated by javac
  */
 
-load(__DIR__ + "maputil.js");
+public class WrongStackframeGenerationTest2 {
+    public static void main(String[] args) {}
 
-function Foo() {
-    this.x = 33;
+    static void foo() {
+        int len;
+        for (;;) {
+            try {
+                len = 1;
+                break;
+            } catch (Exception e) {
+            }
+        }
+
+        try {
+           if (len == -1) {
+               len = 0;
+           }
+        } finally {
+        }
+    }
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/langtools/test/tools/javac/flow/LVTHarness.java b/langtools/test/tools/javac/flow/LVTHarness.java
index 7039a62..c176e5e 100644
--- a/langtools/test/tools/javac/flow/LVTHarness.java
+++ b/langtools/test/tools/javac/flow/LVTHarness.java
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 7047734 8027660 8037937
+ * @bug 7047734 8027660 8037937 8047719
  * @summary The LVT is not generated correctly during some try/catch scenarios
  *          javac crash while creating LVT entry for a local variable defined in
  *          an inner block
diff --git a/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java b/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java
index d96850f..e67e191 100644
--- a/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java
+++ b/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java
@@ -5,7 +5,7 @@
     @AliveRange(varName="o", bytecodeStart=31, bytecodeLength=16)
     @AliveRange(varName="o", bytecodeStart=50, bytecodeLength=15)
     @AliveRange(varName="o", bytecodeStart=68, bytecodeLength=1)
-    @AliveRange(varName="oo", bytecodeStart=39, bytecodeLength=26)
+    @AliveRange(varName="oo", bytecodeStart=39, bytecodeLength=8)
     @AliveRange(varName="uu", bytecodeStart=59, bytecodeLength=6)
     void m1(String[] args) {
         Object o;
@@ -29,7 +29,7 @@
     @AliveRange(varName="o", bytecodeStart=95, bytecodeLength=18)
     @AliveRange(varName="o", bytecodeStart=116, bytecodeLength=15)
     @AliveRange(varName="o", bytecodeStart=134, bytecodeLength=1)
-    @AliveRange(varName="oo", bytecodeStart=104, bytecodeLength=27)
+    @AliveRange(varName="oo", bytecodeStart=104, bytecodeLength=9)
     @AliveRange(varName="uu", bytecodeStart=125, bytecodeLength=6)
     void m2(String[] args) {
         Object o;
@@ -50,12 +50,14 @@
         o = "return";
     }
 
-    @AliveRange(varName="o", bytecodeStart=31, bytecodeLength=8)
-    @AliveRange(varName="o", bytecodeStart=42, bytecodeLength=8)
-    @AliveRange(varName="o", bytecodeStart=53, bytecodeLength=9)
-    void m3(String[] args) {
+    @AliveRange(varName="o", bytecodeStart=35, bytecodeLength=8)
+    @AliveRange(varName="o", bytecodeStart=46, bytecodeLength=8)
+    @AliveRange(varName="o", bytecodeStart=78, bytecodeLength=5)
+    @AliveRange(varName="o", bytecodeStart=86, bytecodeLength=1)
+    @AliveRange(varName="oo", bytecodeStart=56, bytecodeLength=16)
+    void m3(int i) {
         Object o;
-        switch (args.length) {
+        switch (i) {
             case 0:
                     o = "0";
                     o.hashCode();
@@ -64,10 +66,19 @@
                     o = "1";
                     o.hashCode();
                     break;
+            case 2:
+                int oo = i;
+                if (oo > 1) {
+                    System.out.println("greater");
+                }
+                break;
+            case 3:
+                int uu = i;
             default:
                     o = "default";
                     o.hashCode();
         }
         o = "finish";
     }
+
 }
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/generics/inference/8043926/T8043926.java
similarity index 64%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/generics/inference/8043926/T8043926.java
index e2824dd..88f0f1b 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/generics/inference/8043926/T8043926.java
@@ -1,21 +1,21 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
@@ -23,26 +23,21 @@
 
 /**
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8043926
+ * @summary javac, code valid in 7 is not compiling for 8
+ * @compile T8043926.java
  */
+class T8043926 {
+    interface Iface<T1> {}
 
-load(__DIR__ + "maputil.js");
+    static class Impl implements Iface<Impl> {}
 
-function Foo() {
-    this.x = 33;
+    static class Acceptor<T2 extends Iface<T2>> {
+        public Acceptor(T2 obj) {}
+    }
+
+    void test(Impl impl) {
+        Acceptor<?> acceptor1 = new Acceptor<>(impl);
+        Acceptor<? extends Object> acceptor2 = new Acceptor<>(impl);
+    }
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/langtools/test/tools/javac/generics/inference/T8044546/CrashImplicitLambdaTest.java
similarity index 71%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to langtools/test/tools/javac/generics/inference/T8044546/CrashImplicitLambdaTest.java
index db358d2..a34b356 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/langtools/test/tools/javac/generics/inference/T8044546/CrashImplicitLambdaTest.java
@@ -1,33 +1,41 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
- *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @bug 8044546
+ * @summary Crash on faulty reduce/lambda
+ * @compile CrashImplicitLambdaTest.java
  */
 
-load(__DIR__ + "runsunspider.js");
+abstract class CrashImplicitLambdaTest {
+    boolean foo() {
+        return bar(true, a -> {});
+    }
 
+    abstract <T1> T1 bar(T1 t1, S<T1> s);
+
+    interface S<S1> {
+        void baz(S1 s1);
+    }
+}
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/generics/inference/T8044546/NestedInvocationsTest.java
similarity index 68%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/generics/inference/T8044546/NestedInvocationsTest.java
index e2824dd..40e5c3d 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/generics/inference/T8044546/NestedInvocationsTest.java
@@ -1,21 +1,21 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
@@ -23,26 +23,25 @@
 
 /**
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8044546
+ * @summary Crash on faulty reduce/lambda
+ * @compile NestedInvocationsTest.java
  */
 
-load(__DIR__ + "maputil.js");
+class NestedInvocationsTest<T> {
+    boolean foo(I<T> i) {
+        return baz(zas(i));
+    }
 
-function Foo() {
-    this.x = 33;
+    <U> J<U, Boolean> zas(I<U> i) {
+        return null;
+    }
+
+    <R> R baz(J<T, R> j) {
+        return null;
+    }
+
+    interface I<I1> {}
+
+    interface J<J1, J2> {}
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/generics/wildcards/T8051402/WildcardAndCAPSubtypeTest.java
similarity index 66%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/generics/wildcards/T8051402/WildcardAndCAPSubtypeTest.java
index e2824dd..400ba8a 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/generics/wildcards/T8051402/WildcardAndCAPSubtypeTest.java
@@ -1,48 +1,40 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
-/**
+/*
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8051402
+ * @summary javac, type containment should accept that CAP <= ? extends CAP and CAP <= ? super CAP
+ * @compile WildcardAndCAPSubtypeTest.java
  */
 
-load(__DIR__ + "maputil.js");
+import java.util.List;
 
-function Foo() {
-    this.x = 33;
+public abstract class WildcardAndCAPSubtypeTest {
+    abstract <T> List<T> copyOf(List<? extends T> lx);
+    abstract <E> List<E> filter(List<E> lx);
+
+    void g(List<?> lx) {
+        copyOf(filter(lx));
+    }
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/langtools/test/tools/javac/lambda/LambdaTestStrictFP.java b/langtools/test/tools/javac/lambda/LambdaTestStrictFP.java
new file mode 100644
index 0000000..67e247e
--- /dev/null
+++ b/langtools/test/tools/javac/lambda/LambdaTestStrictFP.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8046060
+ * @summary Different results of floating point multiplication for lambda code block
+ */
+
+strictfp
+public class LambdaTestStrictFP {
+
+    static double fld =  eval(() -> {
+            double x = Double.longBitsToDouble(0x1e7ee00000000000L);
+            double y = Double.longBitsToDouble(0x2180101010101010L);
+
+            return x * y;
+        });
+
+    public static void main(String args[]) {
+        double result = eval(() -> {
+            double x = Double.longBitsToDouble(0x1e7ee00000000000L);
+            double y = Double.longBitsToDouble(0x2180101010101010L);
+
+            return x * y;
+        });
+        {
+            double x = Double.longBitsToDouble(0x1e7ee00000000000L);
+            double y = Double.longBitsToDouble(0x2180101010101010L);
+
+            double z = x * y;
+            check(z, result, "method");
+            check(z, fld, "field");
+        }
+    }
+
+    private static void check(double expected, double got, String where) {
+        if (got != expected) {
+            throw new AssertionError(where + ": Non-strictfp " + got + " != " + expected);
+        }
+    }
+
+    private static double eval(Face arg) {
+        return arg.m();
+    }
+
+    private interface Face {
+        double m();
+    }
+}
diff --git a/langtools/test/tools/javac/lambda/LambdaTestStrictFPFlag.java b/langtools/test/tools/javac/lambda/LambdaTestStrictFPFlag.java
new file mode 100644
index 0000000..dc1cccd
--- /dev/null
+++ b/langtools/test/tools/javac/lambda/LambdaTestStrictFPFlag.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8046060
+ * @summary Different results of floating point multiplication for lambda code block
+ */
+
+import java.io.*;
+import java.net.URL;
+import com.sun.tools.classfile.*;
+import static com.sun.tools.classfile.AccessFlags.ACC_STRICT;
+
+public class LambdaTestStrictFPFlag {
+    public static void main(String[] args) throws Exception {
+        new LambdaTestStrictFPFlag().run();
+    }
+
+    void run() throws Exception {
+        ClassFile cf = getClassFile("LambdaTestStrictFPFlag$Test.class");
+        ConstantPool cp = cf.constant_pool;
+        boolean found = false;
+        for (Method meth: cf.methods) {
+            if (meth.getName(cp).startsWith("lambda$")) {
+                if ((meth.access_flags.flags & ACC_STRICT) == 0) {
+                    throw new Exception("strict flag missing from lambda");
+                }
+                found = true;
+            }
+        }
+        if (!found) {
+            throw new Exception("did not find lambda method");
+        }
+    }
+
+    ClassFile getClassFile(String name) throws IOException, ConstantPoolException {
+        URL url = getClass().getResource(name);
+        InputStream in = url.openStream();
+        try {
+            return ClassFile.read(in);
+        } finally {
+            in.close();
+        }
+    }
+
+    class Test {
+        strictfp void test() {
+            Face itf = () -> { };
+        }
+    }
+
+    interface Face {
+        void m();
+    }
+}
diff --git a/langtools/test/tools/javac/lambda/LambdaTestStrictFPMethod.java b/langtools/test/tools/javac/lambda/LambdaTestStrictFPMethod.java
new file mode 100644
index 0000000..e8a03eb
--- /dev/null
+++ b/langtools/test/tools/javac/lambda/LambdaTestStrictFPMethod.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8046060
+ * @summary Different results of floating point multiplication for lambda code block
+ */
+
+public class LambdaTestStrictFPMethod {
+
+    public static void main(String args[]) {
+        new LambdaTestStrictFPMethod().test();
+    }
+
+    strictfp void test() {
+        double result = eval(() -> {
+            double x = Double.longBitsToDouble(0x1e7ee00000000000L);
+            double y = Double.longBitsToDouble(0x2180101010101010L);
+
+            return x * y;
+        });
+        {
+            double x = Double.longBitsToDouble(0x1e7ee00000000000L);
+            double y = Double.longBitsToDouble(0x2180101010101010L);
+
+            double z = x * y;
+            check(z, result, "method");
+        }
+    }
+
+    strictfp void check(double expected, double got, String where) {
+        if (got != expected) {
+            throw new AssertionError(where + ": Non-strictfp " + got + " != " + expected);
+        }
+    }
+
+    static double eval(Face arg) {
+        return arg.m();
+    }
+
+    interface Face {
+        double m();
+    }
+}
diff --git a/langtools/test/tools/javac/lambda/TargetType61.java b/langtools/test/tools/javac/lambda/TargetType61.java
index 1eae34e..c319770 100644
--- a/langtools/test/tools/javac/lambda/TargetType61.java
+++ b/langtools/test/tools/javac/lambda/TargetType61.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8007464
+ * @bug 8007464 8051402
  * @summary Add graph inference support
  *          check that new wildcards inference strategy doesn't run into 7190296
  * @compile TargetType61.java
diff --git a/langtools/test/tools/javac/varargs/6313164/T6313164.java b/langtools/test/tools/javac/varargs/6313164/T6313164.java
index 3e82845..7df40d0 100644
--- a/langtools/test/tools/javac/varargs/6313164/T6313164.java
+++ b/langtools/test/tools/javac/varargs/6313164/T6313164.java
@@ -1,18 +1,26 @@
 /*
  * @test /nodynamiccopyright/
- * @bug     6313164
+ * @bug     6313164 8036953
  * @author mcimadamore
  * @summary  javac generates code that fails byte code verification for the varargs feature
- * @compile/fail/ref=T6313164.out -XDrawDiagnostics T6313164.java
+ * @compile/fail/ref=T6313164Source7.out -source 7 -XDrawDiagnostics T6313164.java
+ * @compile/fail/ref=T6313164Source8AndHigher.out -XDrawDiagnostics T6313164.java
  */
 import p1.*;
 
 class T6313164 {
-    { B b = new B();
-      b.foo1(new B(), new B()); //error - A not accesible
-      b.foo2(new B(), new B()); //ok - A not accessible, but foo2(Object...) applicable
-      b.foo3(null, null); //error - A (inferred) not accesible
-      b.foo4(null, null); //error - A (inferred in 15.12.2.8 - no resolution backtrack) not accesible
-      b.foo4(new B(), new C()); //ok - A (inferred in 15.12.2.7) not accessible, but foo4(Object...) applicable
+    {
+        B b = new B();
+        b.foo1(new B(), new B()); //error - A not accessible
+        /*   7  : ok - A not accessible, but foo2(Object...) applicable
+         *   8+ : error - A not accessible
+         */
+        b.foo2(new B(), new B());
+        b.foo3(null, null); //error - A (inferred) not accessible
+        b.foo4(null, null); //error - A not accesible
+        /*   7  : ok - A not accessible, but foo4(Object...) applicable
+         *   8+ : error - A not accessible
+         */
+        b.foo4(new B(), new C());
     }
 }
diff --git a/langtools/test/tools/javac/varargs/6313164/T6313164.out b/langtools/test/tools/javac/varargs/6313164/T6313164.out
deleted file mode 100644
index 7b2de27..0000000
--- a/langtools/test/tools/javac/varargs/6313164/T6313164.out
+++ /dev/null
@@ -1,6 +0,0 @@
-T6313164.java:12:8: compiler.err.cant.apply.symbol: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
-T6313164.java:14:13: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
-T6313164.java:15:13: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
-- compiler.note.unchecked.filename: B.java
-- compiler.note.unchecked.recompile
-3 errors
diff --git a/langtools/test/tools/javac/varargs/6313164/T6313164Source7.out b/langtools/test/tools/javac/varargs/6313164/T6313164Source7.out
new file mode 100644
index 0000000..8c12e72
--- /dev/null
+++ b/langtools/test/tools/javac/varargs/6313164/T6313164Source7.out
@@ -0,0 +1,6 @@
+- compiler.warn.source.no.bootclasspath: 1.7
+T6313164.java:14:10: compiler.err.cant.apply.symbol: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:19:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:20:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+3 errors
+1 warning
diff --git a/langtools/test/tools/javac/varargs/6313164/T6313164Source8AndHigher.out b/langtools/test/tools/javac/varargs/6313164/T6313164Source8AndHigher.out
new file mode 100644
index 0000000..0257a5d
--- /dev/null
+++ b/langtools/test/tools/javac/varargs/6313164/T6313164Source8AndHigher.out
@@ -0,0 +1,6 @@
+T6313164.java:14:15: compiler.err.cant.apply.symbol: kindname.method, foo1, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:18:15: compiler.err.cant.apply.symbol: kindname.method, foo2, p1.A[], p1.B,p1.B, kindname.class, p1.B, (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:19:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:20:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+T6313164.java:24:15: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: p1.A, kindname.class, T6313164)
+5 errors
diff --git a/langtools/test/tools/javac/varargs/6313164/T7175433.java b/langtools/test/tools/javac/varargs/6313164/T7175433.java
index b4627eb..4384cf5 100644
--- a/langtools/test/tools/javac/varargs/6313164/T7175433.java
+++ b/langtools/test/tools/javac/varargs/6313164/T7175433.java
@@ -1,31 +1,8 @@
 /*
- * Copyright (c) 2012, 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.
- */
-
-/*
- * @test
+ * @test /nodynamiccopyright/
  * @bug 7175433 6313164
  * @summary Inference cleanup: add helper class to handle inference variables
- *
+ * @compile/fail/ref=T7175433.out -XDrawDiagnostics T7175433.java
  */
 
 import java.util.List;
@@ -34,26 +11,16 @@
 
     private class Foo { }
 
-    <Z> List<Z> m(Object... o) { T7175433.assertTrue(true); return null; }
-    <Z> List<Z> m(Foo... o) { T7175433.assertTrue(false); return null; }
+    <Z> List<Z> m(Object... o) { return null; }
+    <Z> List<Z> m(Foo... o) { return null; }
 
     Foo getFoo() { return null; }
 }
 
 public class T7175433 {
 
-    static int assertionCount;
-
-    static void assertTrue(boolean b) {
-        assertionCount++;
-        if (!b) {
-            throw new AssertionError();
-        }
-    }
-
     public static void main(String[] args) {
         Bar b = new Bar();
         b.m(b.getFoo());
-        assertTrue(assertionCount == 1);
     }
 }
diff --git a/langtools/test/tools/javac/varargs/6313164/T7175433.out b/langtools/test/tools/javac/varargs/6313164/T7175433.out
new file mode 100644
index 0000000..598f3bb
--- /dev/null
+++ b/langtools/test/tools/javac/varargs/6313164/T7175433.out
@@ -0,0 +1,2 @@
+T7175433.java:24:12: compiler.err.prob.found.req: (compiler.misc.inaccessible.varargs.type: Bar.Foo, kindname.class, T7175433)
+1 error
diff --git a/langtools/test/tools/javac/varargs/6313164/p1/B.java b/langtools/test/tools/javac/varargs/6313164/p1/B.java
index 38ec371..ebe7ba9 100644
--- a/langtools/test/tools/javac/varargs/6313164/p1/B.java
+++ b/langtools/test/tools/javac/varargs/6313164/p1/B.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 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
@@ -23,13 +23,12 @@
 
 package p1;
 
+@SuppressWarnings("unchecked")
 public class B extends A {
-    public B() {}
     public void foo1(A... args) { }
     public void foo2(A... args) { }
     public void foo2(Object... args) { }
     public <X extends A> void foo3(X... args) { }
     public <X extends A> void foo4(X... args) { }
     public void foo4(Object... args) { }
-
 }
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/varargs/T8049075/VarargsAndWildcardParameterizedTypeTest.java
similarity index 67%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/varargs/T8049075/VarargsAndWildcardParameterizedTypeTest.java
index e2824dd..c961876 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/varargs/T8049075/VarargsAndWildcardParameterizedTypeTest.java
@@ -1,48 +1,40 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
-/**
+/*
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8049075
+ * @summary javac, wildcards and generic vararg method invocation not accepted
+ * @compile VarargsAndWildcardParameterizedTypeTest.java
  */
 
-load(__DIR__ + "maputil.js");
+class VarargsAndWildcardParameterizedTypeTest {
+    interface I<T> {
+        String m(T... t);
+    }
 
-function Foo() {
-    this.x = 33;
+    void m() {
+        I<? super Integer> i = null;
+        i.m(Integer.valueOf(1), Integer.valueOf(1));
+    }
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/langtools/test/tools/javac/warnings/suppress/Overridden.java b/langtools/test/tools/javac/warnings/suppress/Overridden.java
new file mode 100644
index 0000000..8366e39
--- /dev/null
+++ b/langtools/test/tools/javac/warnings/suppress/Overridden.java
@@ -0,0 +1,16 @@
+/**
+ * @test /nodynamiccopyright/
+ * @bug 8033421
+ * @summary Check that \\@SuppressWarnings works properly when overriding deprecated method.
+ * @build VerifySuppressWarnings
+ * @compile/ref=Overridden.out -XDrawDiagnostics -Xlint:deprecation Overridden.java
+ * @run main VerifySuppressWarnings Overridden.java
+ */
+
+public class Overridden implements Interface {
+    public void test() { }
+}
+
+interface Interface {
+    @Deprecated void test();
+}
diff --git a/langtools/test/tools/javac/warnings/suppress/Overridden.out b/langtools/test/tools/javac/warnings/suppress/Overridden.out
new file mode 100644
index 0000000..a215218
--- /dev/null
+++ b/langtools/test/tools/javac/warnings/suppress/Overridden.out
@@ -0,0 +1,2 @@
+Overridden.java:11:17: compiler.warn.has.been.deprecated: test(), Interface
+1 warning
diff --git a/nashorn/test/script/maptests/property_delete.js b/langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java
similarity index 68%
copy from nashorn/test/script/maptests/property_delete.js
copy to langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java
index e2824dd..4d2e305 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/langtools/test/tools/javac/warnings/suppress/OverriddenSuppressed.java
@@ -1,21 +1,21 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
@@ -23,26 +23,16 @@
 
 /**
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @bug 8033421
+ * @summary Check that \\@SuppressWarnings works properly when overriding deprecated method.
+ * @compile -Werror -Xlint:deprecation OverriddenSuppressed.java
  */
 
-load(__DIR__ + "maputil.js");
-
-function Foo() {
-    this.x = 33;
+public class OverriddenSuppressed implements Interface {
+    @SuppressWarnings("deprecation")
+    public void test() { }
 }
 
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
+interface Interface {
+    @Deprecated void test();
 }
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/langtools/test/tools/jdeps/APIDeps.java b/langtools/test/tools/jdeps/APIDeps.java
index 0e0e59d..c3d2c99 100644
--- a/langtools/test/tools/jdeps/APIDeps.java
+++ b/langtools/test/tools/jdeps/APIDeps.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8015912 8029216
+ * @bug 8015912 8029216 8048063 8050804
  * @summary Test -apionly and -jdkinternals options
  * @build m.Bar m.Foo m.Gee b.B c.C c.I d.D e.E f.F g.G
  * @run main APIDeps
@@ -81,27 +81,39 @@
              new String[] {"compact1", "compact3", testDirBasename},
              new String[] {"-classpath", testDir.getPath(), "-verbose", "-P"});
         test(new File(mDir, "Foo.class"),
+             new String[] {"c.I", "e.E", "f.F"},
+             new String[] {testDirBasename},
+             new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-P"});
+        test(new File(mDir, "Foo.class"),
              new String[] {"c.I", "e.E", "f.F", "m.Bar"},
              new String[] {testDirBasename},
-             new String[] {"-classpath", testDir.getPath(), "-verbose", "-P"});
+             new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-filter:none", "-P"});
         test(new File(mDir, "Gee.class"),
-             new String[] {"g.G", "sun.misc.Lock"},
-             new String[] {testDirBasename, "JDK internal API"},
-             new String[] {"-classpath", testDir.getPath(), "-verbose"});
+             new String[] {"g.G", "sun.misc.Lock", "com.sun.tools.classfile.ClassFile",
+                           "com.sun.management.ThreadMXBean", "com.sun.source.tree.BinaryTree"},
+             new String[] {testDirBasename, "JDK internal API", "compact3", ""},
+             new String[] {"-classpath", testDir.getPath(), "-verbose", "-P"});
 
         // -jdkinternals
         test(new File(mDir, "Gee.class"),
-             new String[] {"sun.misc.Lock"},
+             new String[] {"sun.misc.Lock", "com.sun.tools.classfile.ClassFile"},
              new String[] {"JDK internal API"},
              new String[] {"-jdkinternals"});
         // -jdkinternals parses all classes on -classpath and the input arguments
         test(new File(mDir, "Gee.class"),
-             new String[] {"sun.misc.Lock", "sun.misc.Unsafe"},
+             new String[] {"com.sun.tools.jdeps.Main", "com.sun.tools.classfile.ClassFile",
+                           "sun.misc.Lock", "sun.misc.Unsafe"},
              new String[] {"JDK internal API"},
              new String[] {"-classpath", testDir.getPath(), "-jdkinternals"});
 
         // parse only APIs
-        // parse only APIs
+        test(mDir,
+             new String[] {"java.lang.Object", "java.lang.String",
+                           "java.util.Set",
+                           "c.C", "d.D", "c.I", "e.E"},
+             new String[] {"compact1", testDirBasename},
+             new String[] {"-classpath", testDir.getPath(), "-verbose:class", "-P", "-apionly"});
+
         test(mDir,
              new String[] {"java.lang.Object", "java.lang.String",
                            "java.util.Set",
diff --git a/langtools/test/tools/jdeps/Basic.java b/langtools/test/tools/jdeps/Basic.java
index 34999aa..046a047 100644
--- a/langtools/test/tools/jdeps/Basic.java
+++ b/langtools/test/tools/jdeps/Basic.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, 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
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug 8003562 8005428 8015912 8027481
+ * @bug 8003562 8005428 8015912 8027481 8048063
  * @summary Basic tests for jdeps tool
  * @build Test p.Foo p.Bar javax.activity.NotCompactProfile
  * @run main Basic
@@ -86,6 +86,16 @@
              new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
              new String[] {"compact1", "compact1", "not found", "not found"},
              new String[] {"-verbose:class"});
+        // test -filter:none option
+        test(new File(testDir, "p"),
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"},
+             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"},
+             new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"});
+        // test -filter:archive option
+        test(new File(testDir, "p"),
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"});
         // test -p option
         test(new File(testDir, "Test.class"),
              new String[] {"p.Foo", "p.Bar"},
@@ -100,11 +110,12 @@
              new String[] {"java.lang"},
              new String[] {"compact1"},
              new String[] {"-verbose:package", "-e", "java\\.lang\\..*"});
+
         // test -classpath and -include options
         test(null,
-             new String[] {"java.lang", "java.util",
-                           "java.lang.management", "javax.crypto"},
-             new String[] {"compact1", "compact1", "compact3", "compact1"},
+             new String[] {"java.lang", "java.util", "java.lang.management",
+                           "javax.activity", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
              new String[] {"-classpath", testDir.getPath(), "-include", "p.+|Test.class"});
         test(new File(testDir, "Test.class"),
              new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
diff --git a/langtools/test/tools/jdeps/DotFileTest.java b/langtools/test/tools/jdeps/DotFileTest.java
new file mode 100644
index 0000000..63e283f
--- /dev/null
+++ b/langtools/test/tools/jdeps/DotFileTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/*
+ * @test
+ * @bug 8003562
+ * @summary Basic tests for jdeps -dotoutput option
+ * @build Test p.Foo p.Bar javax.activity.NotCompactProfile
+ * @run main DotFileTest
+ */
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.*;
+import java.util.regex.*;
+
+public class DotFileTest {
+    private static boolean symbolFileExist = initProfiles();
+    private static boolean initProfiles() {
+        // check if ct.sym exists; if not use the profiles.properties file
+        Path home = Paths.get(System.getProperty("java.home"));
+        if (home.endsWith("jre")) {
+            home = home.getParent();
+        }
+        Path ctsym = home.resolve("lib").resolve("ct.sym");
+        boolean symbolExists = ctsym.toFile().exists();
+        if (!symbolExists) {
+            Path testSrcProfiles =
+                Paths.get(System.getProperty("test.src", "."), "profiles.properties");
+            if (!testSrcProfiles.toFile().exists())
+                throw new Error(testSrcProfiles + " does not exist");
+            System.out.format("%s doesn't exist.%nUse %s to initialize profiles info%n",
+                ctsym, testSrcProfiles);
+            System.setProperty("jdeps.profiles", testSrcProfiles.toString());
+        }
+        return symbolExists;
+    }
+
+    public static void main(String... args) throws Exception {
+        int errors = 0;
+        errors += new DotFileTest().run();
+        if (errors > 0)
+            throw new Exception(errors + " errors found");
+    }
+
+    final Path dir;
+    final Path dotoutput;
+    DotFileTest() {
+        this.dir = Paths.get(System.getProperty("test.classes", "."));
+        this.dotoutput = dir.resolve("dots");
+    }
+
+    int run() throws IOException {
+        File testDir = dir.toFile();
+        // test a .class file
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang", "p"},
+             new String[] {"compact1", "not found"});
+        // test a directory
+        // also test non-SE javax.activity class dependency
+        test(new File(testDir, "p"),
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"-classpath", testDir.getPath()});
+        // test class-level dependency output
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
+             new String[] {"compact1", "compact1", "not found", "not found"},
+             new String[] {"-verbose:class"});
+        // test -filter:none option
+        test(new File(testDir, "p"),
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto", "p"},
+             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1", "p"},
+             new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:none"});
+        // test -filter:archive option
+        test(new File(testDir, "p"),
+             new String[] {"java.lang", "java.util", "java.lang.management", "javax.activity", "javax.crypto"},
+             new String[] {"compact1", "compact1", "compact3", testDir.getName(), "compact1"},
+             new String[] {"-classpath", testDir.getPath(), "-verbose:package", "-filter:archive"});
+        // test -p option
+        test(new File(testDir, "Test.class"),
+             new String[] {"p.Foo", "p.Bar"},
+             new String[] {"not found", "not found"},
+             new String[] {"-verbose:class", "-p", "p"});
+        // test -e option
+        test(new File(testDir, "Test.class"),
+             new String[] {"p.Foo", "p.Bar"},
+             new String[] {"not found", "not found"},
+             new String[] {"-verbose:class", "-e", "p\\..*"});
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang"},
+             new String[] {"compact1"},
+             new String[] {"-verbose:package", "-e", "java\\.lang\\..*"});
+        // test -classpath options
+        test(new File(testDir, "Test.class"),
+             new String[] {"java.lang.Object", "java.lang.String", "p.Foo", "p.Bar"},
+             new String[] {"compact1", "compact1", testDir.getName(), testDir.getName()},
+             new String[] {"-v", "-classpath", testDir.getPath()});
+
+        testSummary(new File(testDir, "Test.class"),
+             new String[] {"rt.jar", testDir.getName()},
+             new String[] {"compact1", ""},
+             new String[] {"-classpath", testDir.getPath()});
+        testSummary(new File(testDir, "Test.class"),
+             new String[] {"java.lang", "p"},
+             new String[] {"compact1", testDir.getName()},
+             new String[] {"-v", "-classpath", testDir.getPath()});
+        return errors;
+    }
+
+    void test(File file, String[] expect, String[] profiles) throws IOException {
+        test(file, expect, profiles, new String[0]);
+    }
+
+    void test(File file, String[] expect, String[] profiles, String[] options)
+        throws IOException
+    {
+        Path dotfile = dotoutput.resolve(file.toPath().getFileName().toString() + ".dot");
+
+        List<String> args = new ArrayList<>(Arrays.asList(options));
+        args.add("-dotoutput");
+        args.add(dotoutput.toString());
+        if (file != null) {
+            args.add(file.getPath());
+        }
+
+        Map<String,String> result = jdeps(args, dotfile);
+        checkResult("dependencies", expect, result.keySet());
+
+        // with -P option
+        List<String> argsWithDashP = new ArrayList<>();
+        argsWithDashP.add("-dotoutput");
+        argsWithDashP.add(dotoutput.toString());
+        argsWithDashP.add("-P");
+        argsWithDashP.addAll(args);
+
+        result = jdeps(argsWithDashP, dotfile);
+        checkResult("profiles", expect, profiles, result);
+    }
+
+    void testSummary(File file, String[] expect, String[] profiles, String[] options)
+        throws IOException
+    {
+        Path dotfile = dotoutput.resolve("summary.dot");
+
+        List<String> args = new ArrayList<>(Arrays.asList(options));
+        args.add("-dotoutput");
+        args.add(dotoutput.toString());
+        if (file != null) {
+            args.add(file.getPath());
+        }
+
+        Map<String,String> result = jdeps(args, dotfile);
+        checkResult("dependencies", expect, result.keySet());
+
+        // with -P option
+        List<String> argsWithDashP = new ArrayList<>();
+        argsWithDashP.add("-dotoutput");
+        argsWithDashP.add(dotoutput.toString());
+        argsWithDashP.add("-P");
+        argsWithDashP.addAll(args);
+
+        result = jdeps(argsWithDashP, dotfile);
+        checkResult("profiles", expect, profiles, result);
+    }
+
+    Map<String,String> jdeps(List<String> args, Path dotfile) throws IOException {
+        if (Files.exists(dotoutput)) {
+            try (DirectoryStream<Path> stream = Files.newDirectoryStream(dotoutput)) {
+                for (Path p : stream) {
+                    Files.delete(p);
+                }
+            }
+            Files.delete(dotoutput);
+        }
+        // invoke jdeps
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        System.err.println("jdeps " + args);
+        int rc = com.sun.tools.jdeps.Main.run(args.toArray(new String[0]), pw);
+        pw.close();
+        String out = sw.toString();
+        if (!out.isEmpty())
+            System.err.println(out);
+        if (rc != 0)
+            throw new Error("jdeps failed: rc=" + rc);
+
+        // check output files
+        if (Files.notExists(dotfile)) {
+            throw new RuntimeException(dotfile + " doesn't exist");
+        }
+        return parse(dotfile);
+    }
+    private static Pattern pattern = Pattern.compile("(.*) -> +([^ ]*) (.*)");
+    private Map<String,String> parse(Path outfile) throws IOException {
+        Map<String,String> result = new LinkedHashMap<>();
+        for (String line : Files.readAllLines(outfile)) {
+            line = line.replace('"', ' ').replace(';', ' ');
+            Matcher pm = pattern.matcher(line);
+            if (pm.find()) {
+                String origin = pm.group(1).trim();
+                String target = pm.group(2).trim();
+                String module = pm.group(3).replace('(', ' ').replace(')', ' ').trim();
+                result.put(target, module);
+            }
+        }
+        return result;
+    }
+
+    void checkResult(String label, String[] expect, Collection<String> found) {
+        List<String> list = Arrays.asList(expect);
+        if (!isEqual(list, found))
+            error("Unexpected " + label + " found: '" + found + "', expected: '" + list + "'");
+    }
+
+    void checkResult(String label, String[] expect, String[] profiles, Map<String,String> result) {
+        if (expect.length != profiles.length)
+            error("Invalid expected names and profiles");
+
+        // check the dependencies
+        checkResult(label, expect, result.keySet());
+        // check profile information
+        checkResult(label, profiles, result.values());
+        for (int i=0; i < expect.length; i++) {
+            String profile = result.get(expect[i]);
+            if (!profile.equals(profiles[i]))
+                error("Unexpected profile: '" + profile + "', expected: '" + profiles[i] + "'");
+        }
+    }
+
+    boolean isEqual(List<String> expected, Collection<String> found) {
+        if (expected.size() != found.size())
+            return false;
+
+        List<String> list = new ArrayList<>(found);
+        list.removeAll(expected);
+        return list.isEmpty();
+    }
+
+    void error(String msg) {
+        System.err.println("Error: " + msg);
+        errors++;
+    }
+
+    int errors;
+}
diff --git a/langtools/test/tools/jdeps/m/Gee.java b/langtools/test/tools/jdeps/m/Gee.java
index 749847e..0020b18 100644
--- a/langtools/test/tools/jdeps/m/Gee.java
+++ b/langtools/test/tools/jdeps/m/Gee.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -26,5 +26,7 @@
 
 class Gee extends g.G {
     public sun.misc.Lock lock;
+    public com.sun.tools.classfile.ClassFile cf;     // @jdk.Exported(false)
+    public com.sun.source.tree.BinaryTree tree;      // @jdk.Exported
+    public com.sun.management.ThreadMXBean mxbean;   // @jdk.Exported on package-info
 }
-
diff --git a/langtools/test/tools/jdeps/p/Bar.java b/langtools/test/tools/jdeps/p/Bar.java
index 9a99a76..77e20e6 100644
--- a/langtools/test/tools/jdeps/p/Bar.java
+++ b/langtools/test/tools/jdeps/p/Bar.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 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
@@ -30,4 +30,8 @@
     public javax.crypto.Cipher getCiper() {
         return null;
     }
+
+    public Foo foo() {
+        return new Foo();
+    }
 }
diff --git a/make/Jprt.gmk b/make/Jprt.gmk
index c40e852..c1ebee5 100644
--- a/make/Jprt.gmk
+++ b/make/Jprt.gmk
@@ -23,151 +23,7 @@
 # questions.
 #
 
-# This file is included by the root NewerMakefile and contains targets
-# and utilities needed by JPRT.
-
-# Utilities used in this Makefile. Most of this makefile executes without
-# the context of a spec file from configure.
-CAT=cat
-CMP=cmp
-CP=cp
-ECHO=echo
-MKDIR=mkdir
-PRINTF=printf
-PWD=pwd
-# Insure we have a path that looks like it came from pwd
-# (This is mostly for Windows sake and drive letters)
-define UnixPath # path
-$(shell (cd "$1" && $(PWD)))
-endef
-
-BUILD_DIR_ROOT:=$(root_dir)/build
-
-ifdef OPENJDK
-  OPEN_BUILD=true
-else
-  OPEN_BUILD := $(if $(or $(wildcard $(root_dir)/jdk/src/closed), \
-      $(wildcard $(root_dir)/jdk/make/closed), \
-      $(wildcard $(root_dir)/jdk/test/closed), \
-      $(wildcard $(root_dir)/hotspot/src/closed), \
-      $(wildcard $(root_dir)/hotspot/make/closed), \
-      $(wildcard $(root_dir)/hotspot/test/closed)), \
-      false,true)
-endif
-
-HOTSPOT_AVAILABLE := $(if $(wildcard $(root_dir)/hotspot),true,false)
-
-###########################################################################
-# To help in adoption of the new configure&&make build process, a bridge
-# build will use the old settings to run configure and do the build.
-
-# Build with the configure bridge. After running configure, restart make
-# to parse the new spec file.
-BRIDGE_TARGETS := all
-# Add bootcycle-images target if legacy variable is set.
-ifeq ($(SKIP_BOOT_CYCLE),false)
-  BRIDGE_TARGETS += bootcycle-images
-endif
-bridgeBuild: bridge2configure
-	@cd $(root_dir) && $(MAKE) -f Makefile $(BRIDGE_TARGETS)
-
-# Bridge from old Makefile ALT settings to configure options
-bridge2configure: $(BUILD_DIR_ROOT)/.bridge2configureOpts
-	bash ./configure $(strip $(shell $(CAT) $<))
-
-# Create a file with configure options created from old Makefile mechanisms.
-$(BUILD_DIR_ROOT)/.bridge2configureOpts: $(BUILD_DIR_ROOT)/.bridge2configureOptsLatest
-	$(RM) $@
-	$(CP) $< $@
-
-# Use this file to only change when obvious things have changed
-$(BUILD_DIR_ROOT)/.bridge2configureOptsLatest: FRC
-	$(RM) $@.tmp
-	$(MKDIR) -p $(BUILD_DIR_ROOT)
-	@$(ECHO) " --with-debug-level=$(if $(DEBUG_LEVEL),$(DEBUG_LEVEL),release) " >> $@.tmp
-        ifdef ARCH_DATA_MODEL
-	  @$(ECHO) " --with-target-bits=$(ARCH_DATA_MODEL) " >> $@.tmp
-        endif
-        ifeq ($(ARCH_DATA_MODEL),32)
-	  @$(ECHO) " --with-jvm-variants=client,server " >> $@.tmp
-        endif
-        ifdef ALT_PARALLEL_COMPILE_JOBS
-	  @$(ECHO) " --with-num-cores=$(ALT_PARALLEL_COMPILE_JOBS) " >> $@.tmp
-        endif
-        ifdef ALT_BOOTDIR
-	  @$(ECHO) " --with-boot-jdk=$(call UnixPath,$(ALT_BOOTDIR)) " >> $@.tmp
-        endif
-        ifdef ALT_CUPS_HEADERS_PATH
-	  @$(ECHO) " --with-cups-include=$(call UnixPath,$(ALT_CUPS_HEADERS_PATH)) " >> $@.tmp
-        endif
-        ifdef ALT_FREETYPE_HEADERS_PATH
-	  @$(ECHO) " --with-freetype=$(call UnixPath,$(ALT_FREETYPE_HEADERS_PATH)/..) " >> $@.tmp
-        endif
-        ifdef ENABLE_SJAVAC
-	  @$(ECHO) " --enable-sjavac" >> $@.tmp
-        endif
-        ifdef JDK_UPDATE_VERSION
-	  @$(ECHO) " --with-update-version=$(JDK_UPDATE_VERSION)" >> $@.tmp
-        endif
-        ifeq ($(HOTSPOT_AVAILABLE),false)
-          ifdef ALT_JDK_IMPORT_PATH
-	    @$(ECHO) " --with-import-hotspot=$(call UnixPath,$(ALT_JDK_IMPORT_PATH)) " >> $@.tmp
-          endif
-        endif
-        ifeq ($(OPEN_BUILD),true)
-	  @$(ECHO) " --enable-openjdk-only " >> $@.tmp
-        else
-#         Todo: move to closed?
-          ifdef ALT_MOZILLA_HEADERS_PATH
-	    @$(ECHO) " --with-mozilla-headers=$(call UnixPath,$(ALT_MOZILLA_HEADERS_PATH)) " >> $@.tmp
-          endif
-          ifdef ALT_JUNIT_DIR
-	    @$(ECHO) " --with-junit-dir=$(call UnixPath,$(ALT_JUNIT_DIR)) " >> $@.tmp
-          endif
-          ifdef ANT_HOME
-	    @$(ECHO) " --with-ant-home=$(call UnixPath,$(ANT_HOME)) " >> $@.tmp
-          endif
-          ifdef ALT_JAVAFX_ZIP_DIR
-	    @$(ECHO) " --with-javafx-zip-dir=$(call UnixPath,$(ALT_JAVAFX_ZIP_DIR)) " >> $@.tmp
-          endif
-          ifdef ALT_JMC_ZIP_DIR
-	    @$(ECHO) " --with-jmc-zip-dir=$(call UnixPath,$(ALT_JMC_ZIP_DIR)) " >> $@.tmp
-          endif
-          ifdef ALT_WIXDIR
-	    @$(ECHO) " --with-wix=$(call UnixPath,$(ALT_WIXDIR)) " >> $@.tmp
-          endif
-          ifdef ALT_INSTALL_LZMA_PATH
-	    @$(ECHO) " --with-lzma-path=$(call UnixPath,$(ALT_INSTALL_LZMA_PATH)) " >> $@.tmp
-          endif
-          ifdef ALT_INSTALL_UPX_PATH
-	    @$(ECHO) " --with-upx-path=$(call UnixPath,$(ALT_INSTALL_UPX_PATH)) " >> $@.tmp
-          endif
-          ifdef ALT_INSTALL_UPX_FILENAME
-	    @$(ECHO) " --with-upx-filename=$(call UnixPath,$(ALT_INSTALL_UPX_FILENAME)) " >> $@.tmp
-          endif
-          ifdef ALT_CCSS_SIGNING_DIR
-	    @$(ECHO) " --with-ccss-signing=$(call UnixPath,$(ALT_CCSS_SIGNING_DIR)) " >> $@.tmp
-          endif
-          ifdef ALT_SLASH_JAVA
-	    @$(ECHO) " --with-java-devtools=$(call UnixPath,$(ALT_SLASH_JAVA)/devtools) " >> $@.tmp
-          endif
-          ifdef ALT_SPARKLE_FRAMEWORK_DIR
-	    @$(ECHO) " --with-sparkle-framework=$(call UnixPath,$(ALT_SPARKLE_FRAMEWORK_DIR)) " >> $@.tmp
-          endif
-        endif
-	@if [ -f $@ ] ; then \
-	  if ! $(CMP) $@ $@.tmp > /dev/null ; then \
-	    $(CP) $@.tmp $@ ; \
-	  fi ; \
-	else \
-	  $(CP) $@.tmp $@ ; \
-	fi
-	$(RM) $@.tmp
-
-PHONY_LIST += bridge2configure bridgeBuild
-
-###########################################################################
-# JPRT targets
+# This file is contains targets utilities needed by JPRT.
 
 ifndef JPRT_ARCHIVE_BUNDLE
   JPRT_ARCHIVE_BUNDLE=/tmp/jprt_bundles/j2sdk-image.zip
@@ -176,22 +32,9 @@
   JPRT_ARCHIVE_INSTALL_BUNDLE=/tmp/jprt_bundles/product-install.zip
 endif
 
-# These targets execute in a SPEC free context, before calling bridgeBuild
-# to generate the SPEC.
-jprt_build_product: DEBUG_LEVEL=release
-jprt_build_product: BUILD_DIRNAME=*-release
-jprt_build_product: jprt_build_generic
-
-jprt_build_fastdebug: DEBUG_LEVEL=fastdebug
-jprt_build_fastdebug: BUILD_DIRNAME=*-fastdebug
-jprt_build_fastdebug: jprt_build_generic
-
-jprt_build_debug: DEBUG_LEVEL=slowdebug
-jprt_build_debug: BUILD_DIRNAME=*-debug
-jprt_build_debug: jprt_build_generic
-
-jprt_build_generic: BRIDGE_TARGETS+=jprt_bundle
-jprt_build_generic: bridgeBuild
+ifeq ($(SKIP_BOOT_CYCLE), false)
+  jprt_bundle: bootcycle-images
+endif
 
 # This target must be called in the context of a SPEC file
 jprt_bundle: $(JPRT_ARCHIVE_BUNDLE)
@@ -238,14 +81,6 @@
 	@$(call TargetExit)
 
 
-# Keep track of phony targets
-PHONY_LIST += jprt_build_product jprt_build_fastdebug jprt_build_debug \
-    jprt_build_generic bundles jprt_bundle \
-    final-images final-images-only
-
 ###########################################################################
 # Phony targets
-.PHONY: $(PHONY_LIST)
-
-# Force target
-FRC:
+.PHONY: jprt_bundle bundles bundles-only final-images final-images-only
diff --git a/make/Main.gmk b/make/Main.gmk
index 2988f78..acb4faa 100644
--- a/make/Main.gmk
+++ b/make/Main.gmk
@@ -242,4 +242,6 @@
 .PHONY: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-nashorn clean-images clean-docs clean-test clean-overlay-images clean-bootcycle-build
 .PHONY: profiles profiles-only profiles-oscheck
 
+include $(root_dir)/make/Jprt.gmk
+
 FRC: # Force target
diff --git a/make/MakeHelpers.gmk b/make/MakeHelpers.gmk
index 66f4ca4..c999535 100644
--- a/make/MakeHelpers.gmk
+++ b/make/MakeHelpers.gmk
@@ -50,7 +50,7 @@
 
 # Global targets are possible to run either with or without a SPEC. The prototypical
 # global target is "help".
-global_targets=help jprt% bridgeBuild bridge2configure
+global_targets=help
 
 ##############################
 # Functions
diff --git a/make/common/NON_CORE_PKGS.gmk b/make/common/NON_CORE_PKGS.gmk
index 7cd7d50..f171e7c 100644
--- a/make/common/NON_CORE_PKGS.gmk
+++ b/make/common/NON_CORE_PKGS.gmk
@@ -95,7 +95,8 @@
 endif
 
 JDK_PKGS = jdk \
-     jdk.net
+     jdk.net \
+     jdk.management.cmm
 
 # non-core packages in rt.jar
 NON_CORE_PKGS = $(DOMAPI_PKGS) \
diff --git a/make/jprt.properties b/make/jprt.properties
index ae20e82..d15b2a8 100644
--- a/make/jprt.properties
+++ b/make/jprt.properties
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2006, 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
@@ -23,131 +23,461 @@
 # questions.
 #
 
-# Properties for jprt
+##############
+#
+# Global settings
+#
 
-# Locked down to jdk8
-jprt.tools.default.release=jdk8
+# The current release name
+my.jdk.update.version=40
+jprt.tools.default.release=jdk8u${my.jdk.update.version}
 
-# Unix toolkit to use for building on windows
-jprt.windows.jdk8.build.unix.toolkit=cygwin
+# Check if this is the equivalent of a hotspot push job
+# Interpret -testset hotspot to mean exactly that
+my.is.hotspot.job.hotspot=true
+my.is.hotspot.job=${my.is.hotspot.job.${jprt.test.set}}
 
-# The different build flavors we want, we override here so we just get these 2
-jprt.build.flavors=product,fastdebug
-
-# Standard list of jprt build targets for this source tree
-jprt.build.targets= 						\
-    solaris_sparcv9_5.10-{product|fastdebug}, 			\
-    solaris_x64_5.10-{product|fastdebug}, 			\
-    linux_i586_2.6-{product|fastdebug}, 			\
-    linux_x64_2.6-{product|fastdebug}, 				\
-    macosx_x64_10.7-{product|fastdebug}, 			\
-    windows_i586_6.1-{product|fastdebug}, 			\
-    windows_x64_6.1-{product|fastdebug}
-
-# User can select the test set with jprt submit "-testset name" option
-jprt.my.test.set=${jprt.test.set}
-
-# Test target list (no fastdebug & limited c2 testing)
-jprt.my.test.target.set= \
-    solaris_sparcv9_5.10-product-c2-TESTNAME, 			\
-    solaris_x64_5.10-product-c2-TESTNAME, 			\
-    linux_i586_2.6-product-{c1|c2}-TESTNAME, 			\
-    linux_x64_2.6-product-c2-TESTNAME, 				\
-    macosx_x64_10.7-product-c2-TESTNAME, 			\
-    windows_i586_6.1-product-c1-TESTNAME, 			\
-    windows_x64_6.1-product-c2-TESTNAME
-
-# Default vm test targets (testset=default)
-jprt.vm.default.test.targets=              			\
-    ${jprt.my.test.target.set:TESTNAME=jvm98},			\
-    ${jprt.my.test.target.set:TESTNAME=scimark}
-
-# Default jdk test targets (testset=default)
-jprt.make.rule.default.test.targets=				\
-    ${jprt.my.test.target.set:TESTNAME=langtools_jtreg},        \
-    ${jprt.my.test.target.set:TESTNAME=jdk_lang},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_math},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_util}
-    
-
-# Default vm test targets (testset=core)
-jprt.vm.core.test.targets=
-
-# Core jdk test targets (testset=core)
-jprt.make.rule.core.test.targets=                               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_lang},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_math},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_util},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_io},			\
-    ${jprt.my.test.target.set:TESTNAME=jdk_net},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_nio},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_security1},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_security2},          \
-    ${jprt.my.test.target.set:TESTNAME=jdk_security3},          \
-    ${jprt.my.test.target.set:TESTNAME=jdk_rmi},                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_text},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_time},               \
-    ${jprt.my.test.target.set:TESTNAME=jdk_other},              \
-    ${jprt.my.test.target.set:TESTNAME=core_tools}
-
-# Svc vm test targets (testset=svc)
-jprt.vm.svc.test.targets=
-
-# Core jdk test targets (testset=svc)
-jprt.make.rule.svc.test.targets=                                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_management},         \
-    ${jprt.my.test.target.set:TESTNAME=jdk_instrument},         \
-    ${jprt.my.test.target.set:TESTNAME=jdk_jmx},                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_jdi},                \
-    ${jprt.my.test.target.set:TESTNAME=jdk_jfr},                \
-    ${jprt.my.test.target.set:TESTNAME=svc_tools}
-
-# All vm test targets (testset=all)
-jprt.vm.all.test.targets=    					\
-    ${jprt.vm.default.test.targets}, 				\
-    ${jprt.my.test.target.set:TESTNAME=runThese},		\
-    ${jprt.my.test.target.set:TESTNAME=jbb_default}
-
-# All jdk test targets (testset=all)
-jprt.make.rule.all.test.targets=    				\
-    ${jprt.make.rule.core.test.targets}, 			\
-    ${jprt.make.rule.svc.test.targets},                         \
-    ${jprt.my.test.target.set:TESTNAME=jdk_awt},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_beans1},             \
-    ${jprt.my.test.target.set:TESTNAME=jdk_beans2},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_beans3},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_sound},		\
-    ${jprt.my.test.target.set:TESTNAME=jdk_swing}
-
-# PIT vm test targets (testset=pit)
-jprt.vm.pit.test.targets=                                       \
-   ${jprt.vm.all.test.targets}
-
-# PIT jdk test targets (testset=pit)
-jprt.make.rule.pit.test.targets=                                \
-    ${jprt.my.test.target.set:TESTNAME=langtools_jtreg},        \
-    ${jprt.make.rule.core.test.targets},                        \
-    ${jprt.make.rule.svc.test.targets}
-
-# JCK test targets in test/Makefile (no windows)
-jprt.my.jck.test.target.set=					\
-    solaris_sparcv9_5.10-product-c2-JCK7TESTRULE, 		\
-    solaris_x64_5.10-product-c2-JCK7TESTRULE, 			\
-    linux_i586_2.6-product-c1-JCK7TESTRULE, 			\
-    linux_x64_2.6-product-c2-JCK7TESTRULE
-
-# JCK testset targets (e.g. jprt submit -testset jck ... )
-jprt.make.rule.jck.test.targets=				\
-    ${jprt.my.jck.test.target.set:JCK7TESTRULE=jck7devtools},   \
-    ${jprt.my.jck.test.target.set:JCK7TESTRULE=jck7runtime},    \
-    ${jprt.my.jck.test.target.set:JCK7TESTRULE=jck7compiler}
-
-# Select list to use (allow for testset to be empty too)
-jprt.make.rule..test.targets=${jprt.make.rule.default.test.targets}
-jprt.make.rule.test.targets=${jprt.make.rule.${jprt.my.test.set}.test.targets}
-jprt.vm..test.targets=${jprt.vm.default.test.targets}
-jprt.test.targets=${jprt.vm.${jprt.my.test.set}.test.targets}
+# Disable syncing the source after builds and tests are done
+jprt.sync.push=${my.is.hotspot.job ? false : true}
 
 # Directories to be excluded from the source bundles
 jprt.bundle.exclude.src.dirs=build dist webrev
 
+# Use configure when building
+jprt.build.use.configure=true
+
+# Set make target to use for different build flavors
+jprt.build.flavor.debugOpen.target=jprt_bundle
+jprt.build.flavor.fastdebug.target=jprt_bundle
+jprt.build.flavor.product.target=jprt_bundle
+jprt.build.flavor.productOpen.target=jprt_bundle
+
+# Use these configure args to define debug level
+jprt.debug.build.configure.args=--with-debug-level=slowdebug
+jprt.fastdebug.build.configure.args=--with-debug-level=fastdebug
+jprt.product.build.configure.args=--with-debug-level=release
+jprt.debugOpen.build.configure.args=${jprt.debug.build.configure.args} --enable-openjdk-only
+jprt.fastdebugOpen.build.configure.args=${jprt.fastdebug.build.configure.args} --enable-openjdk-only
+jprt.productOpen.build.configure.args=${jprt.product.build.configure.args} --enable-openjdk-only
+
+# Select build flavors and build targets
+jprt.build.flavors=${my.is.hotspot.job ? ${my.build.flavors.hotspot} : ${my.build.flavors.default}}
+jprt.build.targets=${my.is.hotspot.job ? ${my.build.targets.hotspot} : ${my.build.targets.default}}
+
+# Select test targets - jprt default for jprt.test.set is "default"
+jprt.test.targets=${my.test.targets.${jprt.test.set}}
+jprt.make.rule.test.targets=${my.make.rule.test.targets.${jprt.test.set}}
+
+# 7155453: Work-around to prevent popups on OSX from blocking test completion
+# but the work-around is added to all platforms to be consistent
+jprt.jbb.options=-Djava.awt.headless=true
+
+########
+#
+# Build options (generic)
+#
+
+# Configure args common to all builds
+# Also allows for additional, testset specific configure arguments to be set
+jprt.build.configure.args=						\
+    --with-boot-jdk=$ALT_BOOTDIR					\
+    --with-jobs=$ALT_PARALLEL_COMPILE_JOBS				\
+    --with-update-version=${my.jdk.update.version}			\
+    ${my.additional.build.configure.args.${jprt.test.set}}
+
+# i586 is often cross-compiled from 64-bit machines, so need to set target bits explicitly
+jprt.i586.build.configure.args=						\
+    --with-target-bits=32
+
+# i586 platforms have both client and server, but to allow for overriding the exact configuration
+# on a per-build flavor basis the value is set for the individual build flavors
+# All other platforms only build server, which is the default setting from configure
+my.i586.default.build.configure.args=					\
+    --with-jvm-variants=client,server
+jprt.i586.debug.build.configure.args=					\
+    ${my.i586.default.build.configure.args}				\
+    ${jprt.debug.build.configure.args}
+jprt.i586.fastdebug.build.configure.args=				\
+    ${my.i586.default.build.configure.args}				\
+    ${jprt.fastdebug.build.configure.args}
+jprt.i586.product.build.configure.args=					\
+    ${my.i586.default.build.configure.args}				\
+    ${jprt.product.build.configure.args}
+jprt.i586.debugOpen.build.configure.args=				\
+    ${my.i586.default.build.configure.args}				\
+    ${jprt.debugOpen.build.configure.args}
+jprt.i586.fastdebugOpen.build.configure.args=				\
+    ${my.i586.default.build.configure.args}				\
+    ${jprt.fastdebugOpen.build.configure.args}
+jprt.i586.productOpen.build.configure.args=				\
+    ${my.i586.default.build.configure.args}				\
+    ${jprt.productOpen.build.configure.args}
+
+########
+#
+# Build targets and options (default/jdk)
+#
+
+# The default build flavors
+my.build.flavors.default=fastdebug,product
+
+# Standard list of jprt build targets for this source tree
+my.build.targets.default=						\
+    solaris_sparcv9_5.10-{product|fastdebug},				\
+    solaris_x64_5.10-{product|fastdebug},				\
+    linux_i586_2.6-{product|fastdebug},					\
+    linux_x64_2.6-{product|fastdebug},					\
+    macosx_x64_10.7-{product|fastdebug},				\
+    windows_i586_6.1-{product|fastdebug},				\
+    windows_x64_6.1-{product|fastdebug}
+
+# Test target list (no fastdebug & limited c2 testing)
+my.test.target.set=							\
+    solaris_sparcv9_5.10-product-c2-TESTNAME,				\
+    solaris_x64_5.10-product-c2-TESTNAME,				\
+    linux_i586_2.6-product-{c1|c2}-TESTNAME,				\
+    linux_x64_2.6-product-c2-TESTNAME,					\
+    macosx_x64_10.7-product-c2-TESTNAME,				\
+    windows_i586_6.1-product-c1-TESTNAME,				\
+    windows_x64_6.1-product-c2-TESTNAME
+
+# Default vm test targets (testset=default)
+my.test.targets.default=						\
+    ${my.test.target.set:TESTNAME=jvm98},				\
+    ${my.test.target.set:TESTNAME=scimark}
+
+# Default jdk test targets (testset=default)
+my.make.rule.test.targets.default=					\
+    ${my.test.target.set:TESTNAME=langtools_jtreg},			\
+    ${my.test.target.set:TESTNAME=jdk_lang},				\
+    ${my.test.target.set:TESTNAME=jdk_math},				\
+    ${my.test.target.set:TESTNAME=jdk_util}
+    
+# Default vm test targets (testset=core)
+my.test.targets.core=
+
+# Core jdk test targets (testset=core)
+my.make.rule.test.targets.core=						\
+    ${my.test.target.set:TESTNAME=jdk_lang},				\
+    ${my.test.target.set:TESTNAME=jdk_math},				\
+    ${my.test.target.set:TESTNAME=jdk_util},				\
+    ${my.test.target.set:TESTNAME=jdk_io},				\
+    ${my.test.target.set:TESTNAME=jdk_net},				\
+    ${my.test.target.set:TESTNAME=jdk_nio},				\
+    ${my.test.target.set:TESTNAME=jdk_security1},			\
+    ${my.test.target.set:TESTNAME=jdk_security2},			\
+    ${my.test.target.set:TESTNAME=jdk_security3},			\
+    ${my.test.target.set:TESTNAME=jdk_rmi},				\
+    ${my.test.target.set:TESTNAME=jdk_text},				\
+    ${my.test.target.set:TESTNAME=jdk_time},				\
+    ${my.test.target.set:TESTNAME=jdk_other},				\
+    ${my.test.target.set:TESTNAME=core_tools}
+
+# Svc vm test targets (testset=svc)
+my.test.targets.svc=
+
+# Core jdk test targets (testset=svc)
+my.make.rule.test.targets.svc=						\
+    ${my.test.target.set:TESTNAME=jdk_management},			\
+    ${my.test.target.set:TESTNAME=jdk_instrument},			\
+    ${my.test.target.set:TESTNAME=jdk_jmx},				\
+    ${my.test.target.set:TESTNAME=jdk_jdi},				\
+    ${my.test.target.set:TESTNAME=jdk_jfr},				\
+    ${my.test.target.set:TESTNAME=svc_tools}
+
+# All vm test targets (testset=all)
+my.test.targets.all=							\
+    ${my.test.targets.default},						\
+    ${my.test.target.set:TESTNAME=runThese},				\
+    ${my.test.target.set:TESTNAME=jbb_default}
+
+# All jdk test targets (testset=all)
+my.make.rule.test.targets.all=						\
+    ${my.make.rule.test.targets.core},					\
+    ${my.make.rule.test.targets.svc},					\
+    ${my.test.target.set:TESTNAME=jdk_awt},				\
+    ${my.test.target.set:TESTNAME=jdk_beans1},				\
+    ${my.test.target.set:TESTNAME=jdk_beans2},				\
+    ${my.test.target.set:TESTNAME=jdk_beans3},				\
+    ${my.test.target.set:TESTNAME=jdk_sound},				\
+    ${my.test.target.set:TESTNAME=jdk_swing}
+
+# PIT vm test targets (testset=pit)
+my.test.targets.pit=							\
+   ${my.test.targets.all}
+
+# PIT jdk test targets (testset=pit)
+my.make.rule.test.targets.pit=						\
+    ${my.test.target.set:TESTNAME=langtools_jtreg},			\
+    ${my.make.rule.test.targets.core},					\
+    ${my.make.rule.test.targets.svc}
+
+# JCK test targets in test/Makefile (no windows)
+my.test.target.set.jck=							\
+    solaris_sparcv9_5.10-product-c2-JCK7TESTRULE,			\
+    solaris_x64_5.10-product-c2-JCK7TESTRULE,				\
+    linux_i586_2.6-product-c1-JCK7TESTRULE,				\
+    linux_x64_2.6-product-c2-JCK7TESTRULE
+
+# JCK testset targets
+my.make.rule.test.targets.jck=						\
+    ${my.test.target.set.jck:JCK7TESTRULE=jck7devtools},		\
+    ${my.test.target.set.jck:JCK7TESTRULE=jck7runtime},			\
+    ${my.test.target.set.jck:JCK7TESTRULE=jck7compiler}
+
+
+#############
+#
+# Hotspot related settings (testset=hotspot)
+#
+
+# The hotspot build flavors
+my.build.flavors.hotspot=						\
+    debugOpen,fastdebug,product,productOpen,				\
+    ${my.additional.build.flavors.hotspot}
+
+# Platforms built for hotspot push jobs
+my.build.targets.hotspot=						\
+    solaris_sparcv9_5.10-{product|fastdebug|optimized},			\
+    solaris_x64_5.10-{product|fastdebug},				\
+    linux_i586_2.6-{product|fastdebug},					\
+    linux_x64_2.6-{product|fastdebug|optimized},			\
+    macosx_x64_10.7-{product|fastdebug},				\
+    windows_i586_6.1-{product|fastdebug},				\
+    windows_x64_6.1-{product|fastdebug|optimized},			\
+    solaris_x64_5.10-{debugOpen},					\
+    linux_x64_2.6-{productOpen},					\
+    ${my.additional.build.targets.hotspot}
+
+# Tests to run on the various platforms for hotspot push jobs
+my.test.targets.hotspot.solaris.sparcv9=				\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jvm98,			\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jvm98_nontiered,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-scimark,		\
+    solaris_sparcv9_5.10-product-c2-runThese,				\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_SerialGC,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParallelGC,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParNewGC,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_CMS,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_G1,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCBasher_ParOldGC,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_SerialGC,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_ParallelGC,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_ParNewGC,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_CMS,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_G1,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-GCOld_ParOldGC,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_default_nontiered,	\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_SerialGC,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_ParallelGC,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_CMS,		\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_G1,			\
+    solaris_sparcv9_5.10-{product|fastdebug}-c2-jbb_ParOldGC
+
+my.test.targets.hotspot.solaris.x64=					\
+    solaris_x64_5.10-{product|fastdebug}-c2-jvm98,			\
+    solaris_x64_5.10-{product|fastdebug}-c2-jvm98_nontiered,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-scimark,			\
+    solaris_x64_5.10-product-c2-runThese,				\
+    solaris_x64_5.10-product-c2-runThese_Xcomp,				\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCBasher_SerialGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCBasher_ParallelGC,	\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCBasher_ParNewGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCBasher_CMS,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCBasher_G1,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCBasher_ParOldGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_SerialGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_ParallelGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_ParNewGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_CMS,			\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_G1,			\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_ParOldGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-jbb_default_nontiered,	\
+    solaris_x64_5.10-{product|fastdebug}-c2-jbb_SerialGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-jbb_ParallelGC,		\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_CMS,			\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_G1,			\
+    solaris_x64_5.10-{product|fastdebug}-c2-GCOld_ParOldGC
+
+my.test.targets.hotspot.linux.i586=					\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-jvm98,			\
+    linux_i586_2.6-{product|fastdebug}-c2-jvm98_nontiered,		\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-scimark,			\
+    linux_i586_2.6-product-c1-runThese_Xcomp,				\
+    linux_i586_2.6-fastdebug-c1-runThese_Xshare,			\
+    linux_i586_2.6-fastdebug-c2-runThese_Xcomp,				\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC,	\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC,	\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC,	\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-GCBasher_CMS,		\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-GCBasher_G1,		\
+    linux_i586_2.6-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC,	\
+    linux_i586_2.6-product-{c1|c2}-GCOld_SerialGC,			\
+    linux_i586_2.6-product-{c1|c2}-GCOld_ParallelGC,			\
+    linux_i586_2.6-product-{c1|c2}-GCOld_ParNewGC,			\
+    linux_i586_2.6-product-{c1|c2}-GCOld_CMS,				\
+    linux_i586_2.6-product-{c1|c2}-GCOld_G1,				\
+    linux_i586_2.6-product-{c1|c2}-GCOld_ParOldGC,			\
+    linux_i586_2.6-{product|fastdebug}-c1-jbb_SerialGC,			\
+    linux_i586_2.6-{product|fastdebug}-c2-jbb_default_nontiered,	\
+    linux_i586_2.6-{product|fastdebug}-c1-jbb_ParallelGC,		\
+    linux_i586_2.6-{product|fastdebug}-c1-jbb_CMS,			\
+    linux_i586_2.6-{product|fastdebug}-c1-jbb_G1,			\
+    linux_i586_2.6-{product|fastdebug}-c1-jbb_ParOldGC
+
+my.test.targets.hotspot.linux.x64=					\
+    linux_x64_2.6-{product|fastdebug}-c2-jvm98,				\
+    linux_x64_2.6-{product|fastdebug}-c2-jvm98_nontiered,		\
+    linux_x64_2.6-{product|fastdebug}-c2-scimark,			\
+    linux_x64_2.6-{product|fastdebug}-c2-GCBasher_SerialGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCBasher_ParallelGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCBasher_ParNewGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCBasher_CMS,			\
+    linux_x64_2.6-{product|fastdebug}-c2-GCBasher_G1,			\
+    linux_x64_2.6-{product|fastdebug}-c2-GCBasher_ParOldGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCOld_SerialGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCOld_ParallelGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCOld_ParNewGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-GCOld_CMS,			\
+    linux_x64_2.6-{product|fastdebug}-c2-GCOld_G1,			\
+    linux_x64_2.6-{product|fastdebug}-c2-GCOld_ParOldGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-jbb_default_nontiered,		\
+    linux_x64_2.6-{product|fastdebug}-c2-jbb_ParallelGC,		\
+    linux_x64_2.6-{product|fastdebug}-c2-jbb_G1,			\
+    linux_x64_2.6-{product|fastdebug}-c2-jbb_ParOldGC
+
+my.test.targets.hotspot.macosx.x64=					\
+    macosx_x64_10.7-{product|fastdebug}-c2-jvm98,			\
+    macosx_x64_10.7-{product|fastdebug}-c2-jvm98_nontiered,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-scimark,			\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCBasher_SerialGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCBasher_ParallelGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCBasher_ParNewGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCBasher_CMS,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCBasher_G1,			\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCBasher_ParOldGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCOld_SerialGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCOld_ParallelGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCOld_ParNewGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCOld_CMS,			\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCOld_G1,			\
+    macosx_x64_10.7-{product|fastdebug}-c2-GCOld_ParOldGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-jbb_default_nontiered,	\
+    macosx_x64_10.7-{product|fastdebug}-c2-jbb_ParallelGC,		\
+    macosx_x64_10.7-{product|fastdebug}-c2-jbb_G1,			\
+    macosx_x64_10.7-{product|fastdebug}-c2-jbb_ParOldGC
+
+my.test.targets.hotspot.windows.i586=					\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-jvm98,			\
+    windows_i586_6.1-{product|fastdebug}-c2-jvm98_nontiered,		\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-scimark,		\
+    windows_i586_6.1-product-{c1|c2}-runThese,				\
+    windows_i586_6.1-product-{c1|c2}-runThese_Xcomp,			\
+    windows_i586_6.1-fastdebug-c1-runThese_Xshare,			\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_SerialGC,	\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_ParallelGC,	\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_ParNewGC,	\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_CMS,		\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_G1,		\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-GCBasher_ParOldGC,	\
+    windows_i586_6.1-product-{c1|c2}-GCOld_SerialGC,			\
+    windows_i586_6.1-product-{c1|c2}-GCOld_ParallelGC,			\
+    windows_i586_6.1-product-{c1|c2}-GCOld_ParNewGC,			\
+    windows_i586_6.1-product-{c1|c2}-GCOld_CMS,				\
+    windows_i586_6.1-product-{c1|c2}-GCOld_G1,				\
+    windows_i586_6.1-product-{c1|c2}-GCOld_ParOldGC,			\
+    windows_i586_6.1-{product|fastdebug}-{c1|c2}-jbb_default,		\
+    windows_i586_6.1-{product|fastdebug}-c2-jbb_default_nontiered,	\
+    windows_i586_6.1-product-{c1|c2}-jbb_ParallelGC,			\
+    windows_i586_6.1-product-{c1|c2}-jbb_CMS,				\
+    windows_i586_6.1-product-{c1|c2}-jbb_G1,				\
+    windows_i586_6.1-product-{c1|c2}-jbb_ParOldGC
+
+my.test.targets.hotspot.windows.x64=					\
+    windows_x64_6.1-{product|fastdebug}-c2-jvm98,			\
+    windows_x64_6.1-{product|fastdebug}-c2-jvm98_nontiered,		\
+    windows_x64_6.1-{product|fastdebug}-c2-scimark,			\
+    windows_x64_6.1-product-c2-runThese,				\
+    windows_x64_6.1-product-c2-runThese_Xcomp,				\
+    windows_x64_6.1-{product|fastdebug}-c2-GCBasher_SerialGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCBasher_ParallelGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCBasher_ParNewGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCBasher_CMS,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCBasher_G1,			\
+    windows_x64_6.1-{product|fastdebug}-c2-GCBasher_ParOldGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCOld_SerialGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCOld_ParallelGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCOld_ParNewGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-GCOld_CMS,			\
+    windows_x64_6.1-{product|fastdebug}-c2-GCOld_G1,			\
+    windows_x64_6.1-{product|fastdebug}-c2-GCOld_ParOldGC,		\
+    windows_x64_6.1-{product|fastdebug}-c2-jbb_default,			\
+    windows_x64_6.1-{product|fastdebug}-c2-jbb_default_nontiered,	\
+    windows_x64_6.1-product-c2-jbb_CMS,					\
+    windows_x64_6.1-product-c2-jbb_ParallelGC,				\
+    windows_x64_6.1-product-c2-jbb_G1,					\
+    windows_x64_6.1-product-c2-jbb_ParOldGC
+
+# Some basic "smoke" tests for OpenJDK builds
+my.test.targets.hotspot.open=						\
+    solaris_x64_5.10-{productOpen|fastdebugOpen}-c2-jvm98,		\
+    linux_x64_2.6-{productOpen|fastdebugOpen}-c2-jvm98
+
+# The complete list of test targets for jprt
+my.test.targets.hotspot=						\
+  ${my.test.targets.hotspot.open},					\
+  ${my.test.targets.hotspot.solaris.sparcv9},				\
+  ${my.test.targets.hotspot.solaris.x64},				\
+  ${my.test.targets.hotspot.linux.i586},				\
+  ${my.test.targets.hotspot.linux.x64},					\
+  ${my.test.targets.hotspot.macosx.x64},				\
+  ${my.test.targets.hotspot.windows.i586},				\
+  ${my.test.targets.hotspot.windows.x64},				\
+  ${my.test.targets.hotspot.solaris.sparcv9},				\
+  ${my.test.targets.hotspot.solaris.x64},				\
+  ${my.test.targets.hotspot.linux.x64},					\
+  ${my.test.targets.hotspot.windows.i586},				\
+  ${my.test.targets.hotspot.windows.x64},				\
+  ${my.additional.test.targets.hotspot}
+
+
+# Make file based test targets
+
+my.make.rule.test.targets.hotspot.clienttests=				\
+  linux_i586_2.6-*-c1-hotspot_clienttest,				\
+  windows_i586_6.1-*-c1-hotspot_clienttest
+
+my.make.rule.test.targets.hotspot.servertests=				\
+  solaris_sparcv9_5.10-*-c2-hotspot_servertest,				\
+  solaris_x64_5.10-*-c2-hotspot_servertest,				\
+  linux_i586_2.6-*-c2-hotspot_servertest,				\
+  linux_x64_2.6-*-c2-hotspot_servertest,				\
+  macosx_x64_10.7-*-c2-hotspot_servertest,				\
+  windows_i586_6.1-*-c2-hotspot_servertest,				\
+  windows_x64_6.1-*-c2-hotspot_servertest
+
+my.make.rule.test.targets.hotspot.internalvmtests=			\
+  solaris_sparcv9_5.10-fastdebug-c2-hotspot_internalvmtests,		\
+  solaris_x64_5.10-fastdebug-c2-hotspot_internalvmtests,		\
+  linux_i586_2.6-fastdebug-c2-hotspot_internalvmtests,			\
+  linux_x64_2.6-fastdebug-c2-hotspot_internalvmtests,			\
+  macosx_x64_10.7-fastdebug-c2-hotspot_internalvmtests,			\
+  windows_i586_6.1-fastdebug-c2-hotspot_internalvmtests,		\
+  windows_x64_6.1-fastdebug-c2-hotspot_internalvmtests
+
+my.make.rule.test.targets.hotspot.wbapitests=				\
+  solaris_sparcv9_5.10-{product|fastdebug}-c2-hotspot_wbapitest,	\
+  solaris_x64_5.10-{product|fastdebug}-c2-hotspot_wbapitest,		\
+  linux_i586_2.6-{product|fastdebug}-c2-hotspot_wbapitest,		\
+  linux_x64_2.6-{product|fastdebug}-c2-hotspot_wbapitest,		\
+  windows_i586_6.1-{product|fastdebug}-c2-hotspot_wbapitest,		\
+  windows_x64_6.1-{product|fastdebug}-c2-hotspot_wbapitest,		\
+  linux_i586_2.6-{product|fastdebug}-c1-hotspot_wbapitest,		\
+  windows_i586_6.1-{product|fastdebug}-c1-hotspot_wbapitest
+
+my.make.rule.test.targets.hotspot=					\
+  ${my.make.rule.test.targets.hotspot.clienttests},			\
+  ${my.make.rule.test.targets.hotspot.servertests},			\
+  ${my.make.rule.test.targets.hotspot.internalvmtests},			\
+  ${my.make.rule.test.targets.hotspot.wbapitests},			\
+  ${my.additional.make.rule.test.targets.hotspot}
diff --git a/nashorn/.hgtags b/nashorn/.hgtags
index 8d2def7..3919ccb 100644
--- a/nashorn/.hgtags
+++ b/nashorn/.hgtags
@@ -299,3 +299,8 @@
 ad36f9454ce38d78be39fc819902e1223765ee5e jdk8u20-b23
 d3da140e179343011017669a6dbfcc52b0e56f52 jdk8u20-b24
 d3da140e179343011017669a6dbfcc52b0e56f52 jdk8u20-b25
+a23ac9db4227d78b3389e01fa94a8cb695a8fb0a jdk8u20-b26
+f2925491b61b22ac42f8c30ee9c6723ffa401a4c jdk8u40-b00
+62468d841b842769d875bd97d10370585c296eb7 jdk8u40-b01
+b476c69c820ac1e05071f4de5abab8e2dff80e87 jdk8u40-b02
+a2e0a985764b5afd5f316429bfab4f44bf150f7f jdk8u40-b03
diff --git a/nashorn/bin/checkintest.sh b/nashorn/bin/checkintest.sh
deleted file mode 100644
index c4a9e96..0000000
--- a/nashorn/bin/checkintest.sh
+++ /dev/null
@@ -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"
diff --git a/nashorn/bin/dump_octane_code.sh b/nashorn/bin/dump_octane_code.sh
deleted file mode 100644
index d24ab2c..0000000
--- a/nashorn/bin/dump_octane_code.sh
+++ /dev/null
@@ -1,53 +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.
-#
-
-#
-# The purpose of this script is to provide a large amount of IR/bytecode from a known
-# application to be diffed against the same output with a different Nashorn version.
-# That way we can quickly detect if a seemingly minute change modifies a lot of code,
-# which it most likely shouldn't. One example of this was when AccessSpecializer was
-# moved into Lower the first time, it worked fine, but as a lot of Scope information
-# at the time was finalized further down the code pipeline it did a lot fewer callsite
-# specializations. This would have been immediately detected with a before and after 
-# diff using the output from this script.
-#
-
-ITERS=$1
-if [ -z $ITERS ]; then 
-    ITERS=7
-fi
-NASHORN_JAR=dist/nashorn.jar
-JVM_FLAGS="-ea -esa -server -jar ${NASHORN_JAR}"
-
-BENCHMARKS=( "box2d.js" "code-load.js" "crypto.js" "deltablue.js" "earley-boyer.js" "gbemu.js" "mandreel.js" "navier-stokes.js" "pdfjs.js" "raytrace.js" "regexp.js" "richards.js" "splay.js" )
-
-for BENCHMARK in "${BENCHMARKS[@]}"
-do     
-    echo "START: ${BENCHMARK}"
-    CMD="${JAVA_HOME}/bin/java ${JVM_FLAGS} -co --print-lower-parse test/script/external/octane/${BENCHMARK}"
-    $CMD
-    echo "END: ${BENCHMARK}"
-    echo ""
-done
-
-echo "Done"
diff --git a/nashorn/bin/fixwhitespace.sh b/nashorn/bin/fixwhitespace.sh
index cac757d..d327470 100644
--- a/nashorn/bin/fixwhitespace.sh
+++ b/nashorn/bin/fixwhitespace.sh
@@ -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
diff --git a/nashorn/bin/jjs b/nashorn/bin/jjs
deleted file mode 100644
index f89a07c..0000000
--- a/nashorn/bin/jjs
+++ /dev/null
@@ -1,29 +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.  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.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/java -server -XX:+TieredCompilation -Xms2G -Xmx2G -esa -ea -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.debug=true jdk.nashorn.tools.Shell $*
diff --git a/nashorn/bin/jjs.bat b/nashorn/bin/jjs.bat
deleted file mode 100644
index 3c1c159..0000000
--- a/nashorn/bin/jjs.bat
+++ /dev/null
@@ -1,27 +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.  Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-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
-
-java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.ext.dirs=%~dp0\..\dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false jdk.nashorn.tools.Shell
diff --git a/nashorn/bin/jjsdebug.sh b/nashorn/bin/jjsdebug.sh
new file mode 100644
index 0000000..509700c
--- /dev/null
+++ b/nashorn/bin/jjsdebug.sh
@@ -0,0 +1,25 @@
+#!/bin/sh
+#
+# Copyright (c) 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.
+#
+
+$JAVA_HOME/bin/jjs -J-Djava.ext.dirs=`dirname $0`/../dist -J-agentlib:jdwp=transport=dt_socket,address=localhost:9009,server=y,suspend=y $*
diff --git a/nashorn/bin/jjssecure b/nashorn/bin/jjssecure
deleted file mode 100644
index db6bdfc..0000000
--- a/nashorn/bin/jjssecure
+++ /dev/null
@@ -1,29 +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.  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.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=`dirname $0`/../make/java.security.override -Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=true -Dnashorn.home=`dirname $0`/.. -Djava.security.manager jdk.nashorn.tools.Shell $*
diff --git a/nashorn/bin/jjssecure.bat b/nashorn/bin/jjssecure.bat
deleted file mode 100644
index f8da10a..0000000
--- a/nashorn/bin/jjssecure.bat
+++ /dev/null
@@ -1,27 +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.  Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-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
-
-java -Xms2G -Xmx2G -XX:-TieredCompilation -server -esa -ea -Djava.security.properties=%~dp0\..\make\java.security.override -Djava.ext.dirs=%~dp0\..\dist -XX:+HeapDumpOnOutOfMemoryError -Dnashorn.debug=true -Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -Dnashorn.home=%~dp0\.. -Djava.security.manager jdk.nashorn.tools.Shell
diff --git a/nashorn/bin/nashorn b/nashorn/bin/nashorn
deleted file mode 100644
index da22be1..0000000
--- a/nashorn/bin/nashorn
+++ /dev/null
@@ -1,29 +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.  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.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $*
diff --git a/nashorn/bin/nashorn.bat b/nashorn/bin/nashorn.bat
deleted file mode 100644
index 2961ac6..0000000
--- a/nashorn/bin/nashorn.bat
+++ /dev/null
@@ -1,27 +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.  Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-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
-
-jrunscript -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=%~dp0\..\dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Dnashorn.debug=true -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -l nashorn
diff --git a/nashorn/bin/nashornsecure b/nashorn/bin/nashornsecure
deleted file mode 100644
index 77c7c52..0000000
--- a/nashorn/bin/nashornsecure
+++ /dev/null
@@ -1,29 +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.  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.
-#
-
-[ -z "$JAVA_HOME" ] && echo "Please set JAVA_HOME" && exit 1;
-
-$JAVA_HOME/bin/jrunscript -J-Djava.security.properties=`dirname $0`/../make/java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=`dirname $0`/../dist:$JAVA_HOME/jre/lib/ext -J-XX:+HeapDumpOnOutOfMemoryError -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -J-Dnashorn.debug=true -l nashorn $*
diff --git a/nashorn/bin/nashornsecure.bat b/nashorn/bin/nashornsecure.bat
deleted file mode 100644
index 5a4eca6..0000000
--- a/nashorn/bin/nashornsecure.bat
+++ /dev/null
@@ -1,27 +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.  Oracle designates this
-rem particular file as subject to the "Classpath" exception as provided
-rem by Oracle in the LICENSE file that accompanied this code.
-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
-
-jrunscript -J-Djava.security.properties=%~dp0\..\make\java.security.override -J-Djava.security.manager -J-Xms2G -J-Xmx2G -J-XX:-TieredCompilation -J-server -J-esa -J-ea -J-Djava.ext.dirs=%~dp0\..\dist -J-XX:+HeapDumpOnOutOfMemoryError -J-Dnashorn.debug=true -J-Djava.lang.invoke.MethodHandle.DEBUG_NAMES=false -l nashorn
diff --git a/nashorn/bin/run_octane.sh b/nashorn/bin/run_octane.sh
new file mode 100644
index 0000000..a50137f
--- /dev/null
+++ b/nashorn/bin/run_octane.sh
@@ -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
diff --git a/nashorn/bin/runopt.sh b/nashorn/bin/runopt.sh
new file mode 100644
index 0000000..6b26e28
--- /dev/null
+++ b/nashorn/bin/runopt.sh
@@ -0,0 +1,107 @@
+#!/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
+
+$JAVA_HOME/bin/java \
+$FLAGS \
+-ea \
+-esa \
+-Xbootclasspath/p:$NASHORN_JAR \
+-Xms2G -Xmx2G \
+-cp $CLASSPATH:../build/test/classes/ \
+jdk.nashorn.tools.Shell ${@}
+
+# Below are flags that may come in handy, but aren't used for default runs
+
+
+# Type profiling default level is 111, 222 adds some compile time, but produces better code.
+# -XX:TypeProfileLevel=222 \
+
+
+# Testing out new code optimizations using the generic hotspot "new code" parameter
+#-XX:+UnlockDiagnosticVMOptions \
+#-XX:+UseNewCode \
+
+
+# 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
+
diff --git a/nashorn/bin/verbose_octane.bat b/nashorn/bin/verbose_octane.bat
deleted file mode 100644
index ab9e484..0000000
--- a/nashorn/bin/verbose_octane.bat
+++ /dev/null
@@ -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
diff --git a/nashorn/bin/verbose_octane.sh b/nashorn/bin/verbose_octane.sh
deleted file mode 100644
index 1895afe..0000000
--- a/nashorn/bin/verbose_octane.sh
+++ /dev/null
@@ -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"
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
index bb6abbc..2059567 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ClassGenerator.java
@@ -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;
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
index 67cbde4..2661e09 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/ConstructorGenerator.java
@@ -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;
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
index e47f8b1..c8a929d 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MemberInfo.java
@@ -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;
@@ -413,6 +412,10 @@
                     }
                 }
             }
+            break;
+
+            default:
+            break;
         }
     }
 
@@ -451,7 +454,7 @@
 
         if (type.getSort() == Type.OBJECT) {
             try {
-                final Class clazz = Class.forName(type.getClassName(), false, myLoader);
+                final Class<?> clazz = Class.forName(type.getClassName(), false, myLoader);
                 return ScriptObject.class.isAssignableFrom(clazz);
             } catch (final ClassNotFoundException cnfe) {
                 return false;
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
index 479d1d3..a8d6ae2 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/MethodGenerator.java
@@ -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);
     }
 }
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
index 7b1fff7..8eb19b7 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/PrototypeGenerator.java
@@ -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;
diff --git a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
index 1d72418..fb72bbe 100644
--- a/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
+++ b/nashorn/buildtools/nasgen/src/jdk/nashorn/internal/tools/nasgen/StringConstants.java
@@ -26,9 +26,8 @@
 package jdk.nashorn.internal.tools.nasgen;
 
 import java.lang.invoke.MethodHandle;
-import java.lang.reflect.Method;
-import java.util.Collection;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import jdk.internal.org.objectweb.asm.Type;
diff --git a/nashorn/docs/DEVELOPER_README b/nashorn/docs/DEVELOPER_README
index 9a2fffd..fe14095 100644
--- a/nashorn/docs/DEVELOPER_README
+++ b/nashorn/docs/DEVELOPER_README
@@ -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.)
diff --git a/nashorn/docs/genshelldoc.js b/nashorn/docs/genshelldoc.js
index 3d11a47..9647351 100644
--- a/nashorn/docs/genshelldoc.js
+++ b/nashorn/docs/genshelldoc.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -61,7 +61,7 @@
 
 for each (opt in Options.validOptions) {
 
-var isTimezone = (opt.type == "timezone");   
+var isTimezone = (opt.type == "timezone");
 var defValue = opt.defaultValue;
 if (defValue == null) {
     defValue = "&lt;none&gt;";
diff --git a/nashorn/docs/source/importpackageclass.js b/nashorn/docs/source/importpackageclass.js
index afc02a9..224debd 100644
--- a/nashorn/docs/source/importpackageclass.js
+++ b/nashorn/docs/source/importpackageclass.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -32,7 +32,7 @@
 // load compatibility script
 load("nashorn:mozilla_compat.js");
 
-// Import Java packages and classes 
+// Import Java packages and classes
 // like import package.*; in Java
 importPackage(java.awt);
 // like import java.awt.Frame in Java
diff --git a/nashorn/docs/source/javaarray.js b/nashorn/docs/source/javaarray.js
index d0de912..6596191 100644
--- a/nashorn/docs/source/javaarray.js
+++ b/nashorn/docs/source/javaarray.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/docs/source/javaextend.js b/nashorn/docs/source/javaextend.js
index 408da32..f1c6256 100644
--- a/nashorn/docs/source/javaextend.js
+++ b/nashorn/docs/source/javaextend.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/docs/source/javaimporter.js b/nashorn/docs/source/javaimporter.js
index 3bd0798..5004ce8 100644
--- a/nashorn/docs/source/javaimporter.js
+++ b/nashorn/docs/source/javaimporter.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/docs/source/javatypes.js b/nashorn/docs/source/javatypes.js
index e0b6f07..82392ec 100644
--- a/nashorn/docs/source/javatypes.js
+++ b/nashorn/docs/source/javatypes.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/docs/source/overload.js b/nashorn/docs/source/overload.js
index 2407d0c..a2905f9 100644
--- a/nashorn/docs/source/overload.js
+++ b/nashorn/docs/source/overload.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -31,6 +31,6 @@
 
 var out = java.lang.System.out;
 
-// select a particular print function 
+// select a particular print function
 out["println(java.lang.Object)"]("hello");
 
diff --git a/nashorn/docs/source/runnable.js b/nashorn/docs/source/runnable.js
index 67cd31c..346c252 100644
--- a/nashorn/docs/source/runnable.js
+++ b/nashorn/docs/source/runnable.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/docs/source/samfunc.js b/nashorn/docs/source/samfunc.js
index c870076..dbb321d 100644
--- a/nashorn/docs/source/samfunc.js
+++ b/nashorn/docs/source/samfunc.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/docs/source/test.js b/nashorn/docs/source/test.js
index 6323c38..56e96ef 100644
--- a/nashorn/docs/source/test.js
+++ b/nashorn/docs/source/test.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/make/build-benchmark.xml b/nashorn/make/build-benchmark.xml
index ac87fc1..ae76718 100644
--- a/nashorn/make/build-benchmark.xml
+++ b/nashorn/make/build-benchmark.xml
@@ -1,381 +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.
--->
-<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"/>
-  </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"/>
-  </target>
+<!--
+    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=".."
+    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="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="box2d"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="box2d"/>
-    </antcall>
+    <run-one cond="octane.benchmark.box2d" runtime="v8"/>
   </target>
-
   <target name="octane-box2d-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="box2d"/>
-    </antcall>
+    <run-one cond="octane.benchmark.box2d" runtime="rhino"/>
   </target>
 
-
-  <!-- code-load -->  
-  <target name="octane-code-load" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="code-load"/>
-    </antcall>
+  <!-- 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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="code-load"/>
-    </antcall>
+    <run-one cond="octane.benchmark.code-load" runtime="v8"/>
   </target>
-
   <target name="octane-code-load-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="code-load"/>
-    </antcall>
+    <run-one cond="octane.benchmark.code-load" runtime="rhino"/>
   </target>
 
-
   <!-- crypto -->
-  <target name="octane-crypto" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="crypto"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="crypto"/>
-    </antcall>
+    <run-one cond="octane.benchmark.crypto" runtime="v8"/>
   </target>
-
   <target name="octane-crypto-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="crypto"/>
-    </antcall>
+    <run-one cond="octane.benchmark.crypto" runtime="rhino"/>
   </target>
 
-
   <!-- deltablue -->
-  <target name="octane-deltablue" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="deltablue"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="deltablue"/>
-    </antcall>
+    <run-one cond="octane.benchmark.deltablue" runtime="v8"/>
   </target>
-
   <target name="octane-deltablue-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="deltablue"/>
-    </antcall>
+    <run-one cond="octane.benchmark.deltablue" runtime="rhino"/>
   </target>
 
-
   <!-- earley-boyer -->
-  <target name="octane-earley-boyer" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="earley-boyer"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="earley-boyer"/>
-    </antcall>
+    <run-one cond="octane.benchmark.earley-boyer" runtime="v8"/>
   </target>
-
   <target name="octane-earley-boyer-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="earley-boyer"/>
-    </antcall>
+    <run-one cond="octane.benchmark.earley-boyer" runtime="rhino"/>
   </target>
-
-
-  <!-- gbemu -->  
-  <target name="octane-gbemu" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="gbemu"/>
-    </antcall>
+  
+  <!-- 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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="gbemu"/>
-    </antcall>
+    <run-one cond="octane.benchmark.gbemu" runtime="v8"/>
   </target>
-
   <target name="octane-gbemu-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="gbemu"/>
-    </antcall>
+    <run-one cond="octane.benchmark.gbemu" runtime="rhino"/>
   </target>
 
-
-  <!-- mandreel -->  
-  <target name="octane-mandreel" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="mandreel"/>
-    </antcall>
+  <!-- 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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="mandreel"/>
-    </antcall>
+    <run-one cond="octane.benchmark.mandreel" runtime="v8"/>
   </target>
-
   <target name="octane-mandreel-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="mandreel"/>
-    </antcall>
+    <run-one cond="octane.benchmark.mandreel" runtime="rhino"/>
   </target>
 
-
   <!-- navier-stokes -->
-  <target name="octane-navier-stokes" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="navier-stokes"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="navier-stokes"/>
-    </antcall>
+    <run-one cond="octane.benchmark.navier-stokes" runtime="v8"/>
   </target>
-
   <target name="octane-navier-stokes-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="navier-stokes"/>
-    </antcall>
+    <run-one cond="octane.benchmark.navier-stokes" runtime="rhino"/>
   </target>
 
-
-  <!-- pdfjs -->  
-  <target name="octane-pdfjs" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="pdfjs"/>
-    </antcall>
+  <!-- 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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="pdfjs"/>
-    </antcall>
+    <run-one cond="octane.benchmark.pdfjs" runtime="v8"/>
   </target>
-
   <target name="octane-pdfjs-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="pdfjs"/>
-    </antcall>
+    <run-one cond="octane.benchmark.pdfjs" runtime="rhino"/>
   </target>
 
-
   <!-- raytrace -->
-  <target name="octane-raytrace" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="raytrace"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="raytrace"/>
-    </antcall>
+    <run-one cond="octane.benchmark.raytrace" runtime="v8"/>
   </target>
-
   <target name="octane-raytrace-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="raytrace"/>
-    </antcall>
+    <run-one cond="octane.benchmark.raytrace" runtime="rhino"/>
   </target>
 
-
   <!-- regexp -->
-  <target name="octane-regexp" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="regexp"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="regexp"/>
-    </antcall>
+    <run-one cond="octane.benchmark.regexp" runtime="v8"/>
   </target>
-
   <target name="octane-regexp-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="regexp"/>
-    </antcall>
+    <run-one cond="octane.benchmark.regexp" runtime="rhino"/>
   </target>
 
-
   <!-- richards -->
-  <target name="octane-richards" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="richards"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="richards"/>
-    </antcall>
+    <run-one cond="octane.benchmark.richards" runtime="v8"/>
   </target>
-
   <target name="octane-richards-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="richards"/>
-    </antcall>
+    <run-one cond="octane.benchmark.richards" runtime="rhino"/>
   </target>
 
-
   <!-- splay -->
-  <target name="octane-splay" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="splay"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-tests" value="splay"/>
-    </antcall>
+    <run-one cond="octane.benchmark.splay" runtime="v8"/>
   </target>
-
   <target name="octane-splay-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="splay"/>
-    </antcall>
+    <run-one cond="octane.benchmark.splay" runtime="rhino"/>
   </target>
 
-  <!-- splay -->
-  <target name="octane-typescript" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="typescript"/>
-    </antcall>
+  <!-- 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">
-    <antcall target="run-octane-v8">
-      <param name="octane-typescript" value="typescript"/>
-    </antcall>
+    <run-one cond="octane.benchmark.typescript" runtime="v8"/>
   </target>
-
   <target name="octane-typescript-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="typescript"/>
-    </antcall>
+    <run-one cond="octane.benchmark.typescript" runtime="rhino"/>
   </target>
 
   <!-- zlib -->
-  <target name="octane-zlib" depends="jar">
-    <antcall target="run-octane">
-      <param name="octane-tests" value="zlib"/>
-    </antcall>
+  <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">
-    <antcall target="run-octane-v8">
-      <param name="octane-typescript" value="zlib"/>
-    </antcall>
+    <run-one cond="octane.benchmark.zlib" runtime="v8"/>
   </target>
-
   <target name="octane-zlib-rhino" depends="jar">
-    <antcall target="run-octane-rhino">
-      <param name="octane-tests" value="zlib"/>
+    <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>
 
-  <!-- run octane benchmarks in a single process  -->
-  <target name="octane-single-process" depends="octane-init">
-    <antcall target="run-octane"/>
+  <!--
+       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>
 
-  <!-- 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>
 
@@ -383,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>
 
@@ -397,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>
 
@@ -413,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"
@@ -436,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>
 
@@ -445,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>
 
@@ -455,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>
 
diff --git a/nashorn/make/build-nasgen.xml b/nashorn/make/build-nasgen.xml
index 9dca550..16094cc 100644
--- a/nashorn/make/build-nasgen.xml
+++ b/nashorn/make/build-nasgen.xml
@@ -36,11 +36,13 @@
                 <pathelement location="${basedir}/jcov2/lib/jcov_j2se_rt.jar"/>
                 <pathelement location="${basedir}/buildtools/nasgen/dist/nasgen.jar"/>
                 <pathelement path="${basedir}/build/classes"/>
+                <pathelement location="${dist.dir}/nasgen.jar"/>
+                <pathelement path="${build.dir}/classes"/>
             </classpath>
             <jvmarg value="-Djava.ext.dirs="/>
-            <arg value="${basedir}/build/classes"/>
+            <arg value="${build.dir}/classes"/>
             <arg value="jdk.nashorn.internal.objects"/>
-            <arg value="${basedir}/build/classes"/>
+            <arg value="${build.dir}/classes"/>
         </java>
     </target>
 
diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml
index 3b30a08..507c0f1 100644
--- a/nashorn/make/build.xml
+++ b/nashorn/make/build.xml
@@ -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,19 +22,22 @@
  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"/>
 
     <loadproperties srcFile="make/project.properties"/>
+    <path id="dist.path">
+         <pathelement location="${dist.dir}"/>
+    </path>
     <path id="nashorn.ext.path">
       <pathelement location="${dist.dir}"/>
+      <pathelement location="${java.ext.dirs}"/>
     </path>
     <property name="ext.class.path" value="-Djava.ext.dirs=&quot;${toString:nashorn.ext.path}&quot;"/>
     <condition property="svn.executable" value="/usr/local/bin/svn" else="svn">
@@ -51,7 +55,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}"/>
@@ -69,13 +73,16 @@
     <condition property="exclude.list" value="./exclude/exclude_list_cc.txt" else="./exclude/exclude_list.txt">
       <istrue value="${make.code.coverage}" />
     </condition>
+
+    <condition property="jfr.options" value="${run.test.jvmargs.jfr}" else="">
+      <istrue value="${jfr}"/>
+    </condition>
   </target>
 
   <target name="init" depends="init-conditions, init-cc">
-
     <!-- extends jvm args -->
-    <property name="run.test.jvmargs" value="${run.test.jvmargs.main}  ${run.test.cc.jvmargs}"/>
-    <property name="run.test.jvmargs.octane" value="${run.test.jvmargs.octane.main}  ${run.test.cc.jvmargs}" />
+    <property name="run.test.jvmargs" value="${run.test.jvmargs.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
+    <property name="run.test.jvmargs.octane" value="${run.test.jvmargs.octane.main} ${run.test.cc.jvmargs} ${jfr.options}"/>
 
     <echo message="run.test.jvmargs=${run.test.jvmargs}"/>
     <echo message="run.test.jvmargs.octane=${run.test.jvmargs.octane}"/>
@@ -122,8 +129,7 @@
            encoding="${javac.encoding}"
            includeantruntime="false" fork="true">
       <compilerarg value="-J-Djava.ext.dirs="/>
-      <compilerarg value="-Xlint:unchecked"/>
-      <compilerarg value="-Xlint:deprecation"/>
+      <compilerarg value="-Xlint:all"/>
       <compilerarg value="-XDignore.symbol.file"/>
       <compilerarg value="-Xdiags:verbose"/>
     </javac>
@@ -291,6 +297,10 @@
   <target name="generate-policy-file" depends="prepare">
     <echo file="${build.dir}/nashorn.policy">
 
+grant codeBase "file:/${toString:dist.path}/nashorn.jar" {
+    permission java.security.AllPermission;
+};
+
 grant codeBase "file:/${basedir}/${nashorn.internal.tests.jar}" {
     permission java.security.AllPermission;
 };
@@ -298,6 +308,14 @@
 grant codeBase "file:/${basedir}/${file.reference.testng.jar}" {
     permission java.security.AllPermission;
 };
+//// in case of absolute path:
+grant codeBase "file:/${nashorn.internal.tests.jar}" {
+    permission java.security.AllPermission;
+};
+
+grant codeBase "file:/${file.reference.testng.jar}" {
+    permission java.security.AllPermission;
+};
 
 grant codeBase "file:/${basedir}/test/script/trusted/*" {
     permission java.security.AllPermission;
@@ -330,6 +348,10 @@
     permission java.lang.RuntimePermission "nashorn.JavaReflection";
 };
 
+grant codeBase "file:/${basedir}/test/script/markdown.js" {
+    permission java.io.FilePermission "${basedir}/test/script/external/showdown/-", "read";
+};
+
     </echo>
 
     <replace file="${build.dir}/nashorn.policy"><replacetoken>\</replacetoken><replacevalue>/</replacevalue></replace>    <!--hack for Windows - to make URLs with normal path separators -->
@@ -345,6 +367,7 @@
       <available file="${test.external.dir}/yui" property="test-sys-prop.external.yui"/>
       <available file="${test.external.dir}/jquery" property="test-sys-prop.external.jquery"/>
       <available file="${test.external.dir}/test262" property="test-sys-prop.external.test262"/>
+      <available file="${test.external.dir}/showdown" property="test-sys-prop.external.markdown"/>
   </target>
 
   <target name="check-testng" unless="testng.available">
@@ -380,7 +403,8 @@
     <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}"/>
-      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
+      <sysproperty key="nashorn.jar" value="${dist.dir}/nashorn.jar"/>
       <propertyset>
         <propertyref prefix="nashorn."/>
       </propertyset>
@@ -401,9 +425,12 @@
     <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}"/>
-      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
       <jvmarg line="${debug.test.jvmargs}"/>
       <propertyset>
+        <propertyref prefix="nashorn."/>
+      </propertyset>
+      <propertyset>
         <propertyref prefix="test-sys-prop."/>
         <mapper from="test-sys-prop.*" to="*" type="glob"/>
       </propertyset>
@@ -416,18 +443,6 @@
 
   <target name="test" depends="jar, -test-classes-all,-test-classes-single, check-testng, check-external-tests, compile-test, generate-policy-file, -test-security, -test-nosecurity" if="testng.available"/>
 
-  <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>
@@ -436,19 +451,19 @@
     <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}"/>
-      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} -Dbuild.dir=${build.dir}"/>
       <propertyset>
         <propertyref prefix="testjfx-test-sys-prop."/>
         <mapper from="testjfx-test-sys-prop.*" to="*" type="glob"/>
@@ -459,7 +474,26 @@
       </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"/>
+    </fileset>
+
+    <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}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
+      <propertyset>
+        <propertyref prefix="testmarkdown-test-sys-prop."/>
+        <mapper from="testmarkdown-test-sys-prop.*" to="*" type="glob"/>
+      </propertyset>
+      <classpath>
+          <pathelement path="${run.test.classpath}"/>
+      </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"/>
@@ -468,7 +502,10 @@
     <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}"/>
-      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
+      <propertyset>
+        <propertyref prefix="nashorn."/>
+      </propertyset>
       <propertyset>
         <propertyref prefix="test262-test-sys-prop."/>
         <mapper from="test262-test-sys-prop.*" to="*" type="glob"/>
@@ -485,7 +522,9 @@
     <!-- use just build.test.classes.dir to avoid referring to TestNG -->
     <java classname="${parallel.test.runner}" dir="${basedir}" fork="true">
       <jvmarg line="${ext.class.path}"/>
-      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs}"/>
+      <jvmarg line="${run.test.jvmargs} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} -Dbuild.dir=${build.dir}"/>
+      <!-- avoid too many typeinfo cache files. Each script is run only once anyway -->
+      <jvmarg line="-Dnashorn.typeInfo.disabled=true"/>
       <classpath>
           <pathelement path="${run.test.classpath}"/>
       </classpath>
@@ -496,6 +535,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"/>
 
@@ -529,6 +588,8 @@
     <!-- clone test262 git repo -->
     <exec executable="${git.executable}">
        <arg value="clone"/>
+       <arg value="--branch"/>
+       <arg value="es5-tests"/>
        <arg value="https://github.com/tc39/test262"/>
        <arg value="${test.external.dir}/test262"/>
     </exec>
@@ -604,6 +665,11 @@
     <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"/>
+    <get src="https://raw.github.com/coreyti/showdown/master/src/extensions/table.js" dest="${test.external.dir}/showdown" skipexisting="true" ignoreerrors="true"/>
+
   </target>
 
   <!-- update external test suites that are pulled from source control systems -->
@@ -619,4 +685,6 @@
 
   <target name="alltests" depends="exit-if-no-testng, externals, update-externals, test, test262parallel, perf"/>
 
+  <import file="build-benchmark.xml"/>
+
 </project>
diff --git a/nashorn/make/nbproject/ide-targets.xml b/nashorn/make/nbproject/ide-targets.xml
index 70b3e68..d1e8135 100644
--- a/nashorn/make/nbproject/ide-targets.xml
+++ b/nashorn/make/nbproject/ide-targets.xml
@@ -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="../samples/test.js"/>
             <jvmarg value="-Xdebug"/>
             <jvmarg value="-Xrunjdwp:transport=dt_socket,address=${jpda.address}"/>
         </java>
diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties
index 2abccde..800a629 100644
--- a/nashorn/make/project.properties
+++ b/nashorn/make/project.properties
@@ -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
@@ -72,6 +74,9 @@
 fxshell.dir = tools/fxshell
 fxshell.jar = ${dist.dir}/nashornfx.jar
 
+# configuration for java flight recorder
+run.test.jvmargs.jfr=-XX:+UnlockCommercialFeatures -XX:+FlightRecorder -XX:FlightRecorderOptions=defaultrecording=true,disk=true,dumponexit=true,dumponexitpath=${build.dir},stackdepth=128
+
 # jars refererred
 file.reference.testng.jar=test/lib/testng.jar
 
@@ -122,6 +127,7 @@
 test262.dir=${test.external.dir}/test262
 test262.suite.dir=${test262.dir}/test/suite
 testjfx.dir=${test.script.dir}/jfx
+testmarkdown.dir=${test.script.dir}/markdown
 
 test-sys-prop.test.dir=${test.dir}
 test-sys-prop.test.js.roots=${test.basic.dir} ${test.maptests.dir} ${test.error.dir} ${test.sandbox.dir} ${test.trusted.dir}
@@ -163,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
@@ -193,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
 
@@ -202,7 +202,7 @@
 # list of test262 test dirs to be excluded
 test262-test-sys-prop.test.js.exclude.dir=\
     ${test262.suite.dir}/intl402/ \
-    ${test262.suite.dir}/bestPractice/ 
+    ${test262.suite.dir}/bestPractice/
 
 test262-test-sys-prop.test.failed.list.file=${build.dir}/test/failedTests
 
@@ -216,8 +216,18 @@
     ${test262.dir}/test/harness/framework.js \
     ${test262.dir}/test/harness/sta.js
 
+# testmarkdown test root
+testmarkdown-test-sys-prop.test.js.roots=${testmarkdown.dir}
+
+# execute testmarkdown tests in shared nashorn context or not?
+testmarkdown-test-sys-prop.test.js.shared.context=false
+
+# framework root for markdown script tests
+testmarkdown-test-sys-prop.test.js.framework=\
+    ${test.script.dir}${file.separator}markdown.js
+
 # testjfx test root
-testjfx-test-sys-prop.test.js.roots=${testjfx.dir}   
+testjfx-test-sys-prop.test.js.roots=${testjfx.dir}
 
 # execute testjfx tests in shared nashorn context or not?
 testjfx-test-sys-prop.test.js.shared.context=false
@@ -254,48 +264,114 @@
 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} \
+  -Dnashorn.typeInfo.cacheDir=${build.dir}${file.separator}test${file.separator}type_info_cache \
+  ${jfr.args} \
+  -XX:+HeapDumpOnOutOfMemoryError
 
 # turn on assertions for tests
 run.test.jvmargs.main=${run.test.jvmargs.common} -ea
 
-#-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
 
-run.test.jvmsecurityargs=-Xverify:all -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy
+# Use best known performance options for octane
+run.test.jvmargs.octane.main=${run.test.jvmargs.common} -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=${build.dir}/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\.*
diff --git a/nashorn/samples/array_mapreduce.js b/nashorn/samples/array_mapreduce.js
index 5335f35..32184e9 100644
--- a/nashorn/samples/array_mapreduce.js
+++ b/nashorn/samples/array_mapreduce.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -31,9 +31,9 @@
 
 // Usage: jjs array_mapreduce.js
 
-// Many Array.prototype functions such as map, 
+// Many Array.prototype functions such as map,
 // filter, reduce, reduceRight, every, some are generic.
-// These functions accept ECMAScript array as well as 
+// These functions accept ECMAScript array as well as
 // many array-like objects including java arrays.
 // So, you can do map/filter/reduce with Java streams or
 // you can also use Array.prototype functions as below.
@@ -73,6 +73,6 @@
 // print sum of squares of the random numbers
 print("Square sum:",
     reduce.call(
-        map.call(jarr, function(x) x*x), 
+        map.call(jarr, function(x) x*x),
         function(x, y) x + y)
 );
diff --git a/nashorn/samples/astviewer.js b/nashorn/samples/astviewer.js
index 090e50e..ad70d91 100644
--- a/nashorn/samples/astviewer.js
+++ b/nashorn/samples/astviewer.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -82,7 +82,7 @@
 // load parser.js from nashorn resources
 load("nashorn:parser.js");
 
-// read the full content of the file and parse it 
+// read the full content of the file and parse it
 // to get AST of the script specified
 var ast = parse(readFully(sourceName));
 
diff --git a/nashorn/samples/barchart_weather.js b/nashorn/samples/barchart_weather.js
index 8574f0a..9402682 100644
--- a/nashorn/samples/barchart_weather.js
+++ b/nashorn/samples/barchart_weather.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/call_lambda.js b/nashorn/samples/call_lambda.js
index d865164..c5a4dc6 100644
--- a/nashorn/samples/call_lambda.js
+++ b/nashorn/samples/call_lambda.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/counters.js b/nashorn/samples/counters.js
index d89ad58..4a570b0 100644
--- a/nashorn/samples/counters.js
+++ b/nashorn/samples/counters.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/dirname.js b/nashorn/samples/dirname.js
index 119d4f3..bb9279d 100644
--- a/nashorn/samples/dirname.js
+++ b/nashorn/samples/dirname.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/disassemble.js b/nashorn/samples/disassemble.js
index 654b9dd..7cf501ff 100644
--- a/nashorn/samples/disassemble.js
+++ b/nashorn/samples/disassemble.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -33,7 +33,7 @@
 
 // Simple .class disassembler that uses bundled ObjectWeb ASM
 // classes in jdk8. WARNING: Bundled ObjectWeb ASM classes are
-// not part of official jdk8 API. It can be changed/removed 
+// not part of official jdk8 API. It can be changed/removed
 // without notice. So, this script is brittle by design!
 
 // This example demonstrates passing arguments to script
diff --git a/nashorn/samples/engine/accessvar.js b/nashorn/samples/engine/accessvar.js
index ae9ec7d..abd5486 100644
--- a/nashorn/samples/engine/accessvar.js
+++ b/nashorn/samples/engine/accessvar.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/engine/callfunc.js b/nashorn/samples/engine/callfunc.js
index 76108fd..e177a7b 100644
--- a/nashorn/samples/engine/callfunc.js
+++ b/nashorn/samples/engine/callfunc.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -29,7 +29,7 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// simple example showing how to call a global script 
+// simple example showing how to call a global script
 // function from caller
 
 var ScriptEngineManager = Java.type("javax.script.ScriptEngineManager");
@@ -42,7 +42,7 @@
 engine.eval("function func(name) { print('I am func, hello ' + name) }");
 
 // invoke functions, methods of code evaluated by engine
-// from javax.script.Invocable interface. But, hey, 
+// from javax.script.Invocable interface. But, hey,
 // calling code is JavaScript and don't worry about types :)
 
 engine.invokeFunction("func", "Nashorn");
diff --git a/nashorn/samples/engine/callmethod.js b/nashorn/samples/engine/callmethod.js
index 8199dcd..c8cbb300 100644
--- a/nashorn/samples/engine/callmethod.js
+++ b/nashorn/samples/engine/callmethod.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -55,7 +55,7 @@
 CODE);
 
 // invoke methods of an object in script world
-// from javax.script.Invocable interface. But, hey, 
+// from javax.script.Invocable interface. But, hey,
 // calling code is JavaScript and don't worry about types :)
 
 // get that script object on which to call a method
diff --git a/nashorn/samples/engine/exposevar.js b/nashorn/samples/engine/exposevar.js
index 93f57ed..f1a309c 100644
--- a/nashorn/samples/engine/exposevar.js
+++ b/nashorn/samples/engine/exposevar.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/engine/foreignobject.js b/nashorn/samples/engine/foreignobject.js
index 3850089..930c3e8 100644
--- a/nashorn/samples/engine/foreignobject.js
+++ b/nashorn/samples/engine/foreignobject.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -54,7 +54,7 @@
 // the class jdk.nashorn.api.scripting.ScriptObjectMirror
 // But nashorn's dynalink linker can treat these objects
 // specially to support natural script syntax to access..
-// In Java code, you need to use ScriptObjectMirror's 
+// In Java code, you need to use ScriptObjectMirror's
 // methods though. Once again, script world is simpler :-)
 
 var foreignObj = engine.get("obj");
diff --git a/nashorn/samples/engine/hello.js b/nashorn/samples/engine/hello.js
index 37fabbf..72606cf 100644
--- a/nashorn/samples/engine/hello.js
+++ b/nashorn/samples/engine/hello.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/engine/interface.js b/nashorn/samples/engine/interface.js
index 75b7aa2..6461776 100644
--- a/nashorn/samples/engine/interface.js
+++ b/nashorn/samples/engine/interface.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -50,7 +50,7 @@
 
 // create Java interface object whose methods are
 // implemented by script functions. This is from
-// javax.script.Invocable. But we are in JS world, 
+// javax.script.Invocable. But we are in JS world,
 // don't worry about types :)
 
 var Runnable = Java.type("java.lang.Runnable");
diff --git a/nashorn/samples/engine/interface2.js b/nashorn/samples/engine/interface2.js
index 771b110..508be3a 100644
--- a/nashorn/samples/engine/interface2.js
+++ b/nashorn/samples/engine/interface2.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/engine/lambda_as_func.js b/nashorn/samples/engine/lambda_as_func.js
index 2600f17..260eeb9 100644
--- a/nashorn/samples/engine/lambda_as_func.js
+++ b/nashorn/samples/engine/lambda_as_func.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/env.js b/nashorn/samples/env.js
index 74377eb..1febe7a 100644
--- a/nashorn/samples/env.js
+++ b/nashorn/samples/env.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -31,8 +31,8 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// In nashorn -scripting mode, 
-// "$ENV" object exposes process 
+// In nashorn -scripting mode,
+// "$ENV" object exposes process
 // environment variables
 
 print($ENV.PATH);
diff --git a/nashorn/samples/expression_closure.js b/nashorn/samples/expression_closure.js
index 1efb184..17189a8 100644
--- a/nashorn/samples/expression_closure.js
+++ b/nashorn/samples/expression_closure.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/filebrowser.js b/nashorn/samples/filebrowser.js
index da00553..2c36275 100644
--- a/nashorn/samples/filebrowser.js
+++ b/nashorn/samples/filebrowser.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/fileline.js b/nashorn/samples/fileline.js
index 05c9975..59d2288 100644
--- a/nashorn/samples/fileline.js
+++ b/nashorn/samples/fileline.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/find_nonfinals2.js b/nashorn/samples/find_nonfinals2.js
new file mode 100644
index 0000000..75fde62
--- /dev/null
+++ b/nashorn/samples/find_nonfinals2.js
@@ -0,0 +1,118 @@
+#// Usage: jjs find_nonfinals2.js -- <directory>
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 Oracle nor the names of its
+ *     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 THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example finds method
+// parameters without "final" keyword and prints info on those.
+
+if (arguments.length == 0) {
+    print("Usage: jjs find_nonfinals2.js -- <directory>");
+    exit(1);
+}
+
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+var Modifier = Java.type("javax.lang.model.element.Modifier");
+
+function checkNonFinalParams(p) {
+    // get the system compiler tool
+    var compiler = ToolProvider.systemJavaCompiler;
+    // get standard file manager
+    var fileMgr = compiler.getStandardFileManager(null, null, null);
+    // Using Java.to convert script array (arguments) to a Java String[]
+    var compUnits = fileMgr.getJavaFileObjects(
+        Java.to(arguments, StringArray));
+    // create a new compilation task
+    var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+    // subclass SimpleTreeVisitor - to find non-final method params
+    var NonFinalsFinder = Java.extend(TreeScanner);
+
+    function printMethod(method) {
+        print(method.modifiers + " "+ method.returnType + " " +
+            method.name + "(" + method.parameters + ")");
+    }
+
+    var pkgName, clsName, compUnitName, lineMap;
+    var visitor = new NonFinalsFinder() {
+        visitCompilationUnit: function(compUnit, p) {
+            pkgName = compUnit.packageName;
+            compUnitName = compUnit.sourceFile.name;
+            lineMap = compUnit.lineMap;
+            return Java.super(visitor).visitCompilationUnit(compUnit, p);
+        },
+
+        visitClass: function(clazz, p) {
+            clsName = clazz.name;
+            return Java.super(visitor).visitClass(clazz, p);
+        },
+
+        visitMethod: function (method, p) {
+            var params = method.parameters;
+            for each (var p in params) {
+                var modifiers = p.modifiers;
+                if (! modifiers.flags.contains(Modifier.FINAL)) {
+                    print(compUnitName);
+                    print(pkgName + "." + clsName);
+                    printMethod(method);
+                    print("->", p,
+                     " @ " + lineMap.getLineNumber(p.pos) + ":" +
+                           lineMap.getColumnNumber(p.pos));
+                }
+            }
+        }
+    }
+
+    for each (var cu in task.parse()) {
+        cu.accept(visitor, null);
+    }
+}
+
+// for each ".java" file in directory (recursively).
+function main(dir) {
+    var totalCount = 0;
+    Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+      forEach(function(p) {
+        var name = p.toFile().absolutePath;
+        if (name.endsWith(".java")) {
+            checkNonFinalParams(p);
+        }
+      });
+}
+
+main(new File(arguments[0]));
diff --git a/nashorn/samples/fizzbuzz.js b/nashorn/samples/fizzbuzz.js
index ba8d83d..a0fde95 100644
--- a/nashorn/samples/fizzbuzz.js
+++ b/nashorn/samples/fizzbuzz.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/for_each.js b/nashorn/samples/for_each.js
index 10fc39a..988e659 100644
--- a/nashorn/samples/for_each.js
+++ b/nashorn/samples/for_each.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -42,7 +42,7 @@
 var arr = new JArray(10);
 
 // store squares as values
-for (i in arr) 
+for (i in arr)
     arr[i] = i*i;
 
 // for .. each on java arrays
@@ -57,7 +57,7 @@
 print("System properties");
 for each (p in System.properties.entrySet()) {
     print(p.key, "=", p.value);
-} 
+}
 
 // print process environment vars as name = value pairs
 print("Process environment");
diff --git a/nashorn/samples/gaussian_random.js b/nashorn/samples/gaussian_random.js
index f52f49f..235cbcb 100644
--- a/nashorn/samples/gaussian_random.js
+++ b/nashorn/samples/gaussian_random.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -37,7 +37,7 @@
 var r = new Random();
 
 // expression closure (see expression_closure.js as well)
-// passed as lambda double generator. "print" passed as 
+// passed as lambda double generator. "print" passed as
 // double consumer lambda to 'forEach' method.
 
 DoubleStream
diff --git a/nashorn/samples/gaussian_random_bind.js b/nashorn/samples/gaussian_random_bind.js
index 052520c..93f2a17 100644
--- a/nashorn/samples/gaussian_random_bind.js
+++ b/nashorn/samples/gaussian_random_bind.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -34,7 +34,7 @@
 var Random = Java.type("java.util.Random");
 var DoubleStream = Java.type("java.util.stream.DoubleStream");
 
-// function as lambda double generator. "print" passed as 
+// function as lambda double generator. "print" passed as
 // double consumer lambda to 'forEach' method.
 // Function.prototype.bind used to attach 'state' for the
 // generator function.
diff --git a/nashorn/samples/gutenberg.js b/nashorn/samples/gutenberg.js
index 4d83a57..3f21b24 100644
--- a/nashorn/samples/gutenberg.js
+++ b/nashorn/samples/gutenberg.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -69,7 +69,7 @@
                // capture title, description now
                inItem = true;
             }
-        
+
             if (inItem) {
                 switch (local) {
                     case 'title':
diff --git a/nashorn/samples/heredoc.js b/nashorn/samples/heredoc.js
index 0c52ca9..dd79361 100644
--- a/nashorn/samples/heredoc.js
+++ b/nashorn/samples/heredoc.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -38,14 +38,14 @@
 
 var sender = "Buffy the Vampire Slayer";
 var recipient = "Spike";
- 
+
 print(<<END
- 
+
 Dear ${recipient},
- 
+
 I wish you to leave Sunnydale and never return.
- 
+
 Not Quite Love,
 ${sender}
- 
+
 END);
diff --git a/nashorn/samples/interface_impl.js b/nashorn/samples/interface_impl.js
index 5e49816..f219766 100644
--- a/nashorn/samples/interface_impl.js
+++ b/nashorn/samples/interface_impl.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/javaastviewer.js b/nashorn/samples/javaastviewer.js
index c446abe..e8285c0 100644
--- a/nashorn/samples/javaastviewer.js
+++ b/nashorn/samples/javaastviewer.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -56,8 +56,8 @@
     // may not be exhaustive - any getAbc would become "abc" property or
     // public field becomes a property of same name.
     var ignoredProps = new HashSet();
-    for each (var word in 
-        ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs', 
+    for each (var word in
+        ['extending', 'implementing', 'init', 'mods', 'clazz', 'defs',
          'expr', 'tag', 'preferredPosition', 'qualid', 'recvparam',
          'restype', 'params', 'startPosition', 'thrown',
          'tree', 'typarams', 'typetag', 'vartype']) {
@@ -83,7 +83,7 @@
 
     var visitor = new ConverterVisitor() {
         // convert java AST node to a friendly script object
-        // which can be viewed. Every node ends up in defaultAction 
+        // which can be viewed. Every node ends up in defaultAction
         // method of SimpleTreeVisitor method.
 
         defaultAction: function (node, p) {
diff --git a/nashorn/samples/javacastcounter.js b/nashorn/samples/javacastcounter.js
index 607b2f8..6d569a1 100644
--- a/nashorn/samples/javacastcounter.js
+++ b/nashorn/samples/javacastcounter.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -83,7 +83,7 @@
         this.lineMap = node.lineMap;
         this.fileName = node.sourceFile.name;
 
-        // Using Java.super API to call super class method here        
+        // Using Java.super API to call super class method here
         return Java.super(counter).visitCompilationUnit(node, p);
     },
 
diff --git a/nashorn/samples/javafoovars.js b/nashorn/samples/javafoovars.js
new file mode 100644
index 0000000..037c2bf
--- /dev/null
+++ b/nashorn/samples/javafoovars.js
@@ -0,0 +1,103 @@
+#// Usage: jjs javafoovars.js -- <directory>
+
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 Oracle nor the names of its
+ *     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 THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+// This example demonstrates Java subclassing by Java.extend
+// and javac Compiler and Tree API. This example counts number
+// of variables called "foo" in the given java source files!
+if (arguments.length == 0) {
+    print("Usage: jjs javafoovars.js -- <directory>");
+    exit(1);
+}
+
+// Java types used
+var File = Java.type("java.io.File");
+var Files = Java.type("java.nio.file.Files");
+var FileVisitOption = Java.type("java.nio.file.FileVisitOption");
+var StringArray = Java.type("java.lang.String[]");
+var ToolProvider = Java.type("javax.tools.ToolProvider");
+var Tree = Java.type("com.sun.source.tree.Tree");
+var TreeScanner = Java.type("com.sun.source.util.TreeScanner");
+var VariableTree = Java.type("com.sun.source.tree.VariableTree");
+
+// count "foo"-s in the given .java files
+function countFoo() {
+    // get the system compiler tool
+    var compiler = ToolProvider.systemJavaCompiler;
+    // get standard file manager
+    var fileMgr = compiler.getStandardFileManager(null, null, null);
+    // Using Java.to convert script array (arguments) to a Java String[]
+    var compUnits = fileMgr.getJavaFileObjects(
+        Java.to(arguments, StringArray));
+    // create a new compilation task
+    var task = compiler.getTask(null, fileMgr, null, null, null, compUnits);
+    // subclass SimpleTreeVisitor - to count variables called "foo"
+    var FooCounterVisitor = Java.extend(TreeScanner);
+    var fooCount = 0;
+
+    var visitor = new FooCounterVisitor() {
+        visitVariable: function (node, p) {
+            if (node.name.toString() == "foo") {
+                fooCount++;
+            }
+        }
+    }
+
+    for each (var cu in task.parse()) {
+        cu.accept(visitor, null);
+    }
+    return fooCount;
+}
+
+// for each ".java" file in directory (recursively) count "foo".
+function main(dir) {
+    var totalCount = 0;
+    Files.walk(dir.toPath(), FileVisitOption.FOLLOW_LINKS).
+      forEach(function(p) {
+        var name = p.toFile().absolutePath;
+        if (name.endsWith(".java")) {
+            var count = 0;
+            try {
+                count = countFoo(p.toFile().getAbsolutePath());
+            } catch (e) {
+                print(e);
+            }
+            if (count != 0) {
+                print(name + ": " + count);
+            }
+            totalCount += count;
+        }
+      });
+    print("Total foo count: " + totalCount);
+}
+
+main(new File(arguments[0]));
diff --git a/nashorn/samples/javaimporter.js b/nashorn/samples/javaimporter.js
index dd487ec..3e3cb1b 100644
--- a/nashorn/samples/javaimporter.js
+++ b/nashorn/samples/javaimporter.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -34,14 +34,14 @@
 
 function readTextFromURL(url) {
 
-    // equivalent to 
-    // 
+    // equivalent to
+    //
     //    import java.io.*;
     //    import java.net.*;
     //    import java.lang.StringBuffer;
     //
     // only inside the 'with' statement
-    with (new JavaImporter(java.io, 
+    with (new JavaImporter(java.io,
         java.net,
         java.lang.StringBuilder)) {
         var buf = new StringBuilder();
diff --git a/nashorn/samples/javalist.js b/nashorn/samples/javalist.js
index 8f3749b..5430dbd 100644
--- a/nashorn/samples/javalist.js
+++ b/nashorn/samples/javalist.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/javamap.js b/nashorn/samples/javamap.js
index a53d032..57da620 100644
--- a/nashorn/samples/javamap.js
+++ b/nashorn/samples/javamap.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -45,7 +45,7 @@
 print(map['js']);
 print(map.js);
 
-// also assign new key-value pair 
+// also assign new key-value pair
 // as 'property-value'
 map['language'] = 'java';
 print(map.get("language"));
diff --git a/nashorn/samples/javashell.js b/nashorn/samples/javashell.js
index 65d1a8a..4e71f75 100644
--- a/nashorn/samples/javashell.js
+++ b/nashorn/samples/javashell.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -130,7 +130,7 @@
 // generate unique name
 function uniqueName() {
     var now = LocalDateTime.now().toString();
-    // replace unsafe chars with '_' 
+    // replace unsafe chars with '_'
     return "JavaShell" + now.replace(/-|:|\./g, '_');
 }
 
diff --git a/nashorn/samples/jsadapter_dom.js b/nashorn/samples/jsadapter_dom.js
index e86c6d2..cb2f8ba 100644
--- a/nashorn/samples/jsadapter_dom.js
+++ b/nashorn/samples/jsadapter_dom.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -33,7 +33,7 @@
 
 // Simple example that demonstrates reading XML Rss feed
 // to generate a HTML file from script and show it by browser
-// Uses XML DOM parser and DOM element wrapped by script 
+// Uses XML DOM parser and DOM element wrapped by script
 // "proxy" (JSAdapter constructor)
 
 // Java classes used
@@ -78,7 +78,7 @@
         var node = nodeList.item(i);
         if (node.nodeType == TEXT_NODE) {
             text += node.nodeValue;
-        } 
+        }
     }
 
     return text;
diff --git a/nashorn/samples/jsobj_example.js b/nashorn/samples/jsobj_example.js
new file mode 100644
index 0000000..d608876
--- /dev/null
+++ b/nashorn/samples/jsobj_example.js
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 Oracle nor the names of its
+ *     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 THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+// Flexible script object using AbstractJSObject subclass
+
+var AbstractJSObject = Java.type("jdk.nashorn.api.scripting.AbstractJSObject");
+
+// JSObject example that uses a map for properties and
+// falls back to with methods on a java object (for missing
+// properties
+
+function makeJSObj(map, fallback) {
+    return new AbstractJSObject() {
+        getMember: function(name) {
+            if (map.containsKey(name)) {
+                return map.get(name);
+            }
+
+            var val = fallback[name];
+            if (typeof val == 'function') {
+                return function() {
+                   var a = arguments;
+                   switch (a.length) {
+                       case 0: return fallback[name]();
+                       case 1: return fallback[name](a[0]);
+                       case 2: return fallback[name](a[0], a[1]);
+                       case 3: return fallback[name](a[0], a[1], a[2]);
+                       case 4: return fallback[name](a[0], a[1], a[2], a[3]);
+                   }
+                }
+            }
+        }
+    }
+}
+
+var m = new java.util.HashMap();
+m.put("foo", 42);
+m.put("bar", 'hello');
+
+var obj = makeJSObj(m, new java.io.File("."));
+
+print(obj.foo);
+print(obj.bar);
+print(obj.getAbsolutePath());
+print(obj.isDirectory());
diff --git a/nashorn/samples/jsobject.js b/nashorn/samples/jsobject.js
index 48434d7..ad09b2f 100644
--- a/nashorn/samples/jsobject.js
+++ b/nashorn/samples/jsobject.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/jsobject_mapreduce.js b/nashorn/samples/jsobject_mapreduce.js
index ff34940..174ad0a 100644
--- a/nashorn/samples/jsobject_mapreduce.js
+++ b/nashorn/samples/jsobject_mapreduce.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -31,9 +31,9 @@
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-// Many Array.prototype functions such as map, 
+// Many Array.prototype functions such as map,
 // filter, reduce, reduceRight, every, some are generic.
-// These functions accept ECMAScript array as well as 
+// These functions accept ECMAScript array as well as
 // many array-like objects including JSObjects.
 // See also http://en.wikipedia.org/wiki/MapReduce
 
@@ -57,6 +57,6 @@
 // print sum of squares of the random numbers
 print("Square sum:",
     reduce.call(
-        map.call(buf, function(x) x*x), 
+        map.call(buf, function(x) x*x),
         function(x, y) x + y)
 );
diff --git a/nashorn/samples/jsonviewer.js b/nashorn/samples/jsonviewer.js
index 804fef5..c650ae9 100644
--- a/nashorn/samples/jsonviewer.js
+++ b/nashorn/samples/jsonviewer.js
@@ -4,22 +4,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -52,8 +52,8 @@
 
 // read text content of a URL
 function readTextFromURL(url) {
-    // equivalent to 
-    // 
+    // equivalent to
+    //
     //    import java.io.*;
     //    import java.net.*;
     //    import java.lang.StringBuffer;
diff --git a/nashorn/samples/letter.js b/nashorn/samples/letter.js
index 304bf1f..b5a58b8 100644
--- a/nashorn/samples/letter.js
+++ b/nashorn/samples/letter.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -43,7 +43,7 @@
 // JavaScript style line comment is ok too.
 print(<<EOF);
 Dear ${obj.recipient},
- 
+
 I wish you all the best.
 
 Regards,
diff --git a/nashorn/samples/list_mapreduce.js b/nashorn/samples/list_mapreduce.js
index 033f4d7..ac2df98 100644
--- a/nashorn/samples/list_mapreduce.js
+++ b/nashorn/samples/list_mapreduce.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -31,9 +31,9 @@
 
 // Usage: jjs list_mapreduce.js
 
-// Many Array.prototype functions such as map, 
+// Many Array.prototype functions such as map,
 // filter, reduce, reduceRight, every, some are generic.
-// These functions accept ECMAScript array as well as 
+// These functions accept ECMAScript array as well as
 // many array-like objects including java.util.ArrayLists.
 // So, you can do map/filter/reduce with Java streams or
 // you can also use Array.prototype functions as below.
@@ -81,6 +81,6 @@
 // print sum of squares of the random numbers
 print("Square sum:",
     reduce.call(
-        map.call(list, function(x) x*x), 
+        map.call(list, function(x) x*x),
         function(x, y) x + y)
 );
diff --git a/nashorn/samples/locales.js b/nashorn/samples/locales.js
index ae42f96..f16338d 100644
--- a/nashorn/samples/locales.js
+++ b/nashorn/samples/locales.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/logisticmap.js b/nashorn/samples/logisticmap.js
index 7419847..e9b0700 100644
--- a/nashorn/samples/logisticmap.js
+++ b/nashorn/samples/logisticmap.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/options.js b/nashorn/samples/options.js
index 3a10346..9c26b39 100644
--- a/nashorn/samples/options.js
+++ b/nashorn/samples/options.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/parser.js b/nashorn/samples/parser.js
index 2f172cc..16334ae 100644
--- a/nashorn/samples/parser.js
+++ b/nashorn/samples/parser.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/readLine.js b/nashorn/samples/readLine.js
index 9807d3b..d41d35c 100644
--- a/nashorn/samples/readLine.js
+++ b/nashorn/samples/readLine.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/sam_function.js b/nashorn/samples/sam_function.js
index 8406473..70aa5ab 100644
--- a/nashorn/samples/sam_function.js
+++ b/nashorn/samples/sam_function.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -46,6 +46,6 @@
 }, 1000);
 
 // wait for timer thread to print by
-// reading from stdin. 
+// reading from stdin.
 print("press any key to exit after message from timer...");
 System.in.read();
diff --git a/nashorn/samples/shell.js b/nashorn/samples/shell.js
index 9396538..8e3195c 100644
--- a/nashorn/samples/shell.js
+++ b/nashorn/samples/shell.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/stack.js b/nashorn/samples/stack.js
index 295ad20..13b63fa 100644
--- a/nashorn/samples/stack.js
+++ b/nashorn/samples/stack.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -33,7 +33,7 @@
 // error objects. This property's value is a string
 // that shows script stack trace.
 
-function g() { 
+function g() {
     throw new Error("wrong");
 }
 
@@ -44,9 +44,9 @@
 // Output looks something like:
 //
 //  Error: wrong
-//	at g (stack.js:37)
-//	at f (stack.js:41)
-//	at <program> (stack.js:52)
+//    at g (stack.js:37)
+//    at f (stack.js:41)
+//    at <program> (stack.js:52)
 
 try {
    f();
diff --git a/nashorn/samples/uniform_random.js b/nashorn/samples/uniform_random.js
index a82cd0b..da3f26a 100644
--- a/nashorn/samples/uniform_random.js
+++ b/nashorn/samples/uniform_random.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/uniq.js b/nashorn/samples/uniq.js
index cbd2c34..f9316eb 100644
--- a/nashorn/samples/uniq.js
+++ b/nashorn/samples/uniq.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/uniqs.js b/nashorn/samples/uniqs.js
index 57eb7c5..1c36c67 100644
--- a/nashorn/samples/uniqs.js
+++ b/nashorn/samples/uniqs.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -31,7 +31,7 @@
 
 // Usage: jjs uniqs.js -- <file>
 // omit repeated lines and print unique lines
-// But this version uses Stream API 
+// But this version uses Stream API
 
 if (arguments.length < 1) {
     print("Usage: jjs uniqs.js -- <file>");
diff --git a/nashorn/samples/weather.js b/nashorn/samples/weather.js
index 75c6b26..3a37bc1 100644
--- a/nashorn/samples/weather.js
+++ b/nashorn/samples/weather.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/word_histogram.js b/nashorn/samples/word_histogram.js
index 9c739ea..39f4f68 100644
--- a/nashorn/samples/word_histogram.js
+++ b/nashorn/samples/word_histogram.js
@@ -2,22 +2,22 @@
 
 /*
  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/samples/zipfs.js b/nashorn/samples/zipfs.js
new file mode 100644
index 0000000..ecb6f61
--- /dev/null
+++ b/nashorn/samples/zipfs.js
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 Oracle nor the names of its
+ *     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 THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+if (arguments.length == 0) {
+   print("Usage: jjs zipfs.js -- <.zip/.jar file>")
+   exit(1)
+}
+
+var Files = Java.type("java.nio.file.Files")
+var FileSystems = Java.type("java.nio.file.FileSystems")
+var FileVisitOption = Java.type("java.nio.file.FileVisitOption")
+var Paths = Java.type("java.nio.file.Paths")
+
+var zipfile = Paths.get(arguments[0])
+var fs = FileSystems.newFileSystem(zipfile, null)
+var root = fs.rootDirectories[0]
+Files.walk(root, FileVisitOption.FOLLOW_LINKS).forEach(
+   function(p) (print(p), print(Files.readAttributes(p, "zip:*")))
+)
+fs.close()
diff --git a/nashorn/samples/ziplist.js b/nashorn/samples/ziplist.js
new file mode 100644
index 0000000..214dd35
--- /dev/null
+++ b/nashorn/samples/ziplist.js
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 Oracle nor the names of its
+ *     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 THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+if (arguments.length == 0) {
+    print("Usage: jjs ziplist -- <zip-file>");
+    exit(1);
+}
+
+// list the content details of a .zip or .jar file
+var file = arguments[0];
+
+// java classes used
+var Attributes = Java.type("java.util.jar.Attributes");
+var FileTime = Java.type("java.nio.file.attribute.FileTime");
+var JarFile = Java.type("java.util.jar.JarFile");
+var ZipEntry = Java.type("java.util.zip.ZipEntry");
+var ZipFile = Java.type("java.util.zip.ZipFile");
+
+var zf = file.endsWith(".jar")? new JarFile(file) : new ZipFile(file);
+
+var entries = zf.entries();
+// make overall output a valid JSON
+var zfObj = {
+    name: zf.name,
+    comment: zf.comment,
+    size: zf.size(),
+    entries: []
+};
+
+while (entries.hasMoreElements()) {
+    zfObj.entries.push(entries.nextElement());
+}
+
+print(JSON.stringify(zfObj, function (key, value) {
+   if (value instanceof ZipEntry) {
+       return Object.bindProperties({}, value);
+   } else if (value instanceof FileTime) {
+       return value.toString();
+   } else if (value instanceof Attributes) {
+       var attrs = {};
+       var itr = value.entrySet().iterator();
+       while (itr.hasNext()) {
+           var n = itr.next();
+           attrs[n.key] = String(n.value);
+       }
+       return attrs;
+   }
+
+   return value;
+}, ' '));
+
+zf.close();
diff --git a/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java b/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java
index c2ad4eb..45f191a 100644
--- a/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java
+++ b/nashorn/src/jdk/internal/dynalink/ChainedCallSite.java
@@ -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);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java b/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java
index b7edb9d..d687fd6 100644
--- a/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java
+++ b/nashorn/src/jdk/internal/dynalink/DefaultBootstrapper.java
@@ -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)));
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/DynamicLinker.java b/nashorn/src/jdk/internal/dynalink/DynamicLinker.java
index 155ff30..e7e58d2 100644
--- a/nashorn/src/jdk/internal/dynalink/DynamicLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/DynamicLinker.java
@@ -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.runtimeContextArgCount = runtimeContextArgCount;
         this.linkerServices = linkerServices;
+        this.prelinkFilter = prelinkFilter;
+        this.runtimeContextArgCount = runtimeContextArgCount;
         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
diff --git a/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java b/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java
index 72fbebe..af5eb11 100644
--- a/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java
+++ b/nashorn/src/jdk/internal/dynalink/DynamicLinkerFactory.java
@@ -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());
         }
     }
diff --git a/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java b/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java
new file mode 100644
index 0000000..8560d82
--- /dev/null
+++ b/nashorn/src/jdk/internal/dynalink/GuardedInvocationFilter.java
@@ -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);
+}
diff --git a/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java b/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java
index 7f1bbed..98541f2 100644
--- a/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java
+++ b/nashorn/src/jdk/internal/dynalink/MonomorphicCallSite.java
@@ -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);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java b/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
index 8a73af9..879a4b0 100644
--- a/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
+++ b/nashorn/src/jdk/internal/dynalink/NoSuchDynamicMethodException.java
@@ -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);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java b/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
index a6ef8c1..dab6cbf 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/AbstractJavaLinker.java
@@ -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,12 +285,12 @@
      * @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);
         }
         final Member member = (Member)m;
-        return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName());
+        return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName(), m instanceof Constructor);
     }
 
     /**
@@ -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,31 @@
         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) {
+    SingleDynamicMethod getConstructorMethod(final String signature) {
+        return null;
+    }
+
+    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 +410,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 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 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 SingleDynamicMethod getExplicitSignatureDynamicMethod(final String fullName,
+            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
@@ -433,23 +437,33 @@
         // for performance reasons.
 
         // Is the method name lexically of the form "name(types)"?
-        final int lastChar = methodName.length() - 1;
-        if(methodName.charAt(lastChar) != ')') {
+        final int lastChar = fullName.length() - 1;
+        if(fullName.charAt(lastChar) != ')') {
             return null;
         }
-        final int openBrace = methodName.indexOf('(');
+        final int openBrace = fullName.indexOf('(');
         if(openBrace == -1) {
             return null;
         }
 
+        final String name = fullName.substring(0, openBrace);
+        final String signature = fullName.substring(openBrace + 1, lastChar);
+
         // Find an existing method for the "name" part
-        final DynamicMethod simpleNamedMethod = methodsMap.get(methodName.substring(0, openBrace));
+        final DynamicMethod simpleNamedMethod = methodsMap.get(name);
         if(simpleNamedMethod == null) {
+            // explicit signature constructor access
+            // Java.type("java.awt.Color")["(int,int,int)"]
+            // will get Color(int,int,int) constructor of Color class.
+            if (name.isEmpty()) {
+                return getConstructorMethod(signature);
+            }
+
             return null;
         }
 
         // Try to get a narrowed dynamic method for the explicit parameter types.
-        return simpleNamedMethod.getMethodForExactParamTypes(methodName.substring(openBrace + 1, lastChar));
+        return simpleNamedMethod.getMethodForExactParamTypes(signature);
     }
 
     private static final MethodHandle IS_METHOD_HANDLE_NOT_NULL = Guards.isNotNull().asType(MethodType.methodType(
@@ -457,14 +471,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 +491,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 +513,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 +561,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 +584,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 +596,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 +635,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 +645,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 +665,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 +692,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 +721,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 +730,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 +769,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 +783,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 +807,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 +818,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 +840,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 +851,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;
         }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java b/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java
index 72beadf..21789e4 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/AccessibleMembersLookup.java
@@ -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
diff --git a/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java b/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java
index 39a03a8..e749c49 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/ApplicableOverloadedMethods.java
@@ -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;
             }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java b/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java
index fc54e35..754d88e 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/BeanIntrospector.java
@@ -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;
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java b/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java
index d0ad96b..f7f0c94 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/BeanLinker.java
@@ -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.");
         }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java b/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java
index e0c14b0..439c5a6 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/BeansLinker.java
@@ -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);
     }
 
@@ -169,12 +169,32 @@
     }
 
     /**
+     * Returns true if the object is a Dynalink Java constructor.
+     *
+     * @param obj the object we want to test for being a constructor
+     * @return true if it is a constructor, false otherwise.
+     */
+    public static boolean isDynamicConstructor(final Object obj) {
+        return obj instanceof DynamicMethod && ((DynamicMethod)obj).isConstructor();
+    }
+
+    /**
+     * Return the dynamic method of constructor of the given class and the given signature.
+     * @param clazz the class
+     * @param signature full signature of the constructor
+     * @return DynamicMethod for the constructor
+     */
+    public static Object getConstructorMethod(final Class<?> clazz, final String signature) {
+        return StaticClassLinker.getConstructorMethod(clazz, signature);
+    }
+
+    /**
      * Returns a collection of names of all readable instance properties of a class.
      * @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 +206,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 +219,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 +232,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 +241,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 +250,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();
diff --git a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java
index 466bafe..e4ada35 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDetector.java
@@ -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;
                 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
index 1e274d5..2896732 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/CallerSensitiveDynamicMethod.java
@@ -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())) {
@@ -155,4 +155,9 @@
         return StaticClassIntrospector.editConstructorMethodHandle(Lookup.unreflectConstructor(lookup,
                 (Constructor<?>)target));
     }
+
+    @Override
+    boolean isConstructor() {
+        return target instanceof Constructor;
+    }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java b/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java
index 360759f..49723a1 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/CheckRestrictedPackage.java
@@ -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;
diff --git a/nashorn/src/jdk/internal/dynalink/beans/ClassString.java b/nashorn/src/jdk/internal/dynalink/beans/ClassString.java
index 2afbdb4..00729cd 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/ClassString.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/ClassString.java
@@ -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();
         }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java
index 6beb92b..7b7a4d8 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethod.java
@@ -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;
     }
@@ -147,4 +147,13 @@
     public String toString() {
         return "[" + getClass().getName() + " " + getName() + "]";
     }
+
+    /**
+     * True if this method happens to be a constructor method.
+     *
+     * @return true if this represents a constructor.
+     */
+    boolean isConstructor() {
+        return false;
+    }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
index 32942b9..7067c2c 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/DynamicMethodLinker.java
@@ -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;
@@ -114,15 +114,30 @@
             return null;
         }
         final String operator = desc.getNameToken(CallSiteDescriptor.OPERATOR);
-        if(operator == "call") {
-            final MethodHandle invocation = ((DynamicMethod)receiver).getInvocation(
+        final DynamicMethod dynMethod = (DynamicMethod)receiver;
+        final boolean constructor = dynMethod.isConstructor();
+        final MethodHandle invocation;
+
+        if (operator == "call" && !constructor) {
+            invocation = dynMethod.getInvocation(
                     CallSiteDescriptorFactory.dropParameterTypes(desc, 0, 1), linkerServices);
-            if(invocation == null) {
+        } else if (operator == "new" && constructor) {
+            final MethodHandle ctorInvocation = dynMethod.getInvocation(desc, linkerServices);
+            if(ctorInvocation == null) {
                 return null;
             }
-            return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0,
-                    desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver));
+
+            // Insert null for StaticClass parameter
+            invocation = MethodHandles.insertArguments(ctorInvocation, 0, (Object)null);
+        } else {
+            return null;
         }
+
+        if (invocation != null) {
+            return new GuardedInvocation(MethodHandles.dropArguments(invocation, 0,
+                desc.getMethodType().parameterType(0)), Guards.getIdentityGuard(receiver));
+        }
+
         return null;
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java b/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java
index 4ac5dea..29c98d0 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/FacetIntrospector.java
@@ -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));
     }
 
diff --git a/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java b/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java
index f2c76db..9bacd21 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/GuardedInvocationComponent.java
@@ -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);
         }
 
diff --git a/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java b/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java
index 3ee8e41..8b5e321 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/MaximallySpecific.java
@@ -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);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
index 8ce41bc..83156e3 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/OverloadedDynamicMethod.java
@@ -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;
             }
@@ -237,12 +236,18 @@
         return false;
     }
 
+    @Override
+    public boolean isConstructor() {
+        assert !methods.isEmpty();
+        return methods.getFirst().isConstructor();
+    }
+
     ClassLoader getClassLoader() {
         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 +293,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 +308,12 @@
      *
      * @param method a method to add
      */
-    public void addMethod(SingleDynamicMethod method) {
+    public void addMethod(final SingleDynamicMethod method) {
+        assert constructorFlagConsistent(method);
         methods.add(method);
     }
+
+    private boolean constructorFlagConsistent(final SingleDynamicMethod method) {
+        return methods.isEmpty()? true : (methods.getFirst().isConstructor() == method.isConstructor());
+    }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java b/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java
index f711489..70ec495 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/OverloadedMethod.java
@@ -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,8 +151,8 @@
             MethodHandle.class, Object[].class);
 
     @SuppressWarnings("unused")
-    private MethodHandle selectMethod(Object[] args) throws NoSuchMethodException {
-        final Class<?>[] argTypes = new Class[args.length];
+    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];
             argTypes[i] = arg == null ? ClassString.NULL_CLASS : arg.getClass();
@@ -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;
+    }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
index 9d4d696..f4a8b0a 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/SimpleDynamicMethod.java
@@ -98,6 +98,7 @@
  */
 class SimpleDynamicMethod extends SingleDynamicMethod {
     private final MethodHandle target;
+    private final boolean constructor;
 
     /**
      * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle
@@ -107,12 +108,26 @@
      * @param clazz the class declaring the method
      * @param name the simple name of the method
      */
-    SimpleDynamicMethod(MethodHandle target, Class<?> clazz, String name) {
-        super(getName(target, clazz, name));
-        this.target = target;
+    SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name) {
+        this(target, clazz, name, false);
     }
 
-    private static String getName(MethodHandle target, Class<?> clazz, String name) {
+    /**
+     * Creates a new simple dynamic method, with a name constructed from the class name, method name, and handle
+     * signature.
+     *
+     * @param target the target method handle
+     * @param clazz the class declaring the method
+     * @param name the simple name of the method
+     * @param constructor does this represent a constructor?
+     */
+    SimpleDynamicMethod(final MethodHandle target, final Class<?> clazz, final String name, final boolean constructor) {
+        super(getName(target, clazz, name));
+        this.target = target;
+        this.constructor = constructor;
+    }
+
+    private static String getName(final MethodHandle target, final Class<?> clazz, final String name) {
         return getMethodNameWithSignature(target.type(), getClassAndMethodName(clazz, name));
     }
 
@@ -127,7 +142,12 @@
     }
 
     @Override
-    MethodHandle getTarget(Lookup lookup) {
+    MethodHandle getTarget(final Lookup lookup) {
         return target;
     }
+
+    @Override
+    boolean isConstructor() {
+        return constructor;
+    }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java b/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
index 6b55d81..79dca9a 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/SingleDynamicMethod.java
@@ -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());
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java b/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java
index 5008c21..f70f264 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/StaticClass.java
@@ -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);
     }
 
diff --git a/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java b/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java
index 62ce41a..8a07c1f 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/StaticClassIntrospector.java
@@ -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);
     }
 
diff --git a/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java b/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java
index 5f80cae..ab9c884 100644
--- a/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/beans/StaticClassLinker.java
@@ -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) {
@@ -160,22 +160,31 @@
             }
             return null;
         }
+
+        @Override
+        SingleDynamicMethod getConstructorMethod(final String signature) {
+            return constructor != null? constructor.getMethodForExactParamTypes(signature) : null;
+        }
     }
 
-    static Collection<String> getReadableStaticPropertyNames(Class<?> clazz) {
+    static Object getConstructorMethod(final Class<?> clazz, final String signature) {
+        return linkers.get(clazz).getConstructorMethod(signature);
+    }
+
+    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 +194,7 @@
     }
 
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return type == StaticClass.class;
     }
 
@@ -201,7 +210,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;
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java b/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java
index 26a741e..00ee9dc 100644
--- a/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java
+++ b/nashorn/src/jdk/internal/dynalink/linker/GuardedInvocation.java
@@ -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) {
+    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 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(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.switchPoint = switchPoint;
+        this.switchPoints = switchPoint == null ? null : new SwitchPoint[] { switchPoint };
+        this.exception = exception;
     }
 
     /**
-     * Creates a new guarded invocation.
+     * 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 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(MethodHandle invocation, SwitchPoint switchPoint, MethodHandle guard) {
-        this(invocation, guard, switchPoint);
+    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 == null ? null : switchPoints.clone();
+        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());
         }
diff --git a/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java b/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
index 9baed7c..88357ff 100644
--- a/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
+++ b/nashorn/src/jdk/internal/dynalink/linker/GuardedTypeConversion.java
@@ -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;
     }
diff --git a/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java
index 2cd0d0f..82a3619 100644
--- a/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/linker/GuardingDynamicLinker.java
@@ -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.invoke.MethodType)}.
      * @throws Exception if the operation fails for whatever reason
      */
     public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices)
diff --git a/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java b/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java
index 1a82a4f..63501cd 100644
--- a/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java
+++ b/nashorn/src/jdk/internal/dynalink/linker/LinkRequest.java
@@ -101,6 +101,17 @@
     public CallSiteDescriptor getCallSiteDescriptor();
 
     /**
+     * Returns the call site token for the call site being linked. This token is an opaque object that is guaranteed to
+     * have different identity for different call sites, and is also guaranteed to not become weakly reachable before
+     * the call site does and to become weakly reachable some time after the call site does. This makes it ideal as a
+     * candidate for a key in a weak hash map in which a linker might want to keep per-call site linking state (usually
+     * profiling information).
+     *
+     * @return the call site token for the call site being linked.
+     */
+    public Object getCallSiteToken();
+
+    /**
      * Returns the arguments for the invocation being linked. The returned array is a clone; modifications to it won't
      * affect the arguments in this request.
      *
@@ -116,6 +127,17 @@
     public Object getReceiver();
 
     /**
+     * Returns the number of times this callsite has been linked/relinked. This can be useful if you want to
+     * change e.g. exception based relinking to guard based relinking. It's probably not a good idea to keep,
+     * for example, expensive exception throwing relinkage based on failed type checks/ClassCastException in
+     * a nested callsite tree where the exception is thrown repeatedly for the common case. There it would be
+     * much more performant to use exact type guards instead.
+     *
+     * @return link count for call site
+     */
+    public int getLinkCount();
+
+    /**
      * Returns true if the call site is considered unstable, that is, it has been relinked more times than was
      * specified in {@link DynamicLinkerFactory#setUnstableRelinkThreshold(int)}. Linkers should use this as a
      * hint to prefer producing linkage that is more stable (its guard fails less frequently), even if that assumption
diff --git a/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java b/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java
index deaf820..9e35d7f 100644
--- a/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java
+++ b/nashorn/src/jdk/internal/dynalink/linker/LinkerServices.java
@@ -87,7 +87,9 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import jdk.internal.dynalink.DynamicLinker;
+import jdk.internal.dynalink.DynamicLinkerFactory;
 import jdk.internal.dynalink.linker.ConversionComparator.Comparison;
+import jdk.internal.dynalink.support.TypeUtilities;
 
 /**
  * Interface for services provided to {@link GuardingDynamicLinker} instances by the {@link DynamicLinker} that owns
@@ -103,18 +105,34 @@
      * parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive,
      * wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions,
      * it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
-     * provided by {@link GuardingTypeConverterFactory} implementations. It doesn't use language-specific conversions on
-     * the return type.
+     * provided by {@link GuardingTypeConverterFactory} implementations.
      *
      * @param handle target method handle
      * @param fromType the types of source arguments
-     * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and
-     * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
-     * {@link GuardingTypeConverterFactory} produced type converters as filters.
+     * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)},
+     * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)}, and
+     * {@link MethodHandles#filterReturnValue(MethodHandle, MethodHandle)} with
+     * {@link GuardingTypeConverterFactory}-produced type converters as filters.
      */
     public MethodHandle asType(MethodHandle handle, MethodType fromType);
 
     /**
+     * Similar to {@link #asType(MethodHandle, MethodType)} except it only converts the return type of the method handle
+     * when it can be done using a conversion that loses neither precision nor magnitude, otherwise it leaves it
+     * unchanged. The idea is that other conversions should not be performed by individual linkers, but instead the
+     * {@link DynamicLinkerFactory#setPrelinkFilter(jdk.internal.dynalink.GuardedInvocationFilter) pre-link filter of
+     * the dynamic linker} should implement the strategy of dealing with potentially lossy return type conversions in a
+     * manner specific to the language runtime.
+     *
+     * @param handle target method handle
+     * @param fromType the types of source arguments
+     * @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)}, and
+     * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
+     * {@link GuardingTypeConverterFactory}-produced type converters as filters.
+     */
+    public MethodHandle asTypeLosslessReturn(MethodHandle handle, MethodType fromType);
+
+    /**
      * Given a source and target type, returns a method handle that converts between them. Never returns null; in worst
      * case it will return an identity conversion (that might fail for some values at runtime). You rarely need to use
      * this method directly; you should mostly rely on {@link #asType(MethodHandle, MethodType)} instead. You really
@@ -161,4 +179,23 @@
      * conversion.
      */
     public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2);
+
+    /**
+     * If we could just use Java 8 constructs, then {@code asTypeSafeReturn} would be a method with default
+     * implementation. Since we can't do that, we extract common default implementations into this static class.
+     */
+    public static class Implementation {
+        /**
+         * Default implementation for {@link LinkerServices#asTypeLosslessReturn(MethodHandle, MethodType)}.
+         * @param linkerServices the linker services that delegates to this implementation
+         * @param handle the passed handle
+         * @param fromType the passed type
+         * @return the converted method handle, as per the {@code asTypeSafeReturn} semantics.
+         */
+        public static MethodHandle asTypeLosslessReturn(final LinkerServices linkerServices, final MethodHandle handle, final MethodType fromType) {
+            final Class<?> handleReturnType = handle.type().returnType();
+            return linkerServices.asType(handle, TypeUtilities.isConvertibleWithoutLoss(handleReturnType, fromType.returnType()) ?
+                    fromType : fromType.changeReturnType(handleReturnType));
+        }
+    }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
index 3161cf5..6bcbbbb 100644
--- a/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
+++ b/nashorn/src/jdk/internal/dynalink/support/AbstractCallSiteDescriptor.java
@@ -106,7 +106,7 @@
    }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         return obj instanceof CallSiteDescriptor && equals((CallSiteDescriptor)obj);
     }
 
@@ -115,7 +115,7 @@
      * @param csd the other call site descriptor.
      * @return true if they are equal.
      */
-    public boolean equals(CallSiteDescriptor csd) {
+    public boolean equals(final CallSiteDescriptor csd) {
         if(csd == null) {
             return false;
         }
@@ -165,7 +165,7 @@
         return l +  c - 1;
     }
 
-    private StringBuilder appendName(StringBuilder b) {
+    private StringBuilder appendName(final StringBuilder b) {
         b.append(getNameToken(0));
         final int c = getNameTokenCount();
         for(int i = 1; i < c; ++i) {
@@ -174,7 +174,7 @@
         return b;
     }
 
-    private static boolean lookupsEqual(Lookup l1, Lookup l2) {
+    private static boolean lookupsEqual(final Lookup l1, final Lookup l2) {
         if(l1 == l2) {
             return true;
         }
diff --git a/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java b/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
index c05d35e..e01880e 100644
--- a/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
+++ b/nashorn/src/jdk/internal/dynalink/support/AbstractRelinkableCallSite.java
@@ -100,7 +100,7 @@
      * Creates a new relinkable call site.
      * @param descriptor the descriptor for this call site
      */
-    protected AbstractRelinkableCallSite(CallSiteDescriptor descriptor) {
+    protected AbstractRelinkableCallSite(final CallSiteDescriptor descriptor) {
         super(descriptor.getMethodType());
         this.descriptor = descriptor;
     }
@@ -111,7 +111,7 @@
     }
 
     @Override
-    public void initialize(MethodHandle relinkAndInvoke) {
+    public void initialize(final MethodHandle relinkAndInvoke) {
         setTarget(relinkAndInvoke);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java b/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java
index 2909365..ba31861 100644
--- a/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java
+++ b/nashorn/src/jdk/internal/dynalink/support/AutoDiscovery.java
@@ -116,14 +116,14 @@
      * @return a list of guarding dynamic linkers available through the specified class loader. Can be zero-length list
      * but not null.
      */
-    public static List<GuardingDynamicLinker> loadLinkers(ClassLoader cl) {
+    public static List<GuardingDynamicLinker> loadLinkers(final ClassLoader cl) {
         return getLinkers(ServiceLoader.load(GuardingDynamicLinker.class, cl));
     }
 
     /**
      * I can't believe there's no Collections API for making a List given an Iterator...
      */
-    private static <T> List<T> getLinkers(ServiceLoader<T> loader) {
+    private static <T> List<T> getLinkers(final ServiceLoader<T> loader) {
         final List<T> list = new LinkedList<>();
         for(final T linker: loader) {
             list.add(linker);
diff --git a/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java
index 7a2700e..07abb6c 100644
--- a/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/support/BottomGuardingDynamicLinker.java
@@ -105,12 +105,12 @@
     }
 
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return false;
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) {
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) {
         return null;
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java b/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
index b0039d2..9cbd5f0 100644
--- a/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
+++ b/nashorn/src/jdk/internal/dynalink/support/CallSiteDescriptorFactory.java
@@ -86,6 +86,7 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
 import java.lang.invoke.MethodType;
+import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.util.Arrays;
 import java.util.Collections;
@@ -103,7 +104,7 @@
  * @author Attila Szegedi
  */
 public class CallSiteDescriptorFactory {
-    private static final WeakHashMap<CallSiteDescriptor, WeakReference<CallSiteDescriptor>> publicDescs =
+    private static final WeakHashMap<CallSiteDescriptor, Reference<CallSiteDescriptor>> publicDescs =
             new WeakHashMap<>();
 
 
@@ -121,7 +122,7 @@
      * @return a call site descriptor representing the input. Note that although the method name is "create", it will
      * in fact return a weakly-referenced canonical instance.
      */
-    public static CallSiteDescriptor create(Lookup lookup, String name, MethodType methodType) {
+    public static CallSiteDescriptor create(final Lookup lookup, final String name, final MethodType methodType) {
         name.getClass(); // NPE check
         methodType.getClass(); // NPE check
         lookup.getClass(); // NPE check
@@ -134,19 +135,28 @@
 
     static CallSiteDescriptor getCanonicalPublicDescriptor(final CallSiteDescriptor desc) {
         synchronized(publicDescs) {
-            final WeakReference<CallSiteDescriptor> ref = publicDescs.get(desc);
+            final Reference<CallSiteDescriptor> ref = publicDescs.get(desc);
             if(ref != null) {
                 final CallSiteDescriptor canonical = ref.get();
                 if(canonical != null) {
                     return canonical;
                 }
             }
-            publicDescs.put(desc, new WeakReference<>(desc));
+            publicDescs.put(desc, createReference(desc));
         }
         return desc;
     }
 
-    private static CallSiteDescriptor createPublicCallSiteDescriptor(String[] tokenizedName, MethodType methodType) {
+    /**
+     * Override this to use a different kind of references for the cache
+     * @param desc desc
+     * @return reference
+     */
+    protected static Reference<CallSiteDescriptor> createReference(final CallSiteDescriptor desc) {
+        return new WeakReference<>(desc);
+    }
+
+    private static CallSiteDescriptor createPublicCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) {
         final int l = tokenizedName.length;
         if(l > 0 && tokenizedName[0] == "dyn") {
             if(l == 2) {
@@ -158,7 +168,7 @@
         return new DefaultCallSiteDescriptor(tokenizedName, methodType);
     }
 
-    private static boolean isPublicLookup(Lookup lookup) {
+    private static boolean isPublicLookup(final Lookup lookup) {
         return lookup == MethodHandles.publicLookup();
     }
 
@@ -169,7 +179,7 @@
      * @param name the composite name consisting of colon-separated, possibly mangled tokens.
      * @return an array of tokens
      */
-    public static String[] tokenizeName(String name) {
+    public static String[] tokenizeName(final String name) {
         final StringTokenizer tok = new StringTokenizer(name, CallSiteDescriptor.TOKEN_DELIMITER);
         final String[] tokens = new String[tok.countTokens()];
         for(int i = 0; i < tokens.length; ++i) {
@@ -188,7 +198,7 @@
      * @param desc the call site descriptor with the operation
      * @return a list of tokens
      */
-    public static List<String> tokenizeOperators(CallSiteDescriptor desc) {
+    public static List<String> tokenizeOperators(final CallSiteDescriptor desc) {
         final String ops = desc.getNameToken(CallSiteDescriptor.OPERATOR);
         final StringTokenizer tok = new StringTokenizer(ops, CallSiteDescriptor.OPERATOR_DELIMITER);
         final int count = tok.countTokens();
@@ -210,7 +220,7 @@
      * @param end index of the first parameter to not remove
      * @return a new call site descriptor with modified method type
      */
-    public static CallSiteDescriptor dropParameterTypes(CallSiteDescriptor desc, int start, int end) {
+    public static CallSiteDescriptor dropParameterTypes(final CallSiteDescriptor desc, final int start, final int end) {
         return desc.changeMethodType(desc.getMethodType().dropParameterTypes(start, end));
     }
 
@@ -222,7 +232,7 @@
      * @param nptype the new parameter type
      * @return a new call site descriptor with modified method type
      */
-    public static CallSiteDescriptor changeParameterType(CallSiteDescriptor desc, int num, Class<?> nptype) {
+    public static CallSiteDescriptor changeParameterType(final CallSiteDescriptor desc, final int num, final Class<?> nptype) {
         return desc.changeMethodType(desc.getMethodType().changeParameterType(num, nptype));
     }
 
@@ -233,7 +243,7 @@
      * @param nrtype the new return type
      * @return a new call site descriptor with modified method type
      */
-    public static CallSiteDescriptor changeReturnType(CallSiteDescriptor desc, Class<?> nrtype) {
+    public static CallSiteDescriptor changeReturnType(final CallSiteDescriptor desc, final Class<?> nrtype) {
         return desc.changeMethodType(desc.getMethodType().changeReturnType(nrtype));
     }
 
@@ -245,7 +255,7 @@
      * @param ptypesToInsert the new types to insert
      * @return a new call site descriptor with modified method type
      */
-    public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, Class<?>... ptypesToInsert) {
+    public static CallSiteDescriptor insertParameterTypes(final CallSiteDescriptor desc, final int num, final Class<?>... ptypesToInsert) {
         return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
     }
 
@@ -257,7 +267,7 @@
      * @param ptypesToInsert the new types to insert
      * @return a new call site descriptor with modified method type
      */
-    public static CallSiteDescriptor insertParameterTypes(CallSiteDescriptor desc, int num, List<Class<?>> ptypesToInsert) {
+    public static CallSiteDescriptor insertParameterTypes(final CallSiteDescriptor desc, final int num, final List<Class<?>> ptypesToInsert) {
         return desc.changeMethodType(desc.getMethodType().insertParameterTypes(num, ptypesToInsert));
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/ClassMap.java b/nashorn/src/jdk/internal/dynalink/support/ClassMap.java
index d85b21d..758349b 100644
--- a/nashorn/src/jdk/internal/dynalink/support/ClassMap.java
+++ b/nashorn/src/jdk/internal/dynalink/support/ClassMap.java
@@ -110,7 +110,7 @@
      *
      * @param classLoader the classloader that determines strong referenceability.
      */
-    protected ClassMap(ClassLoader classLoader) {
+    protected ClassMap(final ClassLoader classLoader) {
         this.classLoader = classLoader;
     }
 
diff --git a/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
index 44f5c4b..007ab98 100644
--- a/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/support/CompositeGuardingDynamicLinker.java
@@ -109,16 +109,16 @@
      *
      * @param linkers a list of component linkers.
      */
-    public CompositeGuardingDynamicLinker(Iterable<? extends GuardingDynamicLinker> linkers) {
+    public CompositeGuardingDynamicLinker(final Iterable<? extends GuardingDynamicLinker> linkers) {
         final List<GuardingDynamicLinker> l = new LinkedList<>();
-        for(GuardingDynamicLinker linker: linkers) {
+        for(final GuardingDynamicLinker linker: linkers) {
             l.add(linker);
         }
         this.linkers = l.toArray(new GuardingDynamicLinker[l.size()]);
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices)
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
             throws Exception {
         for(final GuardingDynamicLinker linker: linkers) {
             final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
diff --git a/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java b/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
index 180ab0c..d1ff028 100644
--- a/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
+++ b/nashorn/src/jdk/internal/dynalink/support/CompositeTypeBasedGuardingDynamicLinker.java
@@ -111,8 +111,8 @@
         private final TypeBasedGuardingDynamicLinker[] linkers;
         private final List<TypeBasedGuardingDynamicLinker>[] singletonLinkers;
 
-        @SuppressWarnings("unchecked")
-        ClassToLinker(TypeBasedGuardingDynamicLinker[] linkers) {
+        @SuppressWarnings({"unchecked", "rawtypes"})
+        ClassToLinker(final TypeBasedGuardingDynamicLinker[] linkers) {
             this.linkers = linkers;
             singletonLinkers = new List[linkers.length];
             for(int i = 0; i < linkers.length; ++i) {
@@ -120,8 +120,9 @@
             }
         }
 
+        @SuppressWarnings("fallthrough")
         @Override
-        protected List<TypeBasedGuardingDynamicLinker> computeValue(Class<?> clazz) {
+        protected List<TypeBasedGuardingDynamicLinker> computeValue(final Class<?> clazz) {
             List<TypeBasedGuardingDynamicLinker> list = NO_LINKER;
             for(int i = 0; i < linkers.length; ++i) {
                 final TypeBasedGuardingDynamicLinker linker = linkers[i];
@@ -134,7 +135,6 @@
                         case 1: {
                             list = new LinkedList<>(list);
                         }
-                        //$FALL-THROUGH$
                         default: {
                             list.add(linker);
                         }
@@ -152,27 +152,27 @@
      *
      * @param linkers the component linkers
      */
-    public CompositeTypeBasedGuardingDynamicLinker(Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
+    public CompositeTypeBasedGuardingDynamicLinker(final Iterable<? extends TypeBasedGuardingDynamicLinker> linkers) {
         final List<TypeBasedGuardingDynamicLinker> l = new LinkedList<>();
-        for(TypeBasedGuardingDynamicLinker linker: linkers) {
+        for(final TypeBasedGuardingDynamicLinker linker: linkers) {
             l.add(linker);
         }
         this.classToLinker = new ClassToLinker(l.toArray(new TypeBasedGuardingDynamicLinker[l.size()]));
     }
 
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return !classToLinker.get(type).isEmpty();
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, final LinkerServices linkerServices)
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices)
             throws Exception {
         final Object obj = linkRequest.getReceiver();
         if(obj == null) {
             return null;
         }
-        for(TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
+        for(final TypeBasedGuardingDynamicLinker linker: classToLinker.get(obj.getClass())) {
             final GuardedInvocation invocation = linker.getGuardedInvocation(linkRequest, linkerServices);
             if(invocation != null) {
                 return invocation;
@@ -189,10 +189,10 @@
      * @param linkers the list of linkers to optimize
      * @return the optimized list
      */
-    public static List<GuardingDynamicLinker> optimize(Iterable<? extends GuardingDynamicLinker> linkers) {
+    public static List<GuardingDynamicLinker> optimize(final Iterable<? extends GuardingDynamicLinker> linkers) {
         final List<GuardingDynamicLinker> llinkers = new LinkedList<>();
         final List<TypeBasedGuardingDynamicLinker> tblinkers = new LinkedList<>();
-        for(GuardingDynamicLinker linker: linkers) {
+        for(final GuardingDynamicLinker linker: linkers) {
             if(linker instanceof TypeBasedGuardingDynamicLinker) {
                 tblinkers.add((TypeBasedGuardingDynamicLinker)linker);
             } else {
@@ -204,8 +204,8 @@
         return llinkers;
     }
 
-    private static void addTypeBased(List<GuardingDynamicLinker> llinkers,
-            List<TypeBasedGuardingDynamicLinker> tblinkers) {
+    private static void addTypeBased(final List<GuardingDynamicLinker> llinkers,
+            final List<TypeBasedGuardingDynamicLinker> tblinkers) {
         switch(tblinkers.size()) {
             case 0: {
                 break;
diff --git a/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
index 46d4fc8..878d9aa 100644
--- a/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
+++ b/nashorn/src/jdk/internal/dynalink/support/DefaultCallSiteDescriptor.java
@@ -98,7 +98,7 @@
     private final String[] tokenizedName;
     private final MethodType methodType;
 
-    DefaultCallSiteDescriptor(String[] tokenizedName, MethodType methodType) {
+    DefaultCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType) {
         this.tokenizedName = tokenizedName;
         this.methodType = methodType;
     }
@@ -109,10 +109,10 @@
     }
 
     @Override
-    public String getNameToken(int i) {
+    public String getNameToken(final int i) {
         try {
             return tokenizedName[i];
-        } catch(ArrayIndexOutOfBoundsException e) {
+        } catch(final ArrayIndexOutOfBoundsException e) {
             throw new IllegalArgumentException(e.getMessage());
         }
     }
@@ -127,7 +127,7 @@
     }
 
     @Override
-    public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+    public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
         return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new DefaultCallSiteDescriptor(tokenizedName,
                 newMethodType));
     }
diff --git a/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java b/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java
new file mode 100644
index 0000000..ad9679f
--- /dev/null
+++ b/nashorn/src/jdk/internal/dynalink/support/DefaultPrelinkFilter.java
@@ -0,0 +1,99 @@
+/*
+ * 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.support;
+
+import jdk.internal.dynalink.GuardedInvocationFilter;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+
+/**
+ * Default filter for guarded invocation pre link filtering
+ */
+public class DefaultPrelinkFilter implements GuardedInvocationFilter {
+    @Override
+    public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) {
+        return inv.asType(linkerServices, request.getCallSiteDescriptor().getMethodType());
+    }
+}
diff --git a/nashorn/src/jdk/internal/dynalink/support/Guards.java b/nashorn/src/jdk/internal/dynalink/support/Guards.java
index 42aa675..02f3045 100644
--- a/nashorn/src/jdk/internal/dynalink/support/Guards.java
+++ b/nashorn/src/jdk/internal/dynalink/support/Guards.java
@@ -113,7 +113,7 @@
      * @return a method handle testing whether its first argument is of the specified class.
      */
     @SuppressWarnings("boxing")
-    public static MethodHandle isOfClass(Class<?> clazz, MethodType type) {
+    public static MethodHandle isOfClass(final Class<?> clazz, final MethodType type) {
         final Class<?> declaredType = type.parameterType(0);
         if(clazz == declaredType) {
             LOG.log(Level.WARNING, "isOfClassGuardAlwaysTrue", new Object[] { clazz.getName(), 0, type, DynamicLinker.getLinkedCallSiteLocation() });
@@ -135,7 +135,7 @@
      * @param type the method type
      * @return a method handle testing whether its first argument is of the specified class or subclass.
      */
-    public static MethodHandle isInstance(Class<?> clazz, MethodType type) {
+    public static MethodHandle isInstance(final Class<?> clazz, final MethodType type) {
         return isInstance(clazz, 0, type);
     }
 
@@ -150,7 +150,7 @@
      * @return a method handle testing whether its first argument is of the specified class or subclass.
      */
     @SuppressWarnings("boxing")
-    public static MethodHandle isInstance(Class<?> clazz, int pos, MethodType type) {
+    public static MethodHandle isInstance(final Class<?> clazz, final int pos, final MethodType type) {
         final Class<?> declaredType = type.parameterType(pos);
         if(clazz.isAssignableFrom(declaredType)) {
             LOG.log(Level.WARNING, "isInstanceGuardAlwaysTrue", new Object[] { clazz.getName(), pos, type, DynamicLinker.getLinkedCallSiteLocation() });
@@ -172,7 +172,7 @@
      * the arguments are ignored.
      */
     @SuppressWarnings("boxing")
-    public static MethodHandle isArray(int pos, MethodType type) {
+    public static MethodHandle isArray(final int pos, final MethodType type) {
         final Class<?> declaredType = type.parameterType(pos);
         if(declaredType.isArray()) {
             LOG.log(Level.WARNING, "isArrayGuardAlwaysTrue", new Object[] { pos, type, DynamicLinker.getLinkedCallSiteLocation() });
@@ -193,7 +193,7 @@
      * @param referredLoader the referred class loader
      * @return true if it is safe to strongly reference the class
      */
-    public static boolean canReferenceDirectly(ClassLoader referrerLoader, final ClassLoader referredLoader) {
+    public static boolean canReferenceDirectly(final ClassLoader referrerLoader, final ClassLoader referredLoader) {
         if(referredLoader == null) {
             // Can always refer directly to a system class
             return true;
@@ -215,7 +215,7 @@
         return false;
     }
 
-    private static MethodHandle getClassBoundArgumentTest(MethodHandle test, Class<?> clazz, int pos, MethodType type) {
+    private static MethodHandle getClassBoundArgumentTest(final MethodHandle test, final Class<?> clazz, final int pos, final MethodType type) {
         // Bind the class to the first argument of the test
         return asType(test.bindTo(clazz), pos, type);
     }
@@ -227,7 +227,7 @@
      * @param type the type to adapt the method handle to
      * @return the adapted method handle
      */
-    public static MethodHandle asType(MethodHandle test, MethodType type) {
+    public static MethodHandle asType(final MethodHandle test, final MethodType type) {
         return test.asType(getTestType(test, type));
     }
 
@@ -239,16 +239,16 @@
      * @param type the type to adapt the method handle to
      * @return the adapted method handle
      */
-    public static MethodHandle asType(LinkerServices linkerServices, MethodHandle test, MethodType type) {
+    public static MethodHandle asType(final LinkerServices linkerServices, final MethodHandle test, final MethodType type) {
         return linkerServices.asType(test, getTestType(test, type));
     }
 
-    private static MethodType getTestType(MethodHandle test, MethodType type) {
+    private static MethodType getTestType(final MethodHandle test, final MethodType type) {
         return type.dropParameterTypes(test.type().parameterCount(),
                 type.parameterCount()).changeReturnType(boolean.class);
     }
 
-    private static MethodHandle asType(MethodHandle test, int pos, MethodType type) {
+    private static MethodHandle asType(final MethodHandle test, final int pos, final MethodType type) {
         assert test != null;
         assert type != null;
         assert type.parameterCount() > 0;
@@ -283,7 +283,7 @@
      * @param clazz the class to test for.
      * @return the desired guard method.
      */
-    public static MethodHandle getClassGuard(Class<?> clazz) {
+    public static MethodHandle getClassGuard(final Class<?> clazz) {
         return IS_OF_CLASS.bindTo(clazz);
     }
 
@@ -292,7 +292,7 @@
      * @param clazz the class to test for.
      * @return the desired guard method.
      */
-    public static MethodHandle getInstanceOfGuard(Class<?> clazz) {
+    public static MethodHandle getInstanceOfGuard(final Class<?> clazz) {
         return IS_INSTANCE.bindTo(clazz);
     }
 
@@ -301,7 +301,7 @@
      * @param obj the object used as referential identity test
      * @return the desired guard method.
      */
-    public static MethodHandle getIdentityGuard(Object obj) {
+    public static MethodHandle getIdentityGuard(final Object obj) {
         return IS_IDENTICAL.bindTo(obj);
     }
 
@@ -322,39 +322,39 @@
     }
 
     @SuppressWarnings("unused")
-    private static boolean isNull(Object obj) {
+    private static boolean isNull(final Object obj) {
         return obj == null;
     }
 
     @SuppressWarnings("unused")
-    private static boolean isNotNull(Object obj) {
+    private static boolean isNotNull(final Object obj) {
         return obj != null;
     }
 
     @SuppressWarnings("unused")
-    private static boolean isArray(Object o) {
+    private static boolean isArray(final Object o) {
         return o != null && o.getClass().isArray();
     }
 
     @SuppressWarnings("unused")
-    private static boolean isOfClass(Class<?> c, Object o) {
+    private static boolean isOfClass(final Class<?> c, final Object o) {
         return o != null && o.getClass() == c;
     }
 
     @SuppressWarnings("unused")
-    private static boolean isIdentical(Object o1, Object o2) {
+    private static boolean isIdentical(final Object o1, final Object o2) {
         return o1 == o2;
     }
 
-    private static MethodHandle constantTrue(MethodType type) {
+    private static MethodHandle constantTrue(final MethodType type) {
         return constantBoolean(Boolean.TRUE, type);
     }
 
-    private static MethodHandle constantFalse(MethodType type) {
+    private static MethodHandle constantFalse(final MethodType type) {
         return constantBoolean(Boolean.FALSE, type);
     }
 
-    private static MethodHandle constantBoolean(Boolean value, MethodType type) {
+    private static MethodHandle constantBoolean(final Boolean value, final MethodType type) {
         return MethodHandles.permuteArguments(MethodHandles.constant(Boolean.TYPE, value),
                 type.changeReturnType(Boolean.TYPE));
     }
diff --git a/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java b/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java
index c2b0092..2d4c0b1 100644
--- a/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java
+++ b/nashorn/src/jdk/internal/dynalink/support/LinkRequestImpl.java
@@ -95,18 +95,24 @@
 public class LinkRequestImpl implements LinkRequest {
 
     private final CallSiteDescriptor callSiteDescriptor;
+    private final Object callSiteToken;
     private final Object[] arguments;
     private final boolean callSiteUnstable;
+    private final int linkCount;
 
     /**
      * Creates a new link request.
      *
      * @param callSiteDescriptor the descriptor for the call site being linked
+     * @param callSiteToken the opaque token for the call site being linked.
+     * @param linkCount how many times this callsite has been linked/relinked
      * @param callSiteUnstable true if the call site being linked is considered unstable
      * @param arguments the arguments for the invocation
      */
-    public LinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable, Object... arguments) {
+    public LinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken, final int linkCount, final boolean callSiteUnstable, final Object... arguments) {
         this.callSiteDescriptor = callSiteDescriptor;
+        this.callSiteToken = callSiteToken;
+        this.linkCount = linkCount;
         this.callSiteUnstable = callSiteUnstable;
         this.arguments = arguments;
     }
@@ -127,17 +133,27 @@
     }
 
     @Override
+    public Object getCallSiteToken() {
+        return callSiteToken;
+    }
+
+    @Override
     public boolean isCallSiteUnstable() {
         return callSiteUnstable;
     }
 
     @Override
+    public int getLinkCount() {
+        return linkCount;
+    }
+
+    @Override
     public LinkRequest withoutRuntimeContext() {
         return this;
     }
 
     @Override
-    public LinkRequest replaceArguments(CallSiteDescriptor newCallSiteDescriptor, Object[] newArguments) {
-        return new LinkRequestImpl(newCallSiteDescriptor, callSiteUnstable, newArguments);
+    public LinkRequest replaceArguments(final CallSiteDescriptor newCallSiteDescriptor, final Object[] newArguments) {
+        return new LinkRequestImpl(newCallSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, newArguments);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java b/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
index 3b8e7b4..38d93c8 100644
--- a/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
+++ b/nashorn/src/jdk/internal/dynalink/support/LinkerServicesImpl.java
@@ -117,27 +117,32 @@
     }
 
     @Override
-    public boolean canConvert(Class<?> from, Class<?> to) {
+    public boolean canConvert(final Class<?> from, final Class<?> to) {
         return typeConverterFactory.canConvert(from, to);
     }
 
     @Override
-    public MethodHandle asType(MethodHandle handle, MethodType fromType) {
+    public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
         return typeConverterFactory.asType(handle, fromType);
     }
 
     @Override
-    public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
+    public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
+        return Implementation.asTypeLosslessReturn(this, handle, fromType);
+    }
+
+    @Override
+    public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
         return typeConverterFactory.getTypeConverter(sourceType, targetType);
     }
 
     @Override
-    public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2) {
+    public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
         return typeConverterFactory.compareConversion(sourceType, targetType1, targetType2);
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest) throws Exception {
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest) throws Exception {
         final LinkRequest prevLinkRequest = threadLinkRequest.get();
         threadLinkRequest.set(linkRequest);
         try {
@@ -154,7 +159,7 @@
      * permission.
      */
     public static LinkRequest getCurrentLinkRequest() {
-        SecurityManager sm = System.getSecurityManager();
+        final SecurityManager sm = System.getSecurityManager();
         if(sm != null) {
             sm.checkPermission(GET_CURRENT_LINK_REQUEST);
         }
diff --git a/nashorn/src/jdk/internal/dynalink/support/Lookup.java b/nashorn/src/jdk/internal/dynalink/support/Lookup.java
index ba4ff77..ab64ebb 100644
--- a/nashorn/src/jdk/internal/dynalink/support/Lookup.java
+++ b/nashorn/src/jdk/internal/dynalink/support/Lookup.java
@@ -104,7 +104,7 @@
      *
      * @param lookup the {@link java.lang.invoke.MethodHandles.Lookup} it delegates to.
      */
-    public Lookup(MethodHandles.Lookup lookup) {
+    public Lookup(final MethodHandles.Lookup lookup) {
         this.lookup = lookup;
     }
 
@@ -120,7 +120,7 @@
      * @param m the method to unreflect
      * @return the unreflected method handle.
      */
-    public MethodHandle unreflect(Method m) {
+    public MethodHandle unreflect(final Method m) {
         return unreflect(lookup, m);
     }
 
@@ -132,10 +132,10 @@
      * @param m the method to unreflect
      * @return the unreflected method handle.
      */
-    public static MethodHandle unreflect(MethodHandles.Lookup lookup, Method m) {
+    public static MethodHandle unreflect(final MethodHandles.Lookup lookup, final Method m) {
         try {
             return lookup.unreflect(m);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect method " + m);
             ee.initCause(e);
             throw ee;
@@ -149,10 +149,10 @@
      * @param f the field for which a getter is unreflected
      * @return the unreflected field getter handle.
      */
-    public MethodHandle unreflectGetter(Field f) {
+    public MethodHandle unreflectGetter(final Field f) {
         try {
             return lookup.unreflectGetter(f);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect getter for field " + f);
             ee.initCause(e);
             throw ee;
@@ -171,15 +171,15 @@
      * @throws IllegalAccessError if the field is inaccessible.
      * @throws NoSuchFieldError if the field does not exist.
      */
-    public MethodHandle findGetter(Class<?>refc, String name, Class<?> type) {
+    public MethodHandle findGetter(final Class<?>refc, final String name, final Class<?> type) {
         try {
             return lookup.findGetter(refc, name, type);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to access getter for field " + refc.getName() +
                     "." + name + " of type " + type.getName());
             ee.initCause(e);
             throw ee;
-        } catch(NoSuchFieldException e) {
+        } catch(final NoSuchFieldException e) {
             final NoSuchFieldError ee = new NoSuchFieldError("Failed to find getter for field " + refc.getName() +
                     "." + name + " of type " + type.getName());
             ee.initCause(e);
@@ -194,10 +194,10 @@
      * @param f the field for which a setter is unreflected
      * @return the unreflected field setter handle.
      */
-    public MethodHandle unreflectSetter(Field f) {
+    public MethodHandle unreflectSetter(final Field f) {
         try {
             return lookup.unreflectSetter(f);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect setter for field " + f);
             ee.initCause(e);
             throw ee;
@@ -211,7 +211,7 @@
      * @param c the constructor to unreflect
      * @return the unreflected constructor handle.
      */
-    public MethodHandle unreflectConstructor(Constructor<?> c) {
+    public MethodHandle unreflectConstructor(final Constructor<?> c) {
         return unreflectConstructor(lookup, c);
     }
 
@@ -223,10 +223,10 @@
      * @param c the constructor to unreflect
      * @return the unreflected constructor handle.
      */
-    public static MethodHandle unreflectConstructor(MethodHandles.Lookup lookup, Constructor<?> c) {
+    public static MethodHandle unreflectConstructor(final MethodHandles.Lookup lookup, final Constructor<?> c) {
         try {
             return lookup.unreflectConstructor(c);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to unreflect constructor " + c);
             ee.initCause(e);
             throw ee;
@@ -244,15 +244,15 @@
      * @throws IllegalAccessError if the method is inaccessible.
      * @throws NoSuchMethodError if the method does not exist.
      */
-    public MethodHandle findSpecial(Class<?> declaringClass, String name, MethodType type) {
+    public MethodHandle findSpecial(final Class<?> declaringClass, final String name, final MethodType type) {
         try {
             return lookup.findSpecial(declaringClass, name, type, declaringClass);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to access special method " + methodDescription(
                     declaringClass, name, type));
             ee.initCause(e);
             throw ee;
-        } catch(NoSuchMethodException e) {
+        } catch(final NoSuchMethodException e) {
             final NoSuchMethodError ee = new NoSuchMethodError("Failed to find special method " + methodDescription(
                     declaringClass, name, type));
             ee.initCause(e);
@@ -260,7 +260,7 @@
         }
     }
 
-    private static String methodDescription(Class<?> declaringClass, String name, MethodType type) {
+    private static String methodDescription(final Class<?> declaringClass, final String name, final MethodType type) {
         return declaringClass.getName() + "#" + name + type;
     }
 
@@ -275,15 +275,15 @@
      * @throws IllegalAccessError if the method is inaccessible.
      * @throws NoSuchMethodError if the method does not exist.
      */
-    public MethodHandle findStatic(Class<?> declaringClass, String name, MethodType type) {
+    public MethodHandle findStatic(final Class<?> declaringClass, final String name, final MethodType type) {
         try {
             return lookup.findStatic(declaringClass, name, type);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to access static method " + methodDescription(
                     declaringClass, name, type));
             ee.initCause(e);
             throw ee;
-        } catch(NoSuchMethodException e) {
+        } catch(final NoSuchMethodException e) {
             final NoSuchMethodError ee = new NoSuchMethodError("Failed to find static method " + methodDescription(
                     declaringClass, name, type));
             ee.initCause(e);
@@ -302,15 +302,15 @@
      * @throws IllegalAccessError if the method is inaccessible.
      * @throws NoSuchMethodError if the method does not exist.
      */
-    public MethodHandle findVirtual(Class<?> declaringClass, String name, MethodType type) {
+    public MethodHandle findVirtual(final Class<?> declaringClass, final String name, final MethodType type) {
         try {
             return lookup.findVirtual(declaringClass, name, type);
-        } catch(IllegalAccessException e) {
+        } catch(final IllegalAccessException e) {
             final IllegalAccessError ee = new IllegalAccessError("Failed to access virtual method " + methodDescription(
                     declaringClass, name, type));
             ee.initCause(e);
             throw ee;
-        } catch(NoSuchMethodException e) {
+        } catch(final NoSuchMethodException e) {
             final NoSuchMethodError ee = new NoSuchMethodError("Failed to find virtual method " + methodDescription(
                     declaringClass, name, type));
             ee.initCause(e);
@@ -327,7 +327,7 @@
      * @param ptypes the parameter types of the method
      * @return the method handle for the method
      */
-    public static MethodHandle findOwnSpecial(MethodHandles.Lookup lookup, String name, Class<?> rtype, Class<?>... ptypes) {
+    public static MethodHandle findOwnSpecial(final MethodHandles.Lookup lookup, final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return new Lookup(lookup).findOwnSpecial(name, rtype, ptypes);
     }
 
@@ -341,7 +341,7 @@
      * @param ptypes the parameter types of the method
      * @return the method handle for the method
      */
-    public MethodHandle findOwnSpecial(String name, Class<?> rtype, Class<?>... ptypes) {
+    public MethodHandle findOwnSpecial(final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return findSpecial(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes));
     }
 
@@ -355,7 +355,7 @@
      * @param ptypes the parameter types of the method
      * @return the method handle for the method
      */
-    public static MethodHandle findOwnStatic(MethodHandles.Lookup lookup, String name, Class<?> rtype, Class<?>... ptypes) {
+    public static MethodHandle findOwnStatic(final MethodHandles.Lookup lookup, final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return new Lookup(lookup).findOwnStatic(name, rtype, ptypes);
     }
 
@@ -368,7 +368,7 @@
      * @param ptypes the parameter types of the method
      * @return the method handle for the method
      */
-    public MethodHandle findOwnStatic(String name, Class<?> rtype, Class<?>... ptypes) {
+    public MethodHandle findOwnStatic(final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return findStatic(lookup.lookupClass(), name, MethodType.methodType(rtype, ptypes));
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java
index bc5521b..e04321e 100644
--- a/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java
+++ b/nashorn/src/jdk/internal/dynalink/support/LookupCallSiteDescriptor.java
@@ -92,7 +92,7 @@
  * @author Attila Szegedi
  */
 class LookupCallSiteDescriptor extends DefaultCallSiteDescriptor {
-    private Lookup lookup;
+    private final Lookup lookup;
 
     /**
      * Create a new call site descriptor from explicit information.
@@ -100,7 +100,7 @@
      * @param methodType the method type
      * @param lookup the lookup
      */
-    LookupCallSiteDescriptor(String[] tokenizedName, MethodType methodType, Lookup lookup) {
+    LookupCallSiteDescriptor(final String[] tokenizedName, final MethodType methodType, final Lookup lookup) {
         super(tokenizedName, methodType);
         this.lookup = lookup;
     }
@@ -111,7 +111,7 @@
     }
 
     @Override
-    public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+    public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
         return new LookupCallSiteDescriptor(getTokenizedName(), newMethodType, lookup);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/NameCodec.java b/nashorn/src/jdk/internal/dynalink/support/NameCodec.java
index 1c7cd29..9a402a5 100644
--- a/nashorn/src/jdk/internal/dynalink/support/NameCodec.java
+++ b/nashorn/src/jdk/internal/dynalink/support/NameCodec.java
@@ -137,7 +137,7 @@
      * @param name the symbolic name to mangle
      * @return the mangled form of the symbolic name.
      */
-    public static String encode(String name) {
+    public static String encode(final String name) {
         final int l = name.length();
         if(l == 0) {
             return EMPTY_NAME;
@@ -176,7 +176,7 @@
      * @param name the symbolic name to demangle
      * @return the demangled form of the symbolic name.
      */
-    public static String decode(String name) {
+    public static String decode(final String name) {
         if(name.charAt(0) != ESCAPE_CHAR) {
             return name;
         }
@@ -184,11 +184,11 @@
         if(l == 2 && name.charAt(1) == EMPTY_CHAR) {
             return "";
         }
-        StringBuilder b = new StringBuilder(name.length());
+        final StringBuilder b = new StringBuilder(name.length());
         int lastEscape = -2;
         int lastBackslash = -1;
         for(;;) {
-            int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1);
+            final int nextBackslash = name.indexOf(ESCAPE_CHAR, lastBackslash + 1);
             if(nextBackslash == -1 || nextBackslash == l - 1) {
                 break;
             }
@@ -211,7 +211,7 @@
         return b.toString();
     }
 
-    private static void addEncoding(char from, char to) {
+    private static void addEncoding(final char from, final char to) {
         ENCODING[from - MIN_ENCODING] = to;
         DECODING[to - MIN_DECODING] = from;
     }
diff --git a/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java
index 71cbb1d..817df52 100644
--- a/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java
+++ b/nashorn/src/jdk/internal/dynalink/support/NamedDynCallSiteDescriptor.java
@@ -89,7 +89,7 @@
 class NamedDynCallSiteDescriptor extends UnnamedDynCallSiteDescriptor {
     private final String name;
 
-    NamedDynCallSiteDescriptor(String op, String name, MethodType methodType) {
+    NamedDynCallSiteDescriptor(final String op, final String name, final MethodType methodType) {
         super(op, methodType);
         this.name = name;
     }
@@ -100,7 +100,7 @@
     }
 
     @Override
-    public String getNameToken(int i) {
+    public String getNameToken(final int i) {
         switch(i) {
             case 0: return "dyn";
             case 1: return getOp();
@@ -110,7 +110,7 @@
     }
 
     @Override
-    public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+    public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
         return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new NamedDynCallSiteDescriptor(getOp(), name,
                 newMethodType));
     }
diff --git a/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java b/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java
index 03309a7..3f43621 100644
--- a/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java
+++ b/nashorn/src/jdk/internal/dynalink/support/RuntimeContextLinkRequestImpl.java
@@ -101,15 +101,17 @@
      * Creates a new link request.
      *
      * @param callSiteDescriptor the descriptor for the call site being linked
+     * @param callSiteToken the opaque token for the call site being linked.
      * @param arguments the arguments for the invocation
+     * @param linkCount number of times callsite has been linked/relinked
      * @param callSiteUnstable true if the call site being linked is considered unstable
      * @param runtimeContextArgCount the number of the leading arguments on the stack that represent the language
      * runtime specific context arguments.
      * @throws IllegalArgumentException if runtimeContextArgCount is less than 1.
      */
-    public RuntimeContextLinkRequestImpl(CallSiteDescriptor callSiteDescriptor, boolean callSiteUnstable,
-            Object[] arguments, int runtimeContextArgCount) {
-        super(callSiteDescriptor, callSiteUnstable, arguments);
+    public RuntimeContextLinkRequestImpl(final CallSiteDescriptor callSiteDescriptor, final Object callSiteToken,
+            final int linkCount, final boolean callSiteUnstable, final Object[] arguments, final int runtimeContextArgCount) {
+        super(callSiteDescriptor, callSiteToken, linkCount, callSiteUnstable, arguments);
         if(runtimeContextArgCount < 1) {
             throw new IllegalArgumentException("runtimeContextArgCount < 1");
         }
@@ -121,14 +123,14 @@
         if(contextStrippedRequest == null) {
             contextStrippedRequest =
                     new LinkRequestImpl(CallSiteDescriptorFactory.dropParameterTypes(getCallSiteDescriptor(), 1,
-                            runtimeContextArgCount + 1), isCallSiteUnstable(), getTruncatedArguments());
+                            runtimeContextArgCount + 1), getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), getTruncatedArguments());
         }
         return contextStrippedRequest;
     }
 
     @Override
-    public LinkRequest replaceArguments(CallSiteDescriptor callSiteDescriptor, Object[] arguments) {
-        return new RuntimeContextLinkRequestImpl(callSiteDescriptor, isCallSiteUnstable(), arguments,
+    public LinkRequest replaceArguments(final CallSiteDescriptor callSiteDescriptor, final Object[] arguments) {
+        return new RuntimeContextLinkRequestImpl(callSiteDescriptor, getCallSiteToken(), getLinkCount(), isCallSiteUnstable(), arguments,
                 runtimeContextArgCount);
     }
 
diff --git a/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java b/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java
index 436acad..79f6549 100644
--- a/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java
+++ b/nashorn/src/jdk/internal/dynalink/support/TypeConverterFactory.java
@@ -115,12 +115,12 @@
         protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
             return new ClassMap<MethodHandle>(getClassLoader(sourceType)) {
                 @Override
-                protected MethodHandle computeValue(Class<?> targetType) {
+                protected MethodHandle computeValue(final Class<?> targetType) {
                     try {
                         return createConverter(sourceType, targetType);
-                    } catch (RuntimeException e) {
+                    } catch (final RuntimeException e) {
                         throw e;
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         throw new RuntimeException(e);
                     }
                 }
@@ -133,7 +133,7 @@
         protected ClassMap<MethodHandle> computeValue(final Class<?> sourceType) {
             return new ClassMap<MethodHandle>(getClassLoader(sourceType)) {
                 @Override
-                protected MethodHandle computeValue(Class<?> targetType) {
+                protected MethodHandle computeValue(final Class<?> targetType) {
                     if(!canAutoConvert(sourceType, targetType)) {
                         final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
                         if(converter != IDENTITY_CONVERSION) {
@@ -151,12 +151,12 @@
         protected ClassMap<Boolean> computeValue(final Class<?> sourceType) {
             return new ClassMap<Boolean>(getClassLoader(sourceType)) {
                 @Override
-                protected Boolean computeValue(Class<?> targetType) {
+                protected Boolean computeValue(final Class<?> targetType) {
                     try {
                         return getTypeConverterNull(sourceType, targetType) != null;
-                    } catch (RuntimeException e) {
+                    } catch (final RuntimeException e) {
                         throw e;
-                    } catch (Exception e) {
+                    } catch (final Exception e) {
                         throw new RuntimeException(e);
                     }
                 }
@@ -178,10 +178,10 @@
      *
      * @param factories the {@link GuardingTypeConverterFactory} instances to compose.
      */
-    public TypeConverterFactory(Iterable<? extends GuardingTypeConverterFactory> factories) {
+    public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories) {
         final List<GuardingTypeConverterFactory> l = new LinkedList<>();
         final List<ConversionComparator> c = new LinkedList<>();
-        for(GuardingTypeConverterFactory factory: factories) {
+        for(final GuardingTypeConverterFactory factory: factories) {
             l.add(factory);
             if(factory instanceof ConversionComparator) {
                 c.add((ConversionComparator)factory);
@@ -206,7 +206,7 @@
      * {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
      * {@link GuardingTypeConverterFactory} produced type converters as filters.
      */
-    public MethodHandle asType(MethodHandle handle, final MethodType fromType) {
+    public MethodHandle asType(final MethodHandle handle, final MethodType fromType) {
         MethodHandle newHandle = handle;
         final MethodType toType = newHandle.type();
         final int l = toType.parameterCount();
@@ -250,7 +250,7 @@
         return newHandle.asType(fromType);
     }
 
-    private static MethodHandle applyConverters(MethodHandle handle, int pos, List<MethodHandle> converters) {
+    private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List<MethodHandle> converters) {
         if(converters.isEmpty()) {
             return handle;
         }
@@ -285,8 +285,8 @@
      * @return one of Comparison constants that establish which - if any - of the target types is preferable for the
      * conversion.
      */
-    public Comparison compareConversion(Class<?> sourceType, Class<?> targetType1, Class<?> targetType2) {
-        for(ConversionComparator comparator: comparators) {
+    public Comparison compareConversion(final Class<?> sourceType, final Class<?> targetType1, final Class<?> targetType2) {
+        for(final ConversionComparator comparator: comparators) {
             final Comparison result = comparator.compareConversion(sourceType, targetType1, targetType2);
             if(result != Comparison.INDETERMINATE) {
                 return result;
@@ -313,20 +313,20 @@
         return TypeUtilities.isMethodInvocationConvertible(fromType, toType);
     }
 
-    /*private*/ MethodHandle getCacheableTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
+    /*private*/ MethodHandle getCacheableTypeConverterNull(final Class<?> sourceType, final Class<?> targetType) {
         final MethodHandle converter = getCacheableTypeConverter(sourceType, targetType);
         return converter == IDENTITY_CONVERSION ? null : converter;
     }
 
-    /*private*/ MethodHandle getTypeConverterNull(Class<?> sourceType, Class<?> targetType) {
+    /*private*/ MethodHandle getTypeConverterNull(final Class<?> sourceType, final Class<?> targetType) {
         try {
             return getCacheableTypeConverterNull(sourceType, targetType);
-        } catch(NotCacheableConverter e) {
+        } catch(final NotCacheableConverter e) {
             return e.converter;
         }
     }
 
-    /*private*/ MethodHandle getCacheableTypeConverter(Class<?> sourceType, Class<?> targetType) {
+    /*private*/ MethodHandle getCacheableTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
         return converterMap.get(sourceType).get(targetType);
     }
 
@@ -339,15 +339,15 @@
      * @param targetType the type to convert to
      * @return a method handle performing the conversion.
      */
-    public MethodHandle getTypeConverter(Class<?> sourceType, Class<?> targetType) {
+    public MethodHandle getTypeConverter(final Class<?> sourceType, final Class<?> targetType) {
         try {
             return converterIdentityMap.get(sourceType).get(targetType);
-        } catch(NotCacheableConverter e) {
+        } catch(final NotCacheableConverter e) {
             return e.converter;
         }
     }
 
-    /*private*/ MethodHandle createConverter(Class<?> sourceType, Class<?> targetType) throws Exception {
+    /*private*/ MethodHandle createConverter(final Class<?> sourceType, final Class<?> targetType) throws Exception {
         final MethodType type = MethodType.methodType(targetType, sourceType);
         final MethodHandle identity = IDENTITY_CONVERSION.asType(type);
         MethodHandle last = identity;
@@ -372,6 +372,7 @@
 
     /*private*/ static final MethodHandle IDENTITY_CONVERSION = MethodHandles.identity(Object.class);
 
+    @SuppressWarnings("serial")
     private static class NotCacheableConverter extends RuntimeException {
         final MethodHandle converter;
 
diff --git a/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java b/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java
index 57fea99..6403f3d 100644
--- a/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java
+++ b/nashorn/src/jdk/internal/dynalink/support/TypeUtilities.java
@@ -106,38 +106,49 @@
     }
 
     /**
-     * Given two types represented by c1 and c2, returns a type that is their most specific common superclass or
-     * superinterface.
+     * Given two types represented by c1 and c2, returns a type that is their most specific common supertype for
+     * purposes of lossless conversions.
      *
      * @param c1 one type
      * @param c2 another type
-     * @return their most common superclass or superinterface. If they have several unrelated superinterfaces as their
-     * most specific common type, or the types themselves are completely unrelated interfaces, {@link java.lang.Object}
-     * is returned.
+     * @return their most common superclass or superinterface for purposes of lossless conversions. If they have several
+     * unrelated superinterfaces as their most specific common type, or the types themselves are completely
+     * unrelated interfaces, {@link java.lang.Object} is returned.
      */
-    public static Class<?> getMostSpecificCommonType(Class<?> c1, Class<?> c2) {
+    public static Class<?> getCommonLosslessConversionType(final Class<?> c1, final Class<?> c2) {
         if(c1 == c2) {
             return c1;
+        } else if(isConvertibleWithoutLoss(c2, c1)) {
+            return c1;
+        } else if(isConvertibleWithoutLoss(c1, c2)) {
+            return c2;
         }
-        Class<?> c3 = c2;
-        if(c3.isPrimitive()) {
-            if(c3 == Byte.TYPE)
-                c3 = Byte.class;
-            else if(c3 == Short.TYPE)
-                c3 = Short.class;
-            else if(c3 == Character.TYPE)
-                c3 = Character.class;
-            else if(c3 == Integer.TYPE)
-                c3 = Integer.class;
-            else if(c3 == Float.TYPE)
-                c3 = Float.class;
-            else if(c3 == Long.TYPE)
-                c3 = Long.class;
-            else if(c3 == Double.TYPE)
-                c3 = Double.class;
+        if(c1 == void.class) {
+            return c2;
+        } else if(c2 == void.class) {
+            return c1;
         }
-        Set<Class<?>> a1 = getAssignables(c1, c3);
-        Set<Class<?>> a2 = getAssignables(c3, c1);
+        if(c1.isPrimitive() && c2.isPrimitive()) {
+            if((c1 == byte.class && c2 == char.class) || (c1 == char.class && c2 == byte.class)) {
+                // byte + char = int
+                return int.class;
+            } else if((c1 == short.class && c2 == char.class) || (c1 == char.class && c2 == short.class)) {
+                // short + char = int
+                return int.class;
+            } else if((c1 == int.class && c2 == float.class) || (c1 == float.class && c2 == int.class)) {
+                // int + float = double
+                return double.class;
+            }
+        }
+        // For all other cases. This will handle long + (float|double) = Number case as well as boolean + anything = Object case too.
+        return getMostSpecificCommonTypeUnequalNonprimitives(c1, c2);
+    }
+
+    private static Class<?> getMostSpecificCommonTypeUnequalNonprimitives(final Class<?> c1, final Class<?> c2) {
+        final Class<?> npc1 = c1.isPrimitive() ? getWrapperType(c1) : c1;
+        final Class<?> npc2 = c2.isPrimitive() ? getWrapperType(c2) : c2;
+        final Set<Class<?>> a1 = getAssignables(npc1, npc2);
+        final Set<Class<?>> a2 = getAssignables(npc2, npc1);
         a1.retainAll(a2);
         if(a1.isEmpty()) {
             // Can happen when at least one of the arguments is an interface,
@@ -148,10 +159,10 @@
         // thank to interfaces. I.e., if you call this method for String.class
         // and Number.class, you'll have Comparable, Serializable, and Object
         // as maximal elements.
-        List<Class<?>> max = new ArrayList<>();
-        outer: for(Class<?> clazz: a1) {
-            for(Iterator<Class<?>> maxiter = max.iterator(); maxiter.hasNext();) {
-                Class<?> maxClazz = maxiter.next();
+        final List<Class<?>> max = new ArrayList<>();
+        outer: for(final Class<?> clazz: a1) {
+            for(final Iterator<Class<?>> maxiter = max.iterator(); maxiter.hasNext();) {
+                final Class<?> maxClazz = maxiter.next();
                 if(isSubtype(maxClazz, clazz)) {
                     // It can't be maximal, if there's already a more specific
                     // maximal than it.
@@ -168,26 +179,26 @@
             max.add(clazz);
         }
         if(max.size() > 1) {
-            return OBJECT_CLASS;
+            return Object.class;
         }
         return max.get(0);
     }
 
-    private static Set<Class<?>> getAssignables(Class<?> c1, Class<?> c2) {
-        Set<Class<?>> s = new HashSet<>();
+    private static Set<Class<?>> getAssignables(final Class<?> c1, final Class<?> c2) {
+        final Set<Class<?>> s = new HashSet<>();
         collectAssignables(c1, c2, s);
         return s;
     }
 
-    private static void collectAssignables(Class<?> c1, Class<?> c2, Set<Class<?>> s) {
+    private static void collectAssignables(final Class<?> c1, final Class<?> c2, final Set<Class<?>> s) {
         if(c1.isAssignableFrom(c2)) {
             s.add(c1);
         }
-        Class<?> sc = c1.getSuperclass();
+        final Class<?> sc = c1.getSuperclass();
         if(sc != null) {
             collectAssignables(sc, c2, s);
         }
-        Class<?>[] itf = c1.getInterfaces();
+        final Class<?>[] itf = c1.getInterfaces();
         for(int i = 0; i < itf.length; ++i) {
             collectAssignables(itf[i], c2, s);
         }
@@ -210,17 +221,17 @@
         return Collections.unmodifiableMap(wrapperTypes);
     }
 
-    private static Map<String, Class<?>> createClassNameMapping(Collection<Class<?>> classes) {
+    private static Map<String, Class<?>> createClassNameMapping(final Collection<Class<?>> classes) {
         final Map<String, Class<?>> map = new HashMap<>();
-        for(Class<?> clazz: classes) {
+        for(final Class<?> clazz: classes) {
             map.put(clazz.getName(), clazz);
         }
         return map;
     }
 
-    private static <K, V> Map<V, K> invertMap(Map<K, V> map) {
+    private static <K, V> Map<V, K> invertMap(final Map<K, V> map) {
         final Map<V, K> inverted = new IdentityHashMap<>(map.size());
-        for(Map.Entry<K, V> entry: map.entrySet()) {
+        for(final Map.Entry<K, V> entry: map.entrySet()) {
             inverted.put(entry.getValue(), entry.getKey());
         }
         return Collections.unmodifiableMap(inverted);
@@ -232,30 +243,59 @@
      * {@link #isSubtype(Class, Class)}) as well as boxing conversion (JLS 5.1.7) optionally followed by widening
      * reference conversion and unboxing conversion (JLS 5.1.8) optionally followed by widening primitive conversion.
      *
-     * @param callSiteType the parameter type at the call site
-     * @param methodType the parameter type in the method declaration
-     * @return true if callSiteType is method invocation convertible to the methodType.
+     * @param sourceType the type being converted from (call site type for parameter types, method type for return types)
+     * @param targetType the parameter type being converted to (method type for parameter types, call site type for return types)
+     * @return true if source type is method invocation convertible to target type.
      */
-    public static boolean isMethodInvocationConvertible(Class<?> callSiteType, Class<?> methodType) {
-        if(methodType.isAssignableFrom(callSiteType)) {
+    public static boolean isMethodInvocationConvertible(final Class<?> sourceType, final Class<?> targetType) {
+        if(targetType.isAssignableFrom(sourceType)) {
             return true;
         }
-        if(callSiteType.isPrimitive()) {
-            if(methodType.isPrimitive()) {
-                return isProperPrimitiveSubtype(callSiteType, methodType);
+        if(sourceType.isPrimitive()) {
+            if(targetType.isPrimitive()) {
+                return isProperPrimitiveSubtype(sourceType, targetType);
             }
             // Boxing + widening reference conversion
-            return methodType.isAssignableFrom(WRAPPER_TYPES.get(callSiteType));
+            assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName();
+            return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType));
         }
-        if(methodType.isPrimitive()) {
-            final Class<?> unboxedCallSiteType = PRIMITIVE_TYPES.get(callSiteType);
+        if(targetType.isPrimitive()) {
+            final Class<?> unboxedCallSiteType = PRIMITIVE_TYPES.get(sourceType);
             return unboxedCallSiteType != null
-                    && (unboxedCallSiteType == methodType || isProperPrimitiveSubtype(unboxedCallSiteType, methodType));
+                    && (unboxedCallSiteType == targetType || isProperPrimitiveSubtype(unboxedCallSiteType, targetType));
         }
         return false;
     }
 
     /**
+     * Determines whether a type can be converted to another without losing any
+     * precision.
+     *
+     * @param sourceType the source type
+     * @param targetType the target type
+     * @return true if lossless conversion is possible
+     */
+    public static boolean isConvertibleWithoutLoss(final Class<?> sourceType, final Class<?> targetType) {
+        if(targetType.isAssignableFrom(sourceType)) {
+            return true;
+        }
+        if(sourceType.isPrimitive()) {
+            if(sourceType == void.class) {
+                return false; // Void can't be losslessly represented by any type
+            }
+            if(targetType.isPrimitive()) {
+                return isProperPrimitiveLosslessSubtype(sourceType, targetType);
+            }
+            // Boxing + widening reference conversion
+            assert WRAPPER_TYPES.get(sourceType) != null : sourceType.getName();
+            return targetType.isAssignableFrom(WRAPPER_TYPES.get(sourceType));
+        }
+        // Can't convert from any non-primitive type to any primitive type without data loss because of null.
+        // Also, can't convert non-assignable reference types.
+        return false;
+    }
+
+    /**
      * Determines whether one type can be potentially converted to another type at runtime. Allows a conversion between
      * any subtype and supertype in either direction, and also allows a conversion between any two primitive types, as
      * well as between any primitive type and any reference type that can hold a boxed primitive.
@@ -264,9 +304,9 @@
      * @param methodType the parameter type in the method declaration
      * @return true if callSiteType is potentially convertible to the methodType.
      */
-    public static boolean isPotentiallyConvertible(Class<?> callSiteType, Class<?> methodType) {
+    public static boolean isPotentiallyConvertible(final Class<?> callSiteType, final Class<?> methodType) {
         // Widening or narrowing reference conversion
-        if(methodType.isAssignableFrom(callSiteType) || callSiteType.isAssignableFrom(methodType)) {
+        if(areAssignable(callSiteType, methodType)) {
             return true;
         }
         if(callSiteType.isPrimitive()) {
@@ -287,6 +327,16 @@
     }
 
     /**
+     * Returns true if either of the types is assignable from the other.
+     * @param c1 one of the types
+     * @param c2 another one of the types
+     * @return true if either c1 is assignable from c2 or c2 is assignable from c1.
+     */
+    public static boolean areAssignable(final Class<?> c1, final Class<?> c2) {
+        return c1.isAssignableFrom(c2) || c2.isAssignableFrom(c1);
+    }
+
+    /**
      * Determines whether one type is a subtype of another type, as per JLS 4.10 "Subtyping". Note: this is not strict
      * or proper subtype, therefore true is also returned for identical types; to be completely precise, it allows
      * identity conversion (JLS 5.1.1), widening primitive conversion (JLS 5.1.2) and widening reference conversion (JLS
@@ -297,7 +347,7 @@
      * @return true if subType can be converted by identity conversion, widening primitive conversion, or widening
      * reference conversion to superType.
      */
-    public static boolean isSubtype(Class<?> subType, Class<?> superType) {
+    public static boolean isSubtype(final Class<?> subType, final Class<?> superType) {
         // Covers both JLS 4.10.2 "Subtyping among Class and Interface Types"
         // and JLS 4.10.3 "Subtyping among Array Types", as well as primitive
         // type identity.
@@ -328,7 +378,7 @@
      * @param superType the supposed supertype
      * @return true if subType is a proper (not identical to) primitive subtype of the superType
      */
-    private static boolean isProperPrimitiveSubtype(Class<?> subType, Class<?> superType) {
+    private static boolean isProperPrimitiveSubtype(final Class<?> subType, final Class<?> superType) {
         if(superType == boolean.class || subType == boolean.class) {
             return false;
         }
@@ -353,6 +403,37 @@
         return false;
     }
 
+    /**
+     * Similar to {@link #isProperPrimitiveSubtype(Class, Class)}, except it disallows conversions from int and long to
+     * float, and from long to double, as those can lose precision. It also disallows conversion from and to char and
+     * anything else (similar to boolean) as char is not meant to be an arithmetic type.
+     * @param subType the supposed subtype
+     * @param superType the supposed supertype
+     * @return true if subType is a proper (not identical to) primitive subtype of the superType that can be represented
+     * by the supertype without no precision loss.
+     */
+    private static boolean isProperPrimitiveLosslessSubtype(final Class<?> subType, final Class<?> superType) {
+        if(superType == boolean.class || subType == boolean.class) {
+            return false;
+        }
+        if(superType == char.class || subType == char.class) {
+            return false;
+        }
+        if(subType == byte.class) {
+            return true;
+        }
+        if(subType == short.class) {
+            return superType != byte.class;
+        }
+        if(subType == int.class) {
+            return superType == long.class || superType == double.class;
+        }
+        if(subType == float.class) {
+            return superType == double.class;
+        }
+        return false;
+    }
+
     private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE_TYPES = createWrapperToPrimitiveTypes();
 
     private static Map<Class<?>, Class<?>> createWrapperToPrimitiveTypes() {
@@ -384,13 +465,13 @@
         return classes.keySet();
     }
 
-    private static void addClassHierarchy(Map<Class<?>, Class<?>> map, Class<?> clazz) {
+    private static void addClassHierarchy(final Map<Class<?>, Class<?>> map, final Class<?> clazz) {
         if(clazz == null) {
             return;
         }
         map.put(clazz, clazz);
         addClassHierarchy(map, clazz.getSuperclass());
-        for(Class<?> itf: clazz.getInterfaces()) {
+        for(final Class<?> itf: clazz.getInterfaces()) {
             addClassHierarchy(map, itf);
         }
     }
@@ -402,7 +483,7 @@
      * @return true if the class can be assigned from any boxed primitive. Basically, it is true if the class is any
      * primitive wrapper class, or a superclass or superinterface of any primitive wrapper class.
      */
-    private static boolean isAssignableFromBoxedPrimitive(Class<?> clazz) {
+    private static boolean isAssignableFromBoxedPrimitive(final Class<?> clazz) {
         return PRIMITIVE_WRAPPER_TYPES.contains(clazz);
     }
 
@@ -413,7 +494,7 @@
      * @return the class representing the primitive type, or null if the name does not correspond to a primitive type
      * or is "void".
      */
-    public static Class<?> getPrimitiveTypeByName(String name) {
+    public static Class<?> getPrimitiveTypeByName(final String name) {
         return PRIMITIVE_TYPES_BY_NAME.get(name);
     }
 
@@ -424,7 +505,7 @@
      * @param wrapperType the class object representing a wrapper for a primitive type
      * @return the class object representing the primitive type, or null if the passed class is not a primitive wrapper.
      */
-    public static Class<?> getPrimitiveType(Class<?> wrapperType) {
+    public static Class<?> getPrimitiveType(final Class<?> wrapperType) {
         return WRAPPER_TO_PRIMITIVE_TYPES.get(wrapperType);
     }
 
@@ -436,7 +517,7 @@
      * @param primitiveType the class object representing a primitive type
      * @return the class object representing the wrapper type, or null if the passed class is not a primitive.
      */
-    public static Class<?> getWrapperType(Class<?> primitiveType) {
+    public static Class<?> getWrapperType(final Class<?> primitiveType) {
         return WRAPPER_TYPES.get(primitiveType);
     }
 }
diff --git a/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java b/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
index da8c009..89a0677 100644
--- a/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
+++ b/nashorn/src/jdk/internal/dynalink/support/UnnamedDynCallSiteDescriptor.java
@@ -90,7 +90,7 @@
     private final MethodType methodType;
     private final String op;
 
-    UnnamedDynCallSiteDescriptor(String op, MethodType methodType) {
+    UnnamedDynCallSiteDescriptor(final String op, final MethodType methodType) {
         this.op = op;
         this.methodType = methodType;
     }
@@ -105,7 +105,7 @@
     }
 
     @Override
-    public String getNameToken(int i) {
+    public String getNameToken(final int i) {
         switch(i) {
             case 0: return "dyn";
             case 1: return op;
@@ -119,7 +119,7 @@
     }
 
     @Override
-    public CallSiteDescriptor changeMethodType(MethodType newMethodType) {
+    public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
         return CallSiteDescriptorFactory.getCanonicalPublicDescriptor(new UnnamedDynCallSiteDescriptor(op,
                 newMethodType));
     }
diff --git a/nashorn/src/jdk/internal/dynalink/support/messages.properties b/nashorn/src/jdk/internal/dynalink/support/messages.properties
index 88d5990..ed26299 100644
--- a/nashorn/src/jdk/internal/dynalink/support/messages.properties
+++ b/nashorn/src/jdk/internal/dynalink/support/messages.properties
@@ -83,4 +83,4 @@
 isOfClassGuardAlwaysFalse=isOfClass guard for {0} in position {1} in method type {2} at {3} will always return false
 
 isArrayGuardAlwaysTrue=isArray guard in position {0} in method type {1} at {2} will always return true
-isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false
\ No newline at end of file
+isArrayGuardAlwaysFalse=isArray guard in position {0} in method type {1} at {2} will always return false
diff --git a/nashorn/src/jdk/nashorn/api/scripting/ClassFilter.java b/nashorn/src/jdk/nashorn/api/scripting/ClassFilter.java
new file mode 100644
index 0000000..ddf1bc3
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/api/scripting/ClassFilter.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 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.  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.
+ */
+package jdk.nashorn.api.scripting;
+
+/**
+ * Class filter (optional) to be used by nashorn script engine.
+ * jsr-223 program embedding nashorn script can set ClassFilter instance
+ * to be used when an engine instance is created.
+ */
+public interface ClassFilter {
+     /**
+      * Should the Java class of the specified name be exposed to scripts?
+      * @param className is the fully qualified name of the java class being
+      * checked. This will not be null. Only non-array class names will be
+      * passed.
+      * @return true if the java class can be exposed to scripts false otherwise
+      */
+     public boolean exposeToScripts(String className);
+}
diff --git a/nashorn/src/jdk/nashorn/api/scripting/Formatter.java b/nashorn/src/jdk/nashorn/api/scripting/Formatter.java
index a14a83e..544e70c 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/Formatter.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/Formatter.java
@@ -65,8 +65,8 @@
 
         while (m.find()) {
             int index = index(m.group(1));
-            boolean previous = isPreviousArgument(m.group(2));
-            char conversion = m.group(6).charAt(0);
+            final boolean previous = isPreviousArgument(m.group(2));
+            final char conversion = m.group(6).charAt(0);
 
             // skip over some formats
             if (index < 0 || previous
@@ -85,7 +85,7 @@
             }
 
             // current argument
-            Object arg = args[index - 1];
+            final Object arg = args[index - 1];
 
             // for date we convert double to long
             if (m.group(5) != null) {
diff --git a/nashorn/src/jdk/nashorn/api/scripting/JSObject.java b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java
index bd6e820..8d81864 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/JSObject.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java
@@ -26,7 +26,6 @@
 package jdk.nashorn.api.scripting;
 
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Set;
 
 /**
diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
index a5f8c24..098f850 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornException.java
@@ -53,9 +53,6 @@
     // underlying ECMA error object - lazily initialized
     private Object ecmaError;
 
-    /** script source name used for "engine.js" */
-    public static final String ENGINE_SCRIPT_SOURCE_NAME = "nashorn:engine/resources/engine.js";
-
     /**
      * Constructor
      *
@@ -182,7 +179,7 @@
             if (ECMAErrors.isScriptFrame(st)) {
                 final String className = "<" + st.getFileName() + ">";
                 String methodName = st.getMethodName();
-                if (methodName.equals(CompilerConstants.RUN_SCRIPT.symbolName())) {
+                if (methodName.equals(CompilerConstants.PROGRAM.symbolName())) {
                     methodName = "<program>";
                 }
 
@@ -224,10 +221,22 @@
         return buf.toString();
     }
 
+    /**
+     * Get the thrown object. Subclass responsibility
+     * @return thrown object
+     */
     protected Object getThrown() {
         return null;
     }
 
+    /**
+     * Initialization function for ECMA errors. Stores the error
+     * in the ecmaError field of this class. It is only initialized
+     * once, and then reused
+     *
+     * @param global the global
+     * @return initialized exception
+     */
     protected NashornException initEcmaError(final ScriptObject global) {
         if (ecmaError != null) {
             return this; // initialized already!
diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
index 7ebe5c9..bbf1eec 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.api.scripting;
 
-import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
 import java.io.IOException;
@@ -34,13 +32,10 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
-import java.net.URL;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.security.Permissions;
 import java.security.PrivilegedAction;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
 import java.text.MessageFormat;
 import java.util.Locale;
@@ -58,7 +53,6 @@
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
-import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
@@ -98,12 +92,6 @@
     // This is the initial default Nashorn global object.
     // This is used as "shared" global if above option is true.
     private final Global              global;
-    // initialized bit late to be made 'final'.
-    // Property object for "context" property of global object.
-    private volatile Property         contextProperty;
-
-    // default options passed to Nashorn Options object
-    private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
 
     // Nashorn script engine error message management
     private static final String MESSAGES_RESOURCE = "jdk.nashorn.api.scripting.resources.Messages";
@@ -122,36 +110,8 @@
         }
     }
 
-    // load engine.js
-    @SuppressWarnings("resource")
-    private static Source loadEngineJSSource() {
-        final String script = "resources/engine.js";
-        try {
-            return AccessController.doPrivileged(
-                    new PrivilegedExceptionAction<Source>() {
-                        @Override
-                        public Source run() throws IOException {
-                            final URL url = NashornScriptEngine.class.getResource(script);
-                            return sourceFor(NashornException.ENGINE_SCRIPT_SOURCE_NAME, url);
-                        }
-                    }
-            );
-        } catch (final PrivilegedActionException e) {
-            if (Context.DEBUG) {
-                e.printStackTrace();
-            }
-            throw new RuntimeException(e);
-        }
-    }
-
-    // Source object for engine.js
-    private static final Source ENGINE_SCRIPT_SRC = loadEngineJSSource();
-
-    NashornScriptEngine(final NashornScriptEngineFactory factory, final ClassLoader appLoader) {
-        this(factory, DEFAULT_OPTIONS, appLoader);
-    }
-
-    NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader) {
+    NashornScriptEngine(final NashornScriptEngineFactory factory, final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
+        assert args != null : "null argument array";
         this.factory = factory;
         final Options options = new Options("nashorn");
         options.process(args);
@@ -163,7 +123,7 @@
             @Override
             public Context run() {
                 try {
-                    return new Context(options, errMgr, appLoader);
+                    return new Context(options, errMgr, appLoader, classFilter);
                 } catch (final RuntimeException e) {
                     if (Context.DEBUG) {
                         e.printStackTrace();
@@ -249,39 +209,12 @@
         return getInterfaceInner(thiz, clazz);
     }
 
-    // These are called from the "engine.js" script
-
-    /**
-     * This hook is used to search js global variables exposed from Java code.
-     *
-     * @param self 'this' passed from the script
-     * @param ctxt current ScriptContext in which name is searched
-     * @param name name of the variable searched
-     * @return the value of the named variable
-     */
-    public Object __noSuchProperty__(final Object self, final ScriptContext ctxt, final String name) {
-        if (ctxt != null) {
-            final int scope = ctxt.getAttributesScope(name);
-            final Global ctxtGlobal = getNashornGlobalFrom(ctxt);
-            if (scope != -1) {
-                return ScriptObjectMirror.unwrap(ctxt.getAttribute(name, scope), ctxtGlobal);
-            }
-
-            if (self == UNDEFINED) {
-                // scope access and so throw ReferenceError
-                throw referenceError(ctxtGlobal, "not.defined", name);
-            }
-        }
-
-        return UNDEFINED;
-    }
-
     // Implementation only below this point
 
     private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException {
         try {
             return sourceFor(getScriptName(ctxt), reader);
-        } catch (IOException e) {
+        } catch (final IOException e) {
             throw new ScriptException(e);
         }
     }
@@ -380,7 +313,7 @@
         }
 
         // Arbitrary user Bindings implementation. Look for NASHORN_GLOBAL in it!
-        Object scope = bindings.get(NASHORN_GLOBAL);
+        final Object scope = bindings.get(NASHORN_GLOBAL);
         if (scope instanceof ScriptObjectMirror) {
             final Global glob = globalFromMirror((ScriptObjectMirror)scope);
             if (glob != null) {
@@ -397,7 +330,7 @@
 
     // Retrieve nashorn Global object from a given ScriptObjectMirror
     private Global globalFromMirror(final ScriptObjectMirror mirror) {
-        ScriptObject sobj = mirror.getScriptObject();
+        final ScriptObject sobj = mirror.getScriptObject();
         if (sobj instanceof Global && isOfContext((Global)sobj, nashornContext)) {
             return (Global)sobj;
         }
@@ -427,47 +360,12 @@
             }
         }, CREATE_GLOBAL_ACC_CTXT);
 
-        nashornContext.initGlobal(newGlobal);
+        nashornContext.initGlobal(newGlobal, this);
+        newGlobal.setScriptContext(ctxt);
 
-        final int NON_ENUMERABLE_CONSTANT = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE | Property.NOT_WRITABLE;
-        // current ScriptContext exposed as "context"
-        // "context" is non-writable from script - but script engine still
-        // needs to set it and so save the context Property object
-        contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, ctxt);
-        // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as
-        // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property
-        // in the Global of a Context we just created - both the Context and the Global were just created and can not be
-        // seen from another thread outside of this constructor.
-        newGlobal.addOwnProperty("engine", NON_ENUMERABLE_CONSTANT, this);
-        // global script arguments with undefined value
-        newGlobal.addOwnProperty("arguments", Property.NOT_ENUMERABLE, UNDEFINED);
-        // file name default is null
-        newGlobal.addOwnProperty(ScriptEngine.FILENAME, Property.NOT_ENUMERABLE, null);
-        // evaluate engine.js initialization script this new global object
-        try {
-            evalImpl(compileImpl(ENGINE_SCRIPT_SRC, newGlobal), ctxt, newGlobal);
-        } catch (final ScriptException exp) {
-            throw new RuntimeException(exp);
-        }
         return newGlobal;
     }
 
-    // scripts should see "context" and "engine" as variables in the given global object
-    private void setContextVariables(final Global ctxtGlobal, final ScriptContext ctxt) {
-        // set "context" global variable via contextProperty - because this
-        // property is non-writable
-        contextProperty.setObjectValue(ctxtGlobal, ctxtGlobal, ctxt, false);
-        Object args = ScriptObjectMirror.unwrap(ctxt.getAttribute("arguments"), ctxtGlobal);
-        if (args == null || args == UNDEFINED) {
-            args = ScriptRuntime.EMPTY_ARRAY;
-        }
-        // if no arguments passed, expose it
-        if (! (args instanceof ScriptObject)) {
-            args = ctxtGlobal.wrapAsObject(args);
-            ctxtGlobal.set("arguments", args, false);
-        }
-    }
-
     private Object invokeImpl(final Object selfObject, final String name, final Object... args) throws ScriptException, NoSuchMethodException {
         name.getClass(); // null check
 
@@ -525,7 +423,7 @@
         return evalImpl(script, ctxt, getNashornGlobalFrom(ctxt));
     }
 
-    private Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+    private static Object evalImpl(final Context.MultiGlobalCompiledScript mgcs, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
         final Global oldGlobal = Context.getGlobal();
         final boolean globalChanged = (oldGlobal != ctxtGlobal);
         try {
@@ -534,11 +432,7 @@
             }
 
             final ScriptFunction script = mgcs.getFunction(ctxtGlobal);
-
-            // set ScriptContext variables if ctxt is non-null
-            if (ctxt != null) {
-                setContextVariables(ctxtGlobal, ctxt);
-            }
+            ctxtGlobal.setScriptContext(ctxt);
             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
@@ -550,7 +444,7 @@
         }
     }
 
-    private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
+    private static Object evalImpl(final ScriptFunction script, final ScriptContext ctxt, final Global ctxtGlobal) throws ScriptException {
         if (script == null) {
             return null;
         }
@@ -561,10 +455,7 @@
                 Context.setGlobal(ctxtGlobal);
             }
 
-            // set ScriptContext variables if ctxt is non-null
-            if (ctxt != null) {
-                setContextVariables(ctxtGlobal, ctxt);
-            }
+            ctxtGlobal.setScriptContext(ctxt);
             return ScriptObjectMirror.translateUndefined(ScriptObjectMirror.wrap(ScriptRuntime.apply(script, ctxtGlobal), ctxtGlobal));
         } catch (final Exception e) {
             throwAsScriptException(e, ctxtGlobal);
@@ -671,7 +562,7 @@
                 continue;
             }
 
-            Object obj = sobj.get(method.getName());
+            final Object obj = sobj.get(method.getName());
             if (! (obj instanceof ScriptFunction)) {
                 return false;
             }
diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
index beb0c2a..4ddcf94 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java
@@ -135,10 +135,13 @@
         return sb.toString();
     }
 
+    // default options passed to Nashorn script engine
+    private static final String[] DEFAULT_OPTIONS = new String[] { "-doe" };
+
     @Override
     public ScriptEngine getScriptEngine() {
         try {
-            return new NashornScriptEngine(this, getAppClassLoader());
+            return new NashornScriptEngine(this, DEFAULT_OPTIONS, getAppClassLoader(), null);
         } catch (final RuntimeException e) {
             if (Context.DEBUG) {
                 e.printStackTrace();
@@ -152,10 +155,27 @@
      *
      * @param appLoader class loader to be used as script "app" class loader.
      * @return newly created script engine.
+     * @throws SecurityException
+     *         if the security manager's {@code checkPermission}
+     *         denies {@code RuntimePermission("nashorn.setConfig")}
      */
     public ScriptEngine getScriptEngine(final ClassLoader appLoader) {
-        checkConfigPermission();
-        return new NashornScriptEngine(this, appLoader);
+        return newEngine(DEFAULT_OPTIONS, appLoader, null);
+    }
+
+    /**
+     * Create a new Script engine initialized by given class filter.
+     *
+     * @param classFilter class filter to use.
+     * @return newly created script engine.
+     * @throws NullPointerException if {@code classFilter} is {@code null}
+     * @throws SecurityException
+     *         if the security manager's {@code checkPermission}
+     *         denies {@code RuntimePermission("nashorn.setConfig")}
+     */
+    public ScriptEngine getScriptEngine(final ClassFilter classFilter) {
+        classFilter.getClass(); // null check
+        return newEngine(DEFAULT_OPTIONS, getAppClassLoader(), classFilter);
     }
 
     /**
@@ -163,10 +183,14 @@
      *
      * @param args arguments array passed to script engine.
      * @return newly created script engine.
+     * @throws NullPointerException if {@code args} is {@code null}
+     * @throws SecurityException
+     *         if the security manager's {@code checkPermission}
+     *         denies {@code RuntimePermission("nashorn.setConfig")}
      */
-    public ScriptEngine getScriptEngine(final String[] args) {
-        checkConfigPermission();
-        return new NashornScriptEngine(this, args, getAppClassLoader());
+    public ScriptEngine getScriptEngine(final String... args) {
+        args.getClass(); // null check
+        return newEngine(args, getAppClassLoader(), null);
     }
 
     /**
@@ -175,10 +199,44 @@
      * @param args arguments array passed to script engine.
      * @param appLoader class loader to be used as script "app" class loader.
      * @return newly created script engine.
+     * @throws NullPointerException if {@code args} is {@code null}
+     * @throws SecurityException
+     *         if the security manager's {@code checkPermission}
+     *         denies {@code RuntimePermission("nashorn.setConfig")}
      */
     public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader) {
+        args.getClass(); // null check
+        return newEngine(args, appLoader, null);
+    }
+
+    /**
+     * Create a new Script engine initialized by given arguments.
+     *
+     * @param args arguments array passed to script engine.
+     * @param appLoader class loader to be used as script "app" class loader.
+     * @param classFilter class filter to use.
+     * @return newly created script engine.
+     * @throws NullPointerException if {@code args} or {@code classFilter} is {@code null}
+     * @throws SecurityException
+     *         if the security manager's {@code checkPermission}
+     *         denies {@code RuntimePermission("nashorn.setConfig")}
+     */
+    public ScriptEngine getScriptEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
+        args.getClass(); // null check
+        classFilter.getClass(); // null check
+        return newEngine(args, appLoader, classFilter);
+    }
+
+    private ScriptEngine newEngine(final String[] args, final ClassLoader appLoader, final ClassFilter classFilter) {
         checkConfigPermission();
-        return new NashornScriptEngine(this, args, appLoader);
+        try {
+            return new NashornScriptEngine(this, args, appLoader, classFilter);
+        } catch (final RuntimeException e) {
+            if (Context.DEBUG) {
+                e.printStackTrace();
+            }
+            throw e;
+        }
     }
 
     // -- Internals only below this point
@@ -220,7 +278,7 @@
         // Revisit: script engine implementation needs the capability to
         // find the class loader of the context in which the script engine
         // is running so that classes will be found and loaded properly
-        ClassLoader ccl = Thread.currentThread().getContextClassLoader();
+        final ClassLoader ccl = Thread.currentThread().getContextClassLoader();
         return (ccl == null)? NashornScriptEngineFactory.class.getClassLoader() : ccl;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
index b8035d2..7f4ca75 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java
@@ -43,13 +43,13 @@
 import java.util.concurrent.Callable;
 import javax.script.Bindings;
 import jdk.nashorn.internal.objects.Global;
-import jdk.nashorn.internal.runtime.arrays.ArrayData;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.arrays.ArrayData;
 
 /**
  * Mirror object that wraps a given Nashorn Script object.
@@ -164,11 +164,17 @@
                                 return Context.getContext();
                             }
                         }, GET_CONTEXT_ACC_CTXT);
-                return wrap(context.eval(global, s, null, null, false), global);
+                return wrap(context.eval(global, s, sobj, null, false), global);
             }
         });
     }
 
+    /**
+     * Call member function
+     * @param functionName function name
+     * @param args         arguments
+     * @return return value of function
+     */
     public Object callMember(final String functionName, final Object... args) {
         functionName.getClass(); // null check
         final Global oldGlobal = Context.getGlobal();
@@ -709,6 +715,23 @@
         return newArgs;
     }
 
+    /**
+     * Are the given objects mirrors to same underlying object?
+     *
+     * @param obj1 first object
+     * @param obj2 second object
+     * @return true if obj1 and obj2 are identical script objects or mirrors of it.
+     */
+    public static boolean identical(final Object obj1, final Object obj2) {
+        final Object o1 = (obj1 instanceof ScriptObjectMirror)?
+            ((ScriptObjectMirror)obj1).sobj : obj1;
+
+        final Object o2 = (obj2 instanceof ScriptObjectMirror)?
+            ((ScriptObjectMirror)obj2).sobj : obj2;
+
+        return o1 == o2;
+    }
+
     // package-privates below this.
 
     ScriptObjectMirror(final ScriptObject sobj, final Global global) {
@@ -729,7 +752,7 @@
         return global;
     }
 
-    static Object translateUndefined(Object obj) {
+    static Object translateUndefined(final Object obj) {
         return (obj == ScriptRuntime.UNDEFINED)? null : obj;
     }
 
diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java
index 29d03db..4de2cbf 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptUtils.java
@@ -25,14 +25,16 @@
 
 package jdk.nashorn.api.scripting;
 
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.lang.invoke.MethodHandle;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.LinkerServices;
-import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
 /**
  * Utilities that are to be called from script code.
@@ -69,12 +71,15 @@
      * Create a wrapper function that calls {@code func} synchronized on {@code sync} or, if that is undefined,
      * {@code self}. Used to implement "sync" function in resources/mozilla_compat.js.
      *
-     * @param func the function to invoke
+     * @param func the function to wrap
      * @param sync the object to synchronize on
      * @return a synchronizing wrapper function
      */
-    public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) {
-        return func.makeSynchronizedFunction(sync);
+    public static Object makeSynchronizedFunction(final Object func, final Object sync) {
+        if (func instanceof ScriptFunction) {
+           return ((ScriptFunction)func).makeSynchronizedFunction(sync);
+        }
+        throw typeError("not.a.function", ScriptRuntime.safeToString(func));
     }
 
     /**
diff --git a/nashorn/src/jdk/nashorn/api/scripting/URLReader.java b/nashorn/src/jdk/nashorn/api/scripting/URLReader.java
index 13f6984..53efeee 100644
--- a/nashorn/src/jdk/nashorn/api/scripting/URLReader.java
+++ b/nashorn/src/jdk/nashorn/api/scripting/URLReader.java
@@ -81,7 +81,7 @@
     }
 
     @Override
-    public int read(char cbuf[], int off, int len) throws IOException {
+    public int read(final char cbuf[], final int off, final int len) throws IOException {
         return getReader().read(cbuf, off, len);
     }
 
diff --git a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js b/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
deleted file mode 100644
index b903429..0000000
--- a/nashorn/src/jdk/nashorn/api/scripting/resources/engine.js
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * This script file is executed by script engine at the construction
- * of the every new Global object. The functions here assume global variables
- * "context" of type javax.script.ScriptContext and "engine" of the type
- * jdk.nashorn.api.scripting.NashornScriptEngine.
- **/
-
-Object.defineProperty(this, "__noSuchProperty__", {
-    configurable: true,
-    enumerable: false,
-    writable: true,
-    value: function (name) {
-        'use strict';
-        return engine.__noSuchProperty__(this, context, name);
-    }
-});
-
-function print() {
-    var writer = context != null? context.writer : engine.context.writer;
-    if (! (writer instanceof java.io.PrintWriter)) {
-        writer = new java.io.PrintWriter(writer);
-    }
-    
-    var buf = new java.lang.StringBuilder();
-    for (var i = 0; i < arguments.length; i++) {
-        if (i != 0) {
-            buf.append(' ');
-        }
-        buf.append(String(arguments[i]));
-    }
-    writer.println(buf.toString());
-}
-
-/**
- * This is C-like printf
- *
- * @param format string to format the rest of the print items
- * @param args variadic argument list
- */
-Object.defineProperty(this, "printf", {
-    configurable: true,
-    enumerable: false,
-    writable: true,
-    value: function (format, args/*, more args*/) {
-        print(sprintf.apply(this, arguments));
-    }
-});
-
-/**
- * This is C-like sprintf
- *
- * @param format string to format the rest of the print items
- * @param args variadic argument list
- */
-Object.defineProperty(this, "sprintf", {
-    configurable: true,
-    enumerable: false,
-    writable: true,
-    value: function (format, args/*, more args*/) {
-        var len = arguments.length - 1;
-        var array = [];
-
-        if (len < 0) {
-            return "";
-        }
-
-        for (var i = 0; i < len; i++) {
-            if (arguments[i+1] instanceof Date) {
-                array[i] = arguments[i+1].getTime();
-            } else {
-                array[i] = arguments[i+1];
-            }
-        }
-
-        array = Java.to(array);
-        return Packages.jdk.nashorn.api.scripting.ScriptUtils.format(format, array);
-    }
-});
diff --git a/nashorn/src/jdk/nashorn/internal/AssertsEnabled.java b/nashorn/src/jdk/nashorn/internal/AssertsEnabled.java
new file mode 100644
index 0000000..f067866
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/AssertsEnabled.java
@@ -0,0 +1,45 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal;
+
+/**
+ * Class that exposes the current state of asserts.
+ *
+ */
+public final class AssertsEnabled {
+    private static boolean assertsEnabled = false;
+    static {
+        assert assertsEnabled = true; // Intentional side effect
+    }
+
+    /**
+     * Returns true if asserts are enabled
+     * @return true if asserts are enabled
+     */
+    public static boolean assertsEnabled() {
+        return assertsEnabled;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/IntDeque.java b/nashorn/src/jdk/nashorn/internal/IntDeque.java
new file mode 100644
index 0000000..477afcf
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/IntDeque.java
@@ -0,0 +1,87 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal;
+
+/**
+ * Small helper class for fast int deques
+ */
+public class IntDeque {
+    private int[] deque = new int[16];
+    private int nextFree = 0;
+
+    /**
+     * Push an int value
+     * @param value value
+     */
+    public void push(final int value) {
+        if (nextFree == deque.length) {
+            final int[] newDeque = new int[nextFree * 2];
+            System.arraycopy(deque, 0, newDeque, 0, nextFree);
+            deque = newDeque;
+        }
+        deque[nextFree++] = value;
+    }
+
+    /**
+     * Pop an int value
+     * @return value
+     */
+    public int pop() {
+        return deque[--nextFree];
+    }
+
+    /**
+     * Peek
+     * @return top value
+     */
+    public int peek() {
+        return deque[nextFree - 1];
+    }
+
+    /**
+     * Get the value of the top element and increment it.
+     * @return top value
+     */
+    public int getAndIncrement() {
+        return deque[nextFree - 1]++;
+    }
+
+    /**
+     * Decrement the value of the top element and return it.
+     * @return decremented top value
+     */
+    public int decrementAndGet() {
+        return --deque[nextFree - 1];
+    }
+
+    /**
+     * Check if deque is empty
+     * @return true if empty
+     */
+    public boolean isEmpty() {
+        return nextFree == 0;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java b/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
new file mode 100644
index 0000000..d166889
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ApplySpecialization.java
@@ -0,0 +1,327 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
+import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX;
+
+import java.lang.invoke.MethodType;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * An optimization that attempts to turn applies into calls. This pattern
+ * is very common for fake class instance creation, and apply
+ * introduces expensive args collection and boxing
+ *
+ * <pre>
+ * var Class = {
+ *     create: function() {
+ *         return function() { //vararg
+ *             this.initialize.apply(this, arguments);
+ *         }
+ *     }
+ * };
+ *
+ * Color = Class.create();
+ *
+ * Color.prototype = {
+ *    red: 0, green: 0, blue: 0,
+ *    initialize: function(r,g,b) {
+ *        this.red = r;
+ *        this.green = g;
+ *        this.blue = b;
+ *    }
+ * }
+ *
+ * new Color(17, 47, 11);
+ * </pre>
+ */
+
+@Logger(name="apply2call")
+public final class ApplySpecialization extends NodeVisitor<LexicalContext> implements Loggable {
+
+    private static final boolean USE_APPLY2CALL = Options.getBooleanProperty("nashorn.apply2call", true);
+
+    private final DebugLogger log;
+
+    private final Compiler compiler;
+
+    private final Set<Integer> changed = new HashSet<>();
+
+    private final Deque<List<IdentNode>> explodedArguments = new ArrayDeque<>();
+
+    private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName();
+
+    /**
+     * Apply specialization optimization. Try to explode arguments and call
+     * applies as calls if they just pass on the "arguments" array and
+     * "arguments" doesn't escape.
+     *
+     * @param compiler compiler
+     */
+    public ApplySpecialization(final Compiler compiler) {
+        super(new LexicalContext());
+        this.compiler = compiler;
+        this.log = initLogger(compiler.getContext());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    /**
+     * Arguments may only be used as args to the apply. Everything else is disqualified
+     * We cannot control arguments if they escape from the method and go into an unknown
+     * scope, thus we are conservative and treat any access to arguments outside the
+     * apply call as a case of "we cannot apply the optimization".
+     *
+     * @return true if arguments escape
+     */
+    private boolean argumentsEscape(final FunctionNode functionNode) {
+
+        @SuppressWarnings("serial")
+        final UnsupportedOperationException uoe = new UnsupportedOperationException() {
+            @Override
+            public Throwable fillInStackTrace() {
+                return null;
+            }
+        };
+
+        final Deque<Set<Expression>> stack = new ArrayDeque<>();
+        //ensure that arguments is only passed as arg to apply
+        try {
+            functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                private boolean isCurrentArg(final Expression expr) {
+                    return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
+                }
+
+                private boolean isArguments(final Expression expr) {
+                    return expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName());
+                }
+
+                private boolean isParam(final String name) {
+                    for (final IdentNode param : functionNode.getParameters()) {
+                        if (param.getName().equals(name)) {
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+
+                @Override
+                public Node leaveIdentNode(final IdentNode identNode) {
+                    if (isParam(identNode.getName()) || ARGUMENTS.equals(identNode.getName()) && !isCurrentArg(identNode)) {
+                        throw uoe; //avoid filling in stack trace
+                    }
+                    return identNode;
+                }
+
+                @Override
+                public boolean enterCallNode(final CallNode callNode) {
+                    final Set<Expression> callArgs = new HashSet<>();
+                    if (isApply(callNode)) {
+                        final List<Expression> argList = callNode.getArgs();
+                        if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) {
+                            throw new UnsupportedOperationException();
+                        }
+                        callArgs.addAll(callNode.getArgs());
+                    }
+                    stack.push(callArgs);
+                    return true;
+                }
+
+                @Override
+                public Node leaveCallNode(final CallNode callNode) {
+                    stack.pop();
+                    return callNode;
+                }
+            });
+        } catch (final UnsupportedOperationException e) {
+            log.fine("'arguments' escapes, is not used in standard call dispatch, or is reassigned in '" + functionNode.getName() + "'. Aborting");
+            return true; //bad
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean enterCallNode(final CallNode callNode) {
+        return !explodedArguments.isEmpty();
+    }
+
+    @Override
+    public Node leaveCallNode(final CallNode callNode) {
+        //apply needs to be a global symbol or we don't allow it
+
+        final List<IdentNode> newParams = explodedArguments.peek();
+        if (isApply(callNode)) {
+            final List<Expression> newArgs = new ArrayList<>();
+            for (final Expression arg : callNode.getArgs()) {
+                if (arg instanceof IdentNode && ARGUMENTS.equals(((IdentNode)arg).getName())) {
+                    newArgs.addAll(newParams);
+                } else {
+                    newArgs.add(arg);
+                }
+            }
+
+            changed.add(lc.getCurrentFunction().getId());
+
+            final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall();
+
+            log.fine("Transformed ",
+                    callNode,
+                    " from apply to call => ",
+                    newCallNode,
+                    " in ",
+                    DebugLogger.quote(lc.getCurrentFunction().getName()));
+
+            return newCallNode;
+        }
+
+        return callNode;
+    }
+
+    private boolean pushExplodedArgs(final FunctionNode functionNode) {
+        int start = 0;
+
+        final MethodType actualCallSiteType = compiler.getCallSiteType(functionNode);
+        if (actualCallSiteType == null) {
+            return false;
+        }
+        assert actualCallSiteType.parameterType(actualCallSiteType.parameterCount() - 1) != Object[].class : "error vararg callsite passed to apply2call " + functionNode.getName() + " " + actualCallSiteType;
+
+        final TypeMap ptm = compiler.getTypeMap();
+        if (ptm.needsCallee()) {
+            start++;
+        }
+
+        start++; //we always uses this
+
+        final List<IdentNode> params    = functionNode.getParameters();
+        final List<IdentNode> newParams = new ArrayList<>();
+        final long to = Math.max(params.size(), actualCallSiteType.parameterCount() - start);
+        for (int i = 0; i < to; i++) {
+            if (i >= params.size()) {
+                newParams.add(new IdentNode(functionNode.getToken(), functionNode.getFinish(), EXPLODED_ARGUMENT_PREFIX.symbolName() + (i)));
+            } else {
+                newParams.add(params.get(i));
+            }
+        }
+
+        explodedArguments.push(newParams);
+        return true;
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        if (!USE_APPLY2CALL) {
+            return false;
+        }
+
+        if (!Global.instance().isSpecialNameValid("apply")) {
+            log.fine("Apply transform disabled: apply/call overridden");
+            assert !Global.instance().isSpecialNameValid("call") : "call and apply should have the same SwitchPoint";
+            return false;
+        }
+
+        if (!compiler.isOnDemandCompilation()) {
+            return false;
+        }
+
+        if (functionNode.hasEval()) {
+            return false;
+        }
+
+        if (argumentsEscape(functionNode)) {
+            return false;
+        }
+
+        return pushExplodedArgs(functionNode);
+    }
+
+    /**
+     * Try to do the apply to call transformation
+     * @return true if successful, false otherwise
+     */
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode0) {
+        FunctionNode newFunctionNode = functionNode0;
+        final String functionName = newFunctionNode.getName();
+
+        if (changed.contains(newFunctionNode.getId())) {
+            newFunctionNode = newFunctionNode.clearFlag(lc, FunctionNode.USES_ARGUMENTS).
+                    setFlag(lc, FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION).
+                    setParameters(lc, explodedArguments.peek());
+
+            if (log.isEnabled()) {
+                log.info("Successfully specialized apply to call in '",
+                        functionName,
+                        " params=",
+                        explodedArguments.peek(),
+                        "' id=",
+                        newFunctionNode.getId(),
+                        " source=",
+                        newFunctionNode.getSource().getURL());
+            }
+        }
+
+        explodedArguments.pop();
+
+        return newFunctionNode;
+    }
+
+    private static boolean isApply(final CallNode callNode) {
+        final Expression f = callNode.getFunction();
+        return f instanceof AccessNode && "apply".equals(((AccessNode)f).getProperty());
+    }
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java b/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java
new file mode 100644
index 0000000..a45a362
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/AssignSymbols.java
@@ -0,0 +1,958 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
+import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
+import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX;
+import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
+import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
+import static jdk.nashorn.internal.ir.Symbol.HAS_OBJECT_VALUE;
+import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF;
+import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL;
+import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
+import static jdk.nashorn.internal.ir.Symbol.IS_LET;
+import static jdk.nashorn.internal.ir.Symbol.IS_PARAM;
+import static jdk.nashorn.internal.ir.Symbol.IS_PROGRAM_LEVEL;
+import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE;
+import static jdk.nashorn.internal.ir.Symbol.IS_THIS;
+import static jdk.nashorn.internal.ir.Symbol.IS_VAR;
+import static jdk.nashorn.internal.ir.Symbol.KINDMASK;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Set;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LexicalContextNode;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.RuntimeNode.Request;
+import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.WithNode;
+import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * This visitor assigns symbols to identifiers denoting variables. It does few more minor calculations that are only
+ * possible after symbols have been assigned; such is the transformation of "delete" and "typeof" operators into runtime
+ * nodes and counting of number of properties assigned to "this" in constructor functions. This visitor is also notable
+ * for what it doesn't do, most significantly it does no type calculations as in JavaScript variables can change types
+ * during runtime and as such symbols don't have types. Calculation of expression types is performed by a separate
+ * visitor.
+ */
+@Logger(name="symbols")
+final class AssignSymbols extends NodeOperatorVisitor<LexicalContext> implements Loggable {
+    private final DebugLogger log;
+    private final boolean     debug;
+
+    private static boolean isParamOrVar(final IdentNode identNode) {
+        final Symbol symbol = identNode.getSymbol();
+        return symbol.isParam() || symbol.isVar();
+    }
+
+    private static String name(final Node node) {
+        final String cn = node.getClass().getName();
+        final int lastDot = cn.lastIndexOf('.');
+        if (lastDot == -1) {
+            return cn;
+        }
+        return cn.substring(lastDot + 1);
+    }
+
+    /**
+     * Checks if various symbols that were provisionally marked as needing a slot ended up unused, and marks them as not
+     * needing a slot after all.
+     * @param functionNode the function node
+     * @return the passed in node, for easy chaining
+     */
+    private static FunctionNode removeUnusedSlots(final FunctionNode functionNode) {
+        if (!functionNode.needsCallee()) {
+            functionNode.compilerConstant(CALLEE).setNeedsSlot(false);
+        }
+        if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
+            functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
+        }
+        if (!functionNode.usesReturnSymbol()) {
+            functionNode.compilerConstant(RETURN).setNeedsSlot(false);
+        }
+        // Named function expressions that end up not referencing themselves won't need a local slot for the self symbol.
+        if(!functionNode.isDeclared() && !functionNode.usesSelfSymbol() && !functionNode.isAnonymous()) {
+            final Symbol selfSymbol = functionNode.getBody().getExistingSymbol(functionNode.getIdent().getName());
+            if(selfSymbol != null) {
+                if(selfSymbol.isFunctionSelf()) {
+                    selfSymbol.setNeedsSlot(false);
+                    selfSymbol.clearFlag(Symbol.IS_VAR);
+                }
+            } else {
+                assert functionNode.isProgram();
+            }
+        }
+        return functionNode;
+    }
+
+    private final Deque<Set<String>> thisProperties = new ArrayDeque<>();
+    private final Map<String, Symbol> globalSymbols = new HashMap<>(); //reuse the same global symbol
+    private final Compiler compiler;
+
+    public AssignSymbols(final Compiler compiler) {
+        super(new LexicalContext());
+        this.compiler = compiler;
+        this.log   = initLogger(compiler.getContext());
+        this.debug = log.isEnabled();
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    /**
+     * Define symbols for all variable declarations at the top of the function scope. This way we can get around
+     * problems like
+     *
+     * while (true) {
+     *   break;
+     *   if (true) {
+     *     var s;
+     *   }
+     * }
+     *
+     * to an arbitrary nesting depth.
+     *
+     * see NASHORN-73
+     *
+     * @param functionNode the FunctionNode we are entering
+     * @param body the body of the FunctionNode we are entering
+     */
+    private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
+        // This visitor will assign symbol to all declared variables, except function declarations (which are taken care
+        // in a separate step above) and "var" declarations in for loop initializers.
+        //
+        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public boolean enterFunctionNode(final FunctionNode nestedFn) {
+                // Don't descend into nested functions
+                return false;
+            }
+
+            @Override
+            public Node leaveVarNode(final VarNode varNode) {
+                if (varNode.isStatement()) {
+                    final IdentNode ident  = varNode.getName();
+                    final Symbol    symbol = defineSymbol(body, ident.getName(), IS_VAR);
+                    functionNode.addDeclaredSymbol(symbol);
+                    if (varNode.isFunctionDeclaration()) {
+                        symbol.setIsFunctionDeclaration();
+                    }
+                    return varNode.setName(ident.setSymbol(symbol));
+                }
+                return varNode;
+            }
+        });
+    }
+
+    private IdentNode compilerConstantIdentifier(final CompilerConstants cc) {
+        return createImplicitIdentifier(cc.symbolName()).setSymbol(lc.getCurrentFunction().compilerConstant(cc));
+    }
+
+    /**
+     * Creates an ident node for an implicit identifier within the function (one not declared in the script source
+     * code). These identifiers are defined with function's token and finish.
+     * @param name the name of the identifier
+     * @return an ident node representing the implicit identifier.
+     */
+    private IdentNode createImplicitIdentifier(final String name) {
+        final FunctionNode fn = lc.getCurrentFunction();
+        return new IdentNode(fn.getToken(), fn.getFinish(), name);
+    }
+
+    private Symbol createSymbol(final String name, final int flags) {
+        if ((flags & Symbol.KINDMASK) == IS_GLOBAL) {
+            //reuse global symbols so they can be hashed
+            Symbol global = globalSymbols.get(name);
+            if (global == null) {
+                global = new Symbol(name, flags);
+                globalSymbols.put(name, global);
+            }
+            return global;
+        }
+        return new Symbol(name, flags);
+    }
+
+    /**
+     * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
+     * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function
+     * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
+     *
+     * @param name the ident node identifying the variable to initialize
+     * @param initConstant the compiler constant it is initialized to
+     * @param fn the function node the assignment is for
+     * @return a var node with the appropriate assignment
+     */
+    private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
+        final IdentNode init = compilerConstantIdentifier(initConstant);
+        assert init.getSymbol() != null && init.getSymbol().isBytecodeLocal();
+
+        final VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);
+
+        final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
+        assert nameSymbol != null;
+
+        return (VarNode)synthVar.setName(name.setSymbol(nameSymbol)).accept(this);
+    }
+
+    private FunctionNode createSyntheticInitializers(final FunctionNode functionNode) {
+        final List<VarNode> syntheticInitializers = new ArrayList<>(2);
+
+        // Must visit the new var nodes in the context of the body. We could also just set the new statements into the
+        // block and then revisit the entire block, but that seems to be too much double work.
+        final Block body = functionNode.getBody();
+        lc.push(body);
+        try {
+            if (functionNode.usesSelfSymbol()) {
+                // "var fn = :callee"
+                syntheticInitializers.add(createSyntheticInitializer(functionNode.getIdent(), CALLEE, functionNode));
+            }
+
+            if (functionNode.needsArguments()) {
+                // "var arguments = :arguments"
+                syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
+                        ARGUMENTS, functionNode));
+            }
+
+            if (syntheticInitializers.isEmpty()) {
+                return functionNode;
+            }
+
+            for(final ListIterator<VarNode> it = syntheticInitializers.listIterator(); it.hasNext();) {
+                it.set((VarNode)it.next().accept(this));
+            }
+        } finally {
+            lc.pop(body);
+        }
+
+        final List<Statement> stmts = body.getStatements();
+        final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
+        newStatements.addAll(syntheticInitializers);
+        newStatements.addAll(stmts);
+        return functionNode.setBody(lc, body.setStatements(lc, newStatements));
+    }
+
+    private Symbol defineGlobalSymbol(final Block block, final String name) {
+        return defineSymbol(block, name, IS_GLOBAL);
+    }
+
+    /**
+     * Defines a new symbol in the given block.
+     *
+     * @param block        the block in which to define the symbol
+     * @param name         name of symbol.
+     * @param symbolFlags  Symbol flags.
+     *
+     * @return Symbol for given name or null for redefinition.
+     */
+    private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) {
+        int    flags  = symbolFlags;
+        Symbol symbol = findSymbol(block, name); // Locate symbol.
+        final boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
+
+        // Global variables are implicitly always scope variables too.
+        if (isGlobal) {
+            flags |= IS_SCOPE;
+        }
+
+        if (lc.getCurrentFunction().isProgram()) {
+            flags |= IS_PROGRAM_LEVEL;
+        }
+
+        final boolean isParam = (flags & KINDMASK) == IS_PARAM;
+        final boolean isVar =   (flags & KINDMASK) == IS_VAR;
+
+        final FunctionNode function = lc.getFunction(block);
+        if (symbol != null) {
+            // Symbol was already defined. Check if it needs to be redefined.
+            if (isParam) {
+                if (!isLocal(function, symbol)) {
+                    // Not defined in this function. Create a new definition.
+                    symbol = null;
+                } else if (symbol.isParam()) {
+                    // Duplicate parameter. Null return will force an error.
+                    throw new AssertionError("duplicate parameter");
+                }
+            } else if (isVar) {
+                if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) {
+                    // Always create a new definition.
+                    symbol = null;
+                } else {
+                    // Not defined in this function. Create a new definition.
+                    if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
+                        symbol = null;
+                    }
+                }
+            }
+        }
+
+        if (symbol == null) {
+            // If not found, then create a new one.
+            Block symbolBlock;
+
+            // Determine where to create it.
+            if (isVar && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
+                symbolBlock = block; //internal vars are always defined in the block closest to them
+            } else if (isGlobal) {
+                symbolBlock = lc.getOutermostFunction().getBody();
+            } else {
+                symbolBlock = lc.getFunctionBody(function);
+            }
+
+            // Create and add to appropriate block.
+            symbol = createSymbol(name, flags);
+            symbolBlock.putSymbol(lc, symbol);
+
+            if ((flags & IS_SCOPE) == 0) {
+                // Initial assumption; symbol can lose its slot later
+                symbol.setNeedsSlot(true);
+            }
+        } else if (symbol.less(flags)) {
+            symbol.setFlags(flags);
+        }
+
+        return symbol;
+    }
+
+    private <T extends Node> T end(final T node) {
+        return end(node, true);
+    }
+
+    private <T extends Node> T end(final T node, final boolean printNode) {
+        if (debug) {
+            final StringBuilder sb = new StringBuilder();
+
+            sb.append("[LEAVE ").
+                append(name(node)).
+                append("] ").
+                append(printNode ? node.toString() : "").
+                append(" in '").
+                append(lc.getCurrentFunction().getName()).
+                append('\'');
+
+            if (node instanceof IdentNode) {
+                final Symbol symbol = ((IdentNode)node).getSymbol();
+                if (symbol == null) {
+                    sb.append(" <NO SYMBOL>");
+                } else {
+                    sb.append(" <symbol=").append(symbol).append('>');
+                }
+            }
+
+            log.unindent();
+            log.info(sb);
+        }
+
+        return node;
+    }
+
+    @Override
+    public boolean enterBlock(final Block block) {
+        start(block);
+        block.clearSymbols();
+
+        if (lc.isFunctionBody()) {
+            enterFunctionBody();
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean enterCatchNode(final CatchNode catchNode) {
+        final IdentNode exception = catchNode.getException();
+        final Block     block     = lc.getCurrentBlock();
+
+        start(catchNode);
+
+        // define block-local exception variable
+        final String exname = exception.getName();
+        // If the name of the exception starts with ":e", this is a synthetic catch block, likely a catch-all. Its
+        // symbol is naturally internal, and should be treated as such.
+        final boolean isInternal = exname.startsWith(EXCEPTION_PREFIX.symbolName());
+        defineSymbol(block, exname, IS_VAR | IS_LET | (isInternal ? IS_INTERNAL : 0) | HAS_OBJECT_VALUE);
+
+        return true;
+    }
+
+    private void enterFunctionBody() {
+        final FunctionNode functionNode = lc.getCurrentFunction();
+        final Block body = lc.getCurrentBlock();
+
+        initFunctionWideVariables(functionNode, body);
+
+        if (functionNode.isProgram()) {
+            initGlobalSymbols(body);
+        } else if (!functionNode.isDeclared() && !functionNode.isAnonymous()) {
+            // It's neither declared nor program - it's a function expression then; assign it a self-symbol unless it's
+            // anonymous.
+            final String name = functionNode.getIdent().getName();
+            assert name != null;
+            assert body.getExistingSymbol(name) == null;
+            defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF | HAS_OBJECT_VALUE);
+            if(functionNode.allVarsInScope()) { // basically, has deep eval
+                lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
+            }
+        }
+
+        acceptDeclarations(functionNode, body);
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        // TODO: once we have information on symbols used by nested functions, we can stop descending into nested
+        // functions with on-demand compilation, e.g. add
+        // if(!thisProperties.isEmpty() && env.isOnDemandCompilation()) {
+        //    return false;
+        // }
+        start(functionNode, false);
+
+        thisProperties.push(new HashSet<String>());
+
+        //an outermost function in our lexical context that is not a program
+        //is possible - it is a function being compiled lazily
+        if (functionNode.isDeclared()) {
+            final Iterator<Block> blocks = lc.getBlocks();
+            if (blocks.hasNext()) {
+                defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR | (functionNode.isAnonymous()? IS_INTERNAL : 0));
+            }
+        }
+
+        return true;
+    }
+
+    @Override
+    public boolean enterVarNode(final VarNode varNode) {
+        start(varNode);
+        defineSymbol(lc.getCurrentBlock(), varNode.getName().getName(), IS_VAR | (lc.getCurrentFunction().isProgram() ? IS_SCOPE : 0));
+        return true;
+    }
+
+    private Symbol exceptionSymbol() {
+        return newObjectInternal(EXCEPTION_PREFIX);
+    }
+
+    /**
+     * This has to run before fix assignment types, store any type specializations for
+     * paramters, then turn then to objects for the generic version of this method
+     *
+     * @param functionNode functionNode
+     */
+    private FunctionNode finalizeParameters(final FunctionNode functionNode) {
+        final List<IdentNode> newParams = new ArrayList<>();
+        final boolean isVarArg = functionNode.isVarArg();
+
+        final Block body = functionNode.getBody();
+        for (final IdentNode param : functionNode.getParameters()) {
+            final Symbol paramSymbol = body.getExistingSymbol(param.getName());
+            assert paramSymbol != null;
+            assert paramSymbol.isParam() : paramSymbol + " " + paramSymbol.getFlags();
+            newParams.add(param.setSymbol(paramSymbol));
+
+            // parameters should not be slots for a function that uses variable arity signature
+            if (isVarArg) {
+                paramSymbol.setNeedsSlot(false);
+            }
+        }
+
+        return functionNode.setParameters(lc, newParams);
+    }
+
+    /**
+     * Search for symbol in the lexical context starting from the given block.
+     * @param name Symbol name.
+     * @return Found symbol or null if not found.
+     */
+    private Symbol findSymbol(final Block block, final String name) {
+        for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
+            final Symbol symbol = blocks.next().getExistingSymbol(name);
+            if (symbol != null) {
+                return symbol;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Marks the current function as one using any global symbol. The function and all its parent functions will all be
+     * marked as needing parent scope.
+     * @see FunctionNode#needsParentScope()
+     */
+    private void functionUsesGlobalSymbol() {
+        for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) {
+            lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
+        }
+    }
+
+    /**
+     * Marks the current function as one using a scoped symbol. The block defining the symbol will be marked as needing
+     * its own scope to hold the variable. If the symbol is defined outside of the current function, it and all
+     * functions up to (but not including) the function containing the defining block will be marked as needing parent
+     * function scope.
+     * @see FunctionNode#needsParentScope()
+     */
+    private void functionUsesScopeSymbol(final Symbol symbol) {
+        final String name = symbol.getName();
+        for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) {
+            final LexicalContextNode node = contextNodeIter.next();
+            if (node instanceof Block) {
+                final Block block = (Block)node;
+                if (block.getExistingSymbol(name) != null) {
+                    assert lc.contains(block);
+                    lc.setBlockNeedsScope(block);
+                    break;
+                }
+            } else if (node instanceof FunctionNode) {
+                lc.setFlag(node, FunctionNode.USES_ANCESTOR_SCOPE);
+            }
+        }
+    }
+
+    /**
+     * Declares that the current function is using the symbol.
+     * @param symbol the symbol used by the current function.
+     */
+    private void functionUsesSymbol(final Symbol symbol) {
+        assert symbol != null;
+        if (symbol.isScope()) {
+            if (symbol.isGlobal()) {
+                functionUsesGlobalSymbol();
+            } else {
+                functionUsesScopeSymbol(symbol);
+            }
+        } else {
+            assert !symbol.isGlobal(); // Every global is also scope
+        }
+    }
+
+    private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) {
+        defineSymbol(block, cc.symbolName(), flags).setNeedsSlot(true);
+    }
+
+    private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
+        initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
+        initCompileConstant(THIS, body, IS_PARAM | IS_THIS | HAS_OBJECT_VALUE);
+
+        if (functionNode.isVarArg()) {
+            initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL | HAS_OBJECT_VALUE);
+            if (functionNode.needsArguments()) {
+                initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
+                defineSymbol(body, ARGUMENTS_VAR.symbolName(), IS_VAR | HAS_OBJECT_VALUE);
+            }
+        }
+
+        initParameters(functionNode, body);
+        initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | HAS_OBJECT_VALUE);
+        initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL);
+    }
+
+
+    /**
+     * Move any properties from the global map into the scope of this function (which must be a program function).
+     * @param block the function node body for which to init scope vars
+     */
+    private void initGlobalSymbols(final Block block) {
+        final PropertyMap map = Context.getGlobalMap();
+
+        for (final Property property : map.getProperties()) {
+            final Symbol symbol = defineGlobalSymbol(block, property.getKey());
+            log.info("Added global symbol from property map ", symbol);
+        }
+    }
+
+    /**
+     * Initialize parameters for function node.
+     * @param functionNode the function node
+     */
+    private void initParameters(final FunctionNode functionNode, final Block body) {
+        final boolean isVarArg = functionNode.isVarArg();
+        final boolean scopeParams = functionNode.allVarsInScope() || isVarArg;
+        for (final IdentNode param : functionNode.getParameters()) {
+            final Symbol symbol = defineSymbol(body, param.getName(), IS_PARAM);
+            if(scopeParams) {
+                // NOTE: this "set is scope" is a poor substitute for clear expression of where the symbol is stored.
+                // It will force creation of scopes where they would otherwise not necessarily be needed (functions
+                // using arguments object and other variable arity functions). Tracked by JDK-8038942.
+                symbol.setIsScope();
+                assert symbol.hasSlot();
+                if(isVarArg) {
+                    symbol.setNeedsSlot(false);
+                }
+            }
+        }
+    }
+
+    /**
+     * Is the symbol local to (that is, defined in) the specified function?
+     * @param function the function
+     * @param symbol the symbol
+     * @return true if the symbol is defined in the specified function
+     */
+    private boolean isLocal(final FunctionNode function, final Symbol symbol) {
+        final FunctionNode definingFn = lc.getDefiningFunction(symbol);
+        assert definingFn != null;
+        return definingFn == function;
+    }
+
+    @Override
+    public Node leaveASSIGN(final BinaryNode binaryNode) {
+        // If we're assigning a property of the this object ("this.foo = ..."), record it.
+
+        final Expression lhs = binaryNode.lhs();
+        if (lhs instanceof AccessNode) {
+            final AccessNode accessNode = (AccessNode) lhs;
+            final Expression base = accessNode.getBase();
+            if (base instanceof IdentNode) {
+                final Symbol symbol = ((IdentNode)base).getSymbol();
+                if(symbol.isThis()) {
+                    thisProperties.peek().add(accessNode.getProperty());
+                }
+            }
+        }
+        return binaryNode;
+    }
+
+    @Override
+    public Node leaveBlock(final Block block) {
+        // It's not necessary to guard the marking of symbols as locals with this "if"condition for correctness, it's
+        // just an optimization -- runtime type calculation is not used when the compilation is not an on-demand
+        // optimistic compilation, so we can skip locals marking then.
+        if (compiler.useOptimisticTypes() && compiler.isOnDemandCompilation()) {
+            for (final Symbol symbol: block.getSymbols()) {
+                if (!symbol.isScope()) {
+                    assert symbol.isVar() || symbol.isParam();
+                    compiler.declareLocalSymbol(symbol.getName());
+                }
+            }
+        }
+        return block;
+    }
+
+    @Override
+    public Node leaveDELETE(final UnaryNode unaryNode) {
+        final FunctionNode currentFunctionNode = lc.getCurrentFunction();
+        final boolean      strictMode          = currentFunctionNode.isStrict();
+        final Expression   rhs                 = unaryNode.getExpression();
+        final Expression   strictFlagNode      = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this);
+
+        Request request = Request.DELETE;
+        final List<Expression> args = new ArrayList<>();
+
+        if (rhs instanceof IdentNode) {
+            final IdentNode ident = (IdentNode)rhs;
+            // If this is a declared variable or a function parameter, delete always fails (except for globals).
+            final String name = ident.getName();
+            final Symbol symbol = ident.getSymbol();
+            final boolean failDelete = strictMode || (!symbol.isScope() && (symbol.isParam() || (symbol.isVar() && !symbol.isProgramLevel())));
+
+            if (failDelete && symbol.isThis()) {
+                return LiteralNode.newInstance(unaryNode, true).accept(this);
+            }
+            final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
+
+            if (!failDelete) {
+                args.add(compilerConstantIdentifier(SCOPE));
+            }
+            args.add(literalNode);
+            args.add(strictFlagNode);
+
+            if (failDelete) {
+                request = Request.FAIL_DELETE;
+            }
+        } else if (rhs instanceof AccessNode) {
+            final Expression base     = ((AccessNode)rhs).getBase();
+            final String     property = ((AccessNode)rhs).getProperty();
+
+            args.add(base);
+            args.add((Expression)LiteralNode.newInstance(unaryNode, property).accept(this));
+            args.add(strictFlagNode);
+
+        } else if (rhs instanceof IndexNode) {
+            final IndexNode indexNode = (IndexNode)rhs;
+            final Expression base  = indexNode.getBase();
+            final Expression index = indexNode.getIndex();
+
+            args.add(base);
+            args.add(index);
+            args.add(strictFlagNode);
+
+        } else {
+            return LiteralNode.newInstance(unaryNode, true).accept(this);
+        }
+        return new RuntimeNode(unaryNode, request, args).accept(this);
+    }
+
+    @Override
+    public Node leaveForNode(final ForNode forNode) {
+        if (forNode.isForIn()) {
+            forNode.setIterator(newObjectInternal(ITERATOR_PREFIX)); //NASHORN-73
+        }
+
+        return end(forNode);
+    }
+
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+
+        return markProgramBlock(
+               removeUnusedSlots(
+               createSyntheticInitializers(
+               finalizeParameters(
+                       lc.applyTopFlags(functionNode))))
+                       .setThisProperties(lc, thisProperties.pop().size())
+                       .setState(lc, CompilationState.SYMBOLS_ASSIGNED));
+    }
+
+    @Override
+    public Node leaveIdentNode(final IdentNode identNode) {
+        final String name = identNode.getName();
+
+        if (identNode.isPropertyName()) {
+            return identNode;
+        }
+
+        final Block block = lc.getCurrentBlock();
+
+        Symbol symbol = findSymbol(block, name);
+
+        //If an existing symbol with the name is found, use that otherwise, declare a new one
+        if (symbol != null) {
+            log.info("Existing symbol = ", symbol);
+            if (symbol.isFunctionSelf()) {
+                final FunctionNode functionNode = lc.getDefiningFunction(symbol);
+                assert functionNode != null;
+                assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null;
+                lc.setFlag(functionNode, FunctionNode.USES_SELF_SYMBOL);
+            }
+
+            // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already)
+            maybeForceScope(symbol);
+        } else {
+            log.info("No symbol exists. Declare as global: ", symbol);
+            symbol = defineGlobalSymbol(block, name);
+            Symbol.setSymbolIsScope(lc, symbol);
+        }
+
+        functionUsesSymbol(symbol);
+
+        if (!identNode.isInitializedHere()) {
+            symbol.increaseUseCount();
+        }
+
+        return end(identNode.setSymbol(symbol));
+    }
+
+    @Override
+    public Node leaveSwitchNode(final SwitchNode switchNode) {
+        // We only need a symbol for the tag if it's not an integer switch node
+        if(!switchNode.isInteger()) {
+            switchNode.setTag(newObjectInternal(SWITCH_TAG_PREFIX));
+        }
+        return switchNode;
+    }
+
+    @Override
+    public Node leaveTryNode(final TryNode tryNode) {
+        tryNode.setException(exceptionSymbol());
+        if (tryNode.getFinallyBody() != null) {
+            tryNode.setFinallyCatchAll(exceptionSymbol());
+        }
+
+        end(tryNode);
+
+        return tryNode;
+    }
+
+    @Override
+    public Node leaveTYPEOF(final UnaryNode unaryNode) {
+        final Expression rhs = unaryNode.getExpression();
+
+        final List<Expression> args = new ArrayList<>();
+        if (rhs instanceof IdentNode && !isParamOrVar((IdentNode)rhs)) {
+            args.add(compilerConstantIdentifier(SCOPE));
+            args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
+        } else {
+            args.add(rhs);
+            args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
+        }
+
+        final Node runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args).accept(this);
+
+        end(unaryNode);
+
+        return runtimeNode;
+    }
+
+    private FunctionNode markProgramBlock(final FunctionNode functionNode) {
+        if (compiler.isOnDemandCompilation() || !functionNode.isProgram()) {
+            return functionNode;
+        }
+
+        assert functionNode.getId() == 1;
+        return functionNode.setBody(lc, functionNode.getBody().setFlag(lc, Block.IS_GLOBAL_SCOPE));
+    }
+
+    /**
+     * If the symbol isn't already a scope symbol, but it needs to be (see {@link #symbolNeedsToBeScope(Symbol)}, it is
+     * promoted to a scope symbol and its block marked as needing a scope.
+     * @param symbol the symbol that might be scoped
+     */
+    private void maybeForceScope(final Symbol symbol) {
+        if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) {
+            Symbol.setSymbolIsScope(lc, symbol);
+        }
+    }
+
+    private Symbol newInternal(final CompilerConstants cc, final int flags) {
+        return defineSymbol(lc.getCurrentBlock(), lc.getCurrentFunction().uniqueName(cc.symbolName()), IS_VAR | IS_INTERNAL | flags); //NASHORN-73
+    }
+
+    private Symbol newObjectInternal(final CompilerConstants cc) {
+        return newInternal(cc, HAS_OBJECT_VALUE);
+    }
+
+    private boolean start(final Node node) {
+        return start(node, true);
+    }
+
+    private boolean start(final Node node, final boolean printNode) {
+        if (debug) {
+            final StringBuilder sb = new StringBuilder();
+
+            sb.append("[ENTER ").
+                append(name(node)).
+                append("] ").
+                append(printNode ? node.toString() : "").
+                append(" in '").
+                append(lc.getCurrentFunction().getName()).
+                append("'");
+            log.info(sb);
+            log.indent();
+        }
+
+        return true;
+    }
+
+    /**
+     * Determines if the symbol has to be a scope symbol. In general terms, it has to be a scope symbol if it can only
+     * be reached from the current block by traversing a function node, a split node, or a with node.
+     * @param symbol the symbol checked for needing to be a scope symbol
+     * @return true if the symbol has to be a scope symbol.
+     */
+    private boolean symbolNeedsToBeScope(final Symbol symbol) {
+        if (symbol.isThis() || symbol.isInternal()) {
+            return false;
+        }
+
+        if (lc.getCurrentFunction().allVarsInScope()) {
+            return true;
+        }
+
+        boolean previousWasBlock = false;
+        for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
+            final LexicalContextNode node = it.next();
+            if (node instanceof FunctionNode || node instanceof SplitNode || isSplitArray(node)) {
+                // We reached the function boundary or a splitting boundary without seeing a definition for the symbol.
+                // It needs to be in scope.
+                return true;
+            } else if (node instanceof WithNode) {
+                if (previousWasBlock) {
+                    // We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately
+                    // preceded by a block, this means we're currently processing its expression, not its body,
+                    // therefore it doesn't count.
+                    return true;
+                }
+                previousWasBlock = false;
+            } else if (node instanceof Block) {
+                if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
+                    // We reached the block that defines the symbol without reaching either the function boundary, or a
+                    // WithNode. The symbol need not be scoped.
+                    return false;
+                }
+                previousWasBlock = true;
+            } else {
+                previousWasBlock = false;
+            }
+        }
+        throw new AssertionError();
+    }
+
+    private static boolean isSplitArray(final LexicalContextNode expr) {
+        if(!(expr instanceof ArrayLiteralNode)) {
+            return false;
+        }
+        final List<ArrayUnit> units = ((ArrayLiteralNode)expr).getUnits();
+        return !(units == null || units.isEmpty());
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java
deleted file mode 100644
index 61ccb71..0000000
--- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java
+++ /dev/null
@@ -1,1947 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
-import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.LITERAL_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SWITCH_TAG_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
-import static jdk.nashorn.internal.ir.Symbol.IS_ALWAYS_DEFINED;
-import static jdk.nashorn.internal.ir.Symbol.IS_CONSTANT;
-import static jdk.nashorn.internal.ir.Symbol.IS_FUNCTION_SELF;
-import static jdk.nashorn.internal.ir.Symbol.IS_GLOBAL;
-import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
-import static jdk.nashorn.internal.ir.Symbol.IS_LET;
-import static jdk.nashorn.internal.ir.Symbol.IS_PARAM;
-import static jdk.nashorn.internal.ir.Symbol.IS_SCOPE;
-import static jdk.nashorn.internal.ir.Symbol.IS_THIS;
-import static jdk.nashorn.internal.ir.Symbol.IS_VAR;
-import static jdk.nashorn.internal.ir.Symbol.KINDMASK;
-
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Deque;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.AccessNode;
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.CallNode;
-import jdk.nashorn.internal.ir.CaseNode;
-import jdk.nashorn.internal.ir.CatchNode;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.IndexNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.LexicalContextNode;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ObjectNode;
-import jdk.nashorn.internal.ir.ReturnNode;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.RuntimeNode.Request;
-import jdk.nashorn.internal.ir.Statement;
-import jdk.nashorn.internal.ir.SwitchNode;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.TemporarySymbols;
-import jdk.nashorn.internal.ir.TernaryNode;
-import jdk.nashorn.internal.ir.TryNode;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-
-/**
- * This is the attribution pass of the code generator. Attr takes Lowered IR,
- * that is, IR where control flow has been computed and high level to low level
- * substitions for operations have been performed.
- *
- * After Attr, every symbol will have a conservative correct type.
- *
- * Any expression that requires temporary storage as part of computation will
- * also be detected here and give a temporary symbol
- *
- * Types can be narrowed after Attr by Access Specialization in FinalizeTypes,
- * but in general, this is where the main symbol type information is
- * computed.
- */
-
-final class Attr extends NodeOperatorVisitor<LexicalContext> {
-
-    /**
-     * Local definitions in current block (to discriminate from function
-     * declarations always defined in the function scope. This is for
-     * "can be undefined" analysis.
-     */
-    private final Deque<Set<String>> localDefs;
-
-    /**
-     * Local definitions in current block to guard against cases like
-     * NASHORN-467 when things can be undefined as they are used before
-     * their local var definition. *sigh* JavaScript...
-     */
-    private final Deque<Set<String>> localUses;
-
-    private final Deque<Type> returnTypes;
-
-    private int catchNestingLevel;
-
-    private static final DebugLogger LOG   = new DebugLogger("attr");
-    private static final boolean     DEBUG = LOG.isEnabled();
-
-    private final TemporarySymbols temporarySymbols;
-
-    /**
-     * Constructor.
-     */
-    Attr(final TemporarySymbols temporarySymbols) {
-        super(new LexicalContext());
-        this.temporarySymbols = temporarySymbols;
-        this.localDefs   = new ArrayDeque<>();
-        this.localUses   = new ArrayDeque<>();
-        this.returnTypes = new ArrayDeque<>();
-    }
-
-    @Override
-    protected boolean enterDefault(final Node node) {
-        return start(node);
-    }
-
-    @Override
-    protected Node leaveDefault(final Node node) {
-        return end(node);
-    }
-
-    @Override
-    public Node leaveAccessNode(final AccessNode accessNode) {
-        //While Object type is assigned here, Access Specialization in FinalizeTypes may narrow this, that
-        //is why we can't set the access node base to be an object here, that will ruin access specialization
-        //for example for a.x | 17.
-        return end(ensureSymbol(Type.OBJECT, accessNode));
-    }
-
-    private void initFunctionWideVariables(final FunctionNode functionNode, final Block body) {
-        initCompileConstant(CALLEE, body, IS_PARAM | IS_INTERNAL);
-        initCompileConstant(THIS, body, IS_PARAM | IS_THIS, Type.OBJECT);
-
-        if (functionNode.isVarArg()) {
-            initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL);
-            if (functionNode.needsArguments()) {
-                initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
-                final String argumentsName = ARGUMENTS_VAR.symbolName();
-                newType(defineSymbol(body, argumentsName, IS_VAR | IS_ALWAYS_DEFINED), Type.typeFor(ARGUMENTS_VAR.type()));
-                addLocalDef(argumentsName);
-            }
-        }
-
-        initParameters(functionNode, body);
-        initCompileConstant(SCOPE, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED);
-        initCompileConstant(RETURN, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED, Type.OBJECT);
-    }
-
-
-    /**
-     * This pushes all declarations (except for non-statements, i.e. for
-     * node temporaries) to the top of the function scope. This way we can
-     * get around problems like
-     *
-     * while (true) {
-     *   break;
-     *   if (true) {
-     *     var s;
-     *   }
-     * }
-     *
-     * to an arbitrary nesting depth.
-     *
-     * see NASHORN-73
-     *
-     * @param functionNode the FunctionNode we are entering
-     * @param body the body of the FunctionNode we are entering
-     */
-    private void acceptDeclarations(final FunctionNode functionNode, final Block body) {
-        // This visitor will assign symbol to all declared variables, except function declarations (which are taken care
-        // in a separate step above) and "var" declarations in for loop initializers.
-        //
-        // It also handles the case that a variable can be undefined, e.g
-        // if (cond) {
-        //    x = x.y;
-        // }
-        // var x = 17;
-        //
-        // by making sure that no identifier has been found earlier in the body than the
-        // declaration - if such is the case the identifier is flagged as caBeUndefined to
-        // be safe if it turns into a local var. Otherwise corrupt bytecode results
-
-        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            private final Set<String> uses = new HashSet<>();
-            private final Set<String> canBeUndefined = new HashSet<>();
-
-            @Override
-            public boolean enterFunctionNode(final FunctionNode nestedFn) {
-                return false;
-            }
-
-            @Override
-            public Node leaveIdentNode(final IdentNode identNode) {
-                uses.add(identNode.getName());
-                return identNode;
-            }
-
-            @Override
-            public boolean enterVarNode(final VarNode varNode) {
-                final String name = varNode.getName().getName();
-                //if this is used before the var node, the var node symbol needs to be tagged as can be undefined
-                if (uses.contains(name)) {
-                    canBeUndefined.add(name);
-                }
-
-                // all uses of the declared varnode inside the var node are potentially undefined
-                // however this is a bit conservative as e.g. var x = 17; var x = 1 + x; does work
-                if (!varNode.isFunctionDeclaration() && varNode.getInit() != null) {
-                    varNode.getInit().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                       @Override
-                       public boolean enterIdentNode(final IdentNode identNode) {
-                           if (name.equals(identNode.getName())) {
-                              canBeUndefined.add(name);
-                           }
-                           return false;
-                       }
-                    });
-                }
-
-                return true;
-            }
-
-            @Override
-            public Node leaveVarNode(final VarNode varNode) {
-                // any declared symbols that aren't visited need to be typed as well, hence the list
-                if (varNode.isStatement()) {
-                    final IdentNode ident  = varNode.getName();
-                    final Symbol    symbol = defineSymbol(body, ident.getName(), IS_VAR);
-                    if (canBeUndefined.contains(ident.getName())) {
-                        symbol.setType(Type.OBJECT);
-                        symbol.setCanBeUndefined();
-                    }
-                    functionNode.addDeclaredSymbol(symbol);
-                    if (varNode.isFunctionDeclaration()) {
-                        newType(symbol, FunctionNode.FUNCTION_TYPE);
-                        symbol.setIsFunctionDeclaration();
-                    }
-                    return varNode.setName((IdentNode)ident.setSymbol(lc, symbol));
-                }
-
-                return varNode;
-            }
-        });
-    }
-
-    private void enterFunctionBody() {
-
-        final FunctionNode functionNode = lc.getCurrentFunction();
-        final Block body = lc.getCurrentBlock();
-
-        initFunctionWideVariables(functionNode, body);
-
-        if (functionNode.isProgram()) {
-            initFromPropertyMap(body);
-        } else if (!functionNode.isDeclared()) {
-            // It's neither declared nor program - it's a function expression then; assign it a self-symbol.
-            assert functionNode.getSymbol() == null;
-
-            final boolean anonymous = functionNode.isAnonymous();
-            final String  name      = anonymous ? null : functionNode.getIdent().getName();
-            if (!(anonymous || body.getExistingSymbol(name) != null)) {
-                assert !anonymous && name != null;
-                newType(defineSymbol(body, name, IS_VAR | IS_FUNCTION_SELF), Type.OBJECT);
-            }
-        }
-
-        acceptDeclarations(functionNode, body);
-    }
-
-    @Override
-    public boolean enterBlock(final Block block) {
-        start(block);
-        //ensure that we don't use information from a previous compile. This is very ugly TODO
-        //the symbols in the block should really be stateless
-        block.clearSymbols();
-
-        if (lc.isFunctionBody()) {
-            enterFunctionBody();
-        }
-        pushLocalsBlock();
-
-        return true;
-    }
-
-    @Override
-    public Node leaveBlock(final Block block) {
-        popLocals();
-        return end(block);
-    }
-
-    @Override
-    public boolean enterCallNode(final CallNode callNode) {
-        return start(callNode);
-    }
-
-    @Override
-    public Node leaveCallNode(final CallNode callNode) {
-        return end(ensureSymbol(callNode.getType(), callNode));
-    }
-
-    @Override
-    public boolean enterCatchNode(final CatchNode catchNode) {
-        final IdentNode exception = catchNode.getException();
-        final Block     block     = lc.getCurrentBlock();
-
-        start(catchNode);
-        catchNestingLevel++;
-
-        // define block-local exception variable
-        final String exname = exception.getName();
-        final Symbol def = defineSymbol(block, exname, IS_VAR | IS_LET | IS_ALWAYS_DEFINED);
-        newType(def, Type.OBJECT); //we can catch anything, not just ecma exceptions
-
-        addLocalDef(exname);
-
-        return true;
-    }
-
-    @Override
-    public Node leaveCatchNode(final CatchNode catchNode) {
-        final IdentNode exception = catchNode.getException();
-        final Block  block        = lc.getCurrentBlock();
-        final Symbol symbol       = findSymbol(block, exception.getName());
-
-        catchNestingLevel--;
-
-        assert symbol != null;
-        return end(catchNode.setException((IdentNode)exception.setSymbol(lc, symbol)));
-    }
-
-    /**
-     * Declare the definition of a new symbol.
-     *
-     * @param name         Name of symbol.
-     * @param symbolFlags  Symbol flags.
-     *
-     * @return Symbol for given name or null for redefinition.
-     */
-    private Symbol defineSymbol(final Block block, final String name, final int symbolFlags) {
-        int     flags    = symbolFlags;
-        Symbol  symbol   = findSymbol(block, name); // Locate symbol.
-        boolean isGlobal = (flags & KINDMASK) == IS_GLOBAL;
-
-        if (isGlobal) {
-            flags |= IS_SCOPE;
-        }
-
-        final FunctionNode function = lc.getFunction(block);
-        if (symbol != null) {
-            // Symbol was already defined. Check if it needs to be redefined.
-            if ((flags & KINDMASK) == IS_PARAM) {
-                if (!isLocal(function, symbol)) {
-                    // Not defined in this function. Create a new definition.
-                    symbol = null;
-                } else if (symbol.isParam()) {
-                    // Duplicate parameter. Null return will force an error.
-                    assert false : "duplicate parameter";
-                    return null;
-                }
-            } else if ((flags & KINDMASK) == IS_VAR) {
-                if ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET) {
-                    // Always create a new definition.
-                    symbol = null;
-                } else {
-                    // Not defined in this function. Create a new definition.
-                    if (!isLocal(function, symbol) || symbol.less(IS_VAR)) {
-                        symbol = null;
-                    }
-                }
-            }
-        }
-
-        if (symbol == null) {
-            // If not found, then create a new one.
-            Block symbolBlock;
-
-            // Determine where to create it.
-            if ((flags & Symbol.KINDMASK) == IS_VAR && ((flags & IS_INTERNAL) == IS_INTERNAL || (flags & IS_LET) == IS_LET)) {
-                symbolBlock = block; //internal vars are always defined in the block closest to them
-            } else if (isGlobal) {
-                symbolBlock = lc.getOutermostFunction().getBody();
-            } else {
-                symbolBlock = lc.getFunctionBody(function);
-            }
-
-            // Create and add to appropriate block.
-            symbol = new Symbol(name, flags);
-            symbolBlock.putSymbol(lc, symbol);
-
-            if ((flags & Symbol.KINDMASK) != IS_GLOBAL) {
-                symbol.setNeedsSlot(true);
-            }
-        } else if (symbol.less(flags)) {
-            symbol.setFlags(flags);
-        }
-
-        return symbol;
-    }
-
-    @Override
-    public boolean enterFunctionNode(final FunctionNode functionNode) {
-        start(functionNode, false);
-
-        if (functionNode.isLazy()) {
-            return false;
-        }
-
-        //an outermost function in our lexical context that is not a program (runScript)
-        //is possible - it is a function being compiled lazily
-        if (functionNode.isDeclared()) {
-            final Iterator<Block> blocks = lc.getBlocks();
-            if (blocks.hasNext()) {
-                defineSymbol(blocks.next(), functionNode.getIdent().getName(), IS_VAR);
-            }
-        }
-
-        returnTypes.push(functionNode.getReturnType());
-        pushLocalsFunction();
-
-        return true;
-    }
-
-    @Override
-    public Node leaveFunctionNode(final FunctionNode functionNode) {
-        FunctionNode newFunctionNode = functionNode;
-
-        final Block body = newFunctionNode.getBody();
-
-        //look for this function in the parent block
-        if (functionNode.isDeclared()) {
-            final Iterator<Block> blocks = lc.getBlocks();
-            if (blocks.hasNext()) {
-                newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, findSymbol(blocks.next(), functionNode.getIdent().getName()));
-            }
-        } else if (!functionNode.isProgram()) {
-            final boolean anonymous = functionNode.isAnonymous();
-            final String  name      = anonymous ? null : functionNode.getIdent().getName();
-            if (anonymous || body.getExistingSymbol(name) != null) {
-                newFunctionNode = (FunctionNode)ensureSymbol(FunctionNode.FUNCTION_TYPE, newFunctionNode);
-            } else {
-                assert name != null;
-                final Symbol self = body.getExistingSymbol(name);
-                assert self != null && self.isFunctionSelf();
-                newFunctionNode = (FunctionNode)newFunctionNode.setSymbol(lc, body.getExistingSymbol(name));
-            }
-        }
-
-        //unknown parameters are promoted to object type.
-        if (newFunctionNode.hasLazyChildren()) {
-            //the final body has already been assigned as we have left the function node block body by now
-            objectifySymbols(body);
-        }
-        newFunctionNode = finalizeParameters(newFunctionNode);
-        newFunctionNode = finalizeTypes(newFunctionNode);
-        for (final Symbol symbol : newFunctionNode.getDeclaredSymbols()) {
-            if (symbol.getSymbolType().isUnknown()) {
-                symbol.setType(Type.OBJECT);
-                symbol.setCanBeUndefined();
-            }
-        }
-
-        List<VarNode> syntheticInitializers = null;
-
-        if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) {
-            syntheticInitializers = new ArrayList<>(2);
-            LOG.info("Accepting self symbol init for ", newFunctionNode.getName());
-            // "var fn = :callee"
-            syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode));
-        }
-
-        if (newFunctionNode.needsArguments()) {
-            if (syntheticInitializers == null) {
-                syntheticInitializers = new ArrayList<>(1);
-            }
-            // "var arguments = :arguments"
-            syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()),
-                    ARGUMENTS, newFunctionNode));
-        }
-
-        if (syntheticInitializers != null) {
-            final List<Statement> stmts = newFunctionNode.getBody().getStatements();
-            final List<Statement> newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size());
-            newStatements.addAll(syntheticInitializers);
-            newStatements.addAll(stmts);
-            newFunctionNode = newFunctionNode.setBody(lc, newFunctionNode.getBody().setStatements(lc, newStatements));
-        }
-
-        if (returnTypes.peek().isUnknown()) {
-            LOG.info("Unknown return type promoted to object");
-            newFunctionNode = newFunctionNode.setReturnType(lc, Type.OBJECT);
-        }
-        final Type returnType = returnTypes.pop();
-        newFunctionNode = newFunctionNode.setReturnType(lc, returnType.isUnknown() ? Type.OBJECT : returnType);
-        newFunctionNode = newFunctionNode.setState(lc, CompilationState.ATTR);
-
-        popLocals();
-
-        end(newFunctionNode, false);
-
-        return newFunctionNode;
-    }
-
-    /**
-     * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically
-     * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function
-     * expressions as well as for assignment of {@code :arguments} to {@code arguments}.
-     *
-     * @param name the ident node identifying the variable to initialize
-     * @param initConstant the compiler constant it is initialized to
-     * @param fn the function node the assignment is for
-     * @return a var node with the appropriate assignment
-     */
-    private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) {
-        final IdentNode init = compilerConstant(initConstant);
-        assert init.getSymbol() != null && init.getSymbol().hasSlot();
-
-        VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init);
-
-        final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName());
-        assert nameSymbol != null;
-
-        return synthVar.setName((IdentNode)name.setSymbol(lc, nameSymbol));
-    }
-
-    @Override
-    public Node leaveIdentNode(final IdentNode identNode) {
-        final String name = identNode.getName();
-
-        if (identNode.isPropertyName()) {
-            // assign a pseudo symbol to property name
-            final Symbol pseudoSymbol = pseudoSymbol(name);
-            LOG.info("IdentNode is property name -> assigning pseudo symbol ", pseudoSymbol);
-            LOG.unindent();
-            return end(identNode.setSymbol(lc, pseudoSymbol));
-        }
-
-        final Block block = lc.getCurrentBlock();
-
-        Symbol symbol = findSymbol(block, name);
-
-        //If an existing symbol with the name is found, use that otherwise, declare a new one
-        if (symbol != null) {
-            LOG.info("Existing symbol = ", symbol);
-            if (symbol.isFunctionSelf()) {
-                final FunctionNode functionNode = lc.getDefiningFunction(symbol);
-                assert functionNode != null;
-                assert lc.getFunctionBody(functionNode).getExistingSymbol(CALLEE.symbolName()) != null;
-                lc.setFlag(functionNode.getBody(), Block.NEEDS_SELF_SYMBOL);
-                newType(symbol, FunctionNode.FUNCTION_TYPE);
-            } else if (!identNode.isInitializedHere()) {
-                /*
-                 * See NASHORN-448, JDK-8016235
-                 *
-                 * Here is a use outside the local def scope
-                 * the inCatch check is a conservative approach to handle things that might have only been
-                 * defined in the try block, but with variable declarations, which due to JavaScript rules
-                 * have to be lifted up into the function scope outside the try block anyway, but as the
-                 * flow can fault at almost any place in the try block and get us to the catch block, all we
-                 * know is that we have a declaration, not a definition. This can be made better and less
-                 * conservative once we superimpose a CFG onto the AST.
-                 */
-                if (!isLocalDef(name) || inCatch()) {
-                    newType(symbol, Type.OBJECT);
-                    symbol.setCanBeUndefined();
-                }
-            }
-
-            // if symbol is non-local or we're in a with block, we need to put symbol in scope (if it isn't already)
-            maybeForceScope(symbol);
-        } else {
-            LOG.info("No symbol exists. Declare undefined: ", symbol);
-            symbol = defineSymbol(block, name, IS_GLOBAL);
-            // we have never seen this before, it can be undefined
-            newType(symbol, Type.OBJECT); // TODO unknown -we have explicit casts anyway?
-            symbol.setCanBeUndefined();
-            Symbol.setSymbolIsScope(lc, symbol);
-        }
-
-        setBlockScope(name, symbol);
-
-        if (!identNode.isInitializedHere()) {
-            symbol.increaseUseCount();
-        }
-        addLocalUse(identNode.getName());
-
-        return end(identNode.setSymbol(lc, symbol));
-    }
-
-    private boolean inCatch() {
-        return catchNestingLevel > 0;
-    }
-
-    /**
-     * If the symbol isn't already a scope symbol, and it is either not local to the current function, or it is being
-     * referenced from within a with block, we force it to be a scope symbol.
-     * @param symbol the symbol that might be scoped
-     */
-    private void maybeForceScope(final Symbol symbol) {
-        if (!symbol.isScope() && symbolNeedsToBeScope(symbol)) {
-            Symbol.setSymbolIsScope(lc, symbol);
-        }
-    }
-
-    private boolean symbolNeedsToBeScope(Symbol symbol) {
-        if (symbol.isThis() || symbol.isInternal()) {
-            return false;
-        }
-        boolean previousWasBlock = false;
-        for (final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
-            final LexicalContextNode node = it.next();
-            if (node instanceof FunctionNode) {
-                // We reached the function boundary without seeing a definition for the symbol - it needs to be in
-                // scope.
-                return true;
-            } else if (node instanceof WithNode) {
-                if (previousWasBlock) {
-                    // We reached a WithNode; the symbol must be scoped. Note that if the WithNode was not immediately
-                    // preceded by a block, this means we're currently processing its expression, not its body,
-                    // therefore it doesn't count.
-                    return true;
-                }
-                previousWasBlock = false;
-            } else if (node instanceof Block) {
-                if (((Block)node).getExistingSymbol(symbol.getName()) == symbol) {
-                    // We reached the block that defines the symbol without reaching either the function boundary, or a
-                    // WithNode. The symbol need not be scoped.
-                    return false;
-                }
-                previousWasBlock = true;
-            } else {
-                previousWasBlock = false;
-            }
-        }
-        throw new AssertionError();
-    }
-
-    private void setBlockScope(final String name, final Symbol symbol) {
-        assert symbol != null;
-        if (symbol.isGlobal()) {
-            setUsesGlobalSymbol();
-            return;
-        }
-
-        if (symbol.isScope()) {
-            Block scopeBlock = null;
-            for (final Iterator<LexicalContextNode> contextNodeIter = lc.getAllNodes(); contextNodeIter.hasNext(); ) {
-                final LexicalContextNode node = contextNodeIter.next();
-                if (node instanceof Block) {
-                    if (((Block)node).getExistingSymbol(name) != null) {
-                        scopeBlock = (Block)node;
-                        break;
-                    }
-                } else if (node instanceof FunctionNode) {
-                    lc.setFlag(node, FunctionNode.USES_ANCESTOR_SCOPE);
-                }
-            }
-
-            if (scopeBlock != null) {
-                assert lc.contains(scopeBlock);
-                lc.setBlockNeedsScope(scopeBlock);
-            }
-        }
-    }
-
-    /**
-     * Marks the current function as one using any global symbol. The function and all its parent functions will all be
-     * marked as needing parent scope.
-     * @see #needsParentScope()
-     */
-    private void setUsesGlobalSymbol() {
-        for (final Iterator<FunctionNode> fns = lc.getFunctions(); fns.hasNext();) {
-            lc.setFlag(fns.next(), FunctionNode.USES_ANCESTOR_SCOPE);
-        }
-    }
-
-    /**
-     * Search for symbol in the lexical context starting from the given block.
-     * @param name Symbol name.
-     * @return Found symbol or null if not found.
-     */
-    private Symbol findSymbol(final Block block, final String name) {
-        // Search up block chain to locate symbol.
-
-        for (final Iterator<Block> blocks = lc.getBlocks(block); blocks.hasNext();) {
-            // Find name.
-            final Symbol symbol = blocks.next().getExistingSymbol(name);
-            // If found then we are good.
-            if (symbol != null) {
-                return symbol;
-            }
-        }
-        return null;
-    }
-
-    @Override
-    public Node leaveIndexNode(final IndexNode indexNode) {
-        return end(ensureSymbol(Type.OBJECT, indexNode));
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public Node leaveLiteralNode(final LiteralNode literalNode) {
-        assert !literalNode.isTokenType(TokenType.THIS) : "tokentype for " + literalNode + " is this"; //guard against old dead code case. literal nodes should never inherit tokens
-        assert literalNode instanceof ArrayLiteralNode || !(literalNode.getValue() instanceof Node) : "literals with Node values not supported";
-        final Symbol symbol = new Symbol(lc.getCurrentFunction().uniqueName(LITERAL_PREFIX.symbolName()), IS_CONSTANT, literalNode.getType());
-        if (literalNode instanceof ArrayLiteralNode) {
-            ((ArrayLiteralNode)literalNode).analyze();
-        }
-        return end(literalNode.setSymbol(lc, symbol));
-    }
-
-    @Override
-    public boolean enterObjectNode(final ObjectNode objectNode) {
-        return start(objectNode);
-    }
-
-    @Override
-    public Node leaveObjectNode(final ObjectNode objectNode) {
-        return end(ensureSymbol(Type.OBJECT, objectNode));
-    }
-
-    @Override
-    public Node leaveReturnNode(final ReturnNode returnNode) {
-        final Expression expr = returnNode.getExpression();
-        final Type returnType;
-
-        if (expr != null) {
-            //we can't do parameter specialization if we return something that hasn't been typed yet
-            final Symbol symbol = expr.getSymbol();
-            if (expr.getType().isUnknown() && symbol.isParam()) {
-                symbol.setType(Type.OBJECT);
-            }
-
-            returnType = widestReturnType(returnTypes.pop(), symbol.getSymbolType());
-        } else {
-            returnType = Type.OBJECT; //undefined
-        }
-        LOG.info("Returntype is now ", returnType);
-        returnTypes.push(returnType);
-
-        end(returnNode);
-
-        return returnNode;
-    }
-
-    @Override
-    public Node leaveSwitchNode(final SwitchNode switchNode) {
-        Type type = Type.UNKNOWN;
-
-        final List<CaseNode> newCases = new ArrayList<>();
-        for (final CaseNode caseNode : switchNode.getCases()) {
-            final Node test = caseNode.getTest();
-
-            CaseNode newCaseNode = caseNode;
-            if (test != null) {
-                if (test instanceof LiteralNode) {
-                    //go down to integers if we can
-                    final LiteralNode<?> lit = (LiteralNode<?>)test;
-                    if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) {
-                        if (JSType.isRepresentableAsInt(lit.getNumber())) {
-                            newCaseNode = caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this));
-                        }
-                    }
-                } else {
-                    // the "all integer" case that CodeGenerator optimizes for currently assumes literals only
-                    type = Type.OBJECT;
-                }
-
-                final Type newCaseType = newCaseNode.getTest().getType();
-                if (newCaseType.isBoolean()) {
-                    type = Type.OBJECT; //booleans and integers aren't assignment compatible
-                } else {
-                    type = Type.widest(type, newCaseType);
-                }
-            }
-
-            newCases.add(newCaseNode);
-        }
-
-        //only optimize for all integers
-        if (!type.isInteger()) {
-            type = Type.OBJECT;
-        }
-
-        switchNode.setTag(newInternal(lc.getCurrentFunction().uniqueName(SWITCH_TAG_PREFIX.symbolName()), type));
-
-        end(switchNode);
-
-        return switchNode.setCases(lc, newCases);
-    }
-
-    @Override
-    public Node leaveTryNode(final TryNode tryNode) {
-        tryNode.setException(exceptionSymbol());
-
-        if (tryNode.getFinallyBody() != null) {
-            tryNode.setFinallyCatchAll(exceptionSymbol());
-        }
-
-        end(tryNode);
-
-        return tryNode;
-    }
-
-    @Override
-    public boolean enterVarNode(final VarNode varNode) {
-        start(varNode);
-
-        final IdentNode ident = varNode.getName();
-        final String    name  = ident.getName();
-
-        final Symbol symbol = defineSymbol(lc.getCurrentBlock(), name, IS_VAR);
-        assert symbol != null;
-
-        // NASHORN-467 - use before definition of vars - conservative
-        if (isLocalUse(ident.getName())) {
-            newType(symbol, Type.OBJECT);
-            symbol.setCanBeUndefined();
-        }
-
-        return true;
-    }
-
-    @Override
-    public Node leaveVarNode(final VarNode varNode) {
-        final Expression init  = varNode.getInit();
-        final IdentNode  ident = varNode.getName();
-        final String     name  = ident.getName();
-
-        final Symbol  symbol = findSymbol(lc.getCurrentBlock(), name);
-        assert ident.getSymbol() == symbol;
-
-        if (init == null) {
-            // var x; with no init will be treated like a use of x by
-            // leaveIdentNode unless we remove the name from the localdef list.
-            removeLocalDef(name);
-            return end(varNode);
-        }
-
-        addLocalDef(name);
-
-        assert symbol != null;
-
-        final IdentNode newIdent = (IdentNode)ident.setSymbol(lc, symbol);
-
-        final VarNode newVarNode = varNode.setName(newIdent);
-
-        final boolean isScript = lc.getDefiningFunction(symbol).isProgram(); //see NASHORN-56
-        if ((init.getType().isNumeric() || init.getType().isBoolean()) && !isScript) {
-            // Forbid integers as local vars for now as we have no way to treat them as undefined
-            newType(symbol, init.getType());
-        } else {
-            newType(symbol, Type.OBJECT);
-        }
-
-        assert newVarNode.getName().hasType() : newVarNode + " has no type";
-
-        return end(newVarNode);
-    }
-
-    @Override
-    public Node leaveADD(final UnaryNode unaryNode) {
-        return end(ensureSymbol(arithType(), unaryNode));
-    }
-
-    @Override
-    public Node leaveBIT_NOT(final UnaryNode unaryNode) {
-        return end(ensureSymbol(Type.INT, unaryNode));
-    }
-
-    @Override
-    public Node leaveDECINC(final UnaryNode unaryNode) {
-        // @see assignOffset
-        final Type type = arithType();
-        newType(unaryNode.rhs().getSymbol(), type);
-        return end(ensureSymbol(type, unaryNode));
-    }
-
-    @Override
-    public Node leaveDELETE(final UnaryNode unaryNode) {
-        final FunctionNode   currentFunctionNode = lc.getCurrentFunction();
-        final boolean        strictMode          = currentFunctionNode.isStrict();
-        final Expression     rhs                 = unaryNode.rhs();
-        final Expression     strictFlagNode      = (Expression)LiteralNode.newInstance(unaryNode, strictMode).accept(this);
-
-        Request request = Request.DELETE;
-        final List<Expression> args = new ArrayList<>();
-
-        if (rhs instanceof IdentNode) {
-            // If this is a declared variable or a function parameter, delete always fails (except for globals).
-            final String name = ((IdentNode)rhs).getName();
-
-            final boolean failDelete = strictMode || rhs.getSymbol().isParam() || (rhs.getSymbol().isVar() && !isProgramLevelSymbol(name));
-
-            if (failDelete && rhs.getSymbol().isThis()) {
-                return LiteralNode.newInstance(unaryNode, true).accept(this);
-            }
-            final Expression literalNode = (Expression)LiteralNode.newInstance(unaryNode, name).accept(this);
-
-            if (!failDelete) {
-                args.add(compilerConstant(SCOPE));
-            }
-            args.add(literalNode);
-            args.add(strictFlagNode);
-
-            if (failDelete) {
-                request = Request.FAIL_DELETE;
-            }
-        } else if (rhs instanceof AccessNode) {
-            final Expression base     = ((AccessNode)rhs).getBase();
-            final IdentNode  property = ((AccessNode)rhs).getProperty();
-
-            args.add(base);
-            args.add((Expression)LiteralNode.newInstance(unaryNode, property.getName()).accept(this));
-            args.add(strictFlagNode);
-
-        } else if (rhs instanceof IndexNode) {
-            final IndexNode indexNode = (IndexNode)rhs;
-            final Expression base  = indexNode.getBase();
-            final Expression index = indexNode.getIndex();
-
-            args.add(base);
-            args.add(index);
-            args.add(strictFlagNode);
-
-        } else {
-            return LiteralNode.newInstance(unaryNode, true).accept(this);
-        }
-
-        final RuntimeNode runtimeNode = new RuntimeNode(unaryNode, request, args);
-        assert runtimeNode.getSymbol() == unaryNode.getSymbol(); //unary parent constructor should do this
-
-        return leaveRuntimeNode(runtimeNode);
-    }
-
-    /**
-     * Is the symbol denoted by the specified name in the current lexical context defined in the program level
-     * @param name the name of the symbol
-     * @return true if the symbol denoted by the specified name in the current lexical context defined in the program level.
-     */
-    private boolean isProgramLevelSymbol(final String name) {
-        for(final Iterator<Block> it = lc.getBlocks(); it.hasNext();) {
-            final Block next = it.next();
-            if(next.getExistingSymbol(name) != null) {
-                return next == lc.getFunctionBody(lc.getOutermostFunction());
-            }
-        }
-        throw new AssertionError("Couldn't find symbol " + name + " in the context");
-    }
-
-    @Override
-    public Node leaveNEW(final UnaryNode unaryNode) {
-        return end(ensureSymbol(Type.OBJECT, unaryNode.setRHS(((CallNode)unaryNode.rhs()).setIsNew())));
-    }
-
-    @Override
-    public Node leaveNOT(final UnaryNode unaryNode) {
-        return end(ensureSymbol(Type.BOOLEAN, unaryNode));
-    }
-
-    private IdentNode compilerConstant(CompilerConstants cc) {
-        return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc, lc.getCurrentFunction().compilerConstant(cc));
-    }
-
-    /**
-     * Creates an ident node for an implicit identifier within the function (one not declared in the script source
-     * code). These identifiers are defined with function's token and finish.
-     * @param name the name of the identifier
-     * @return an ident node representing the implicit identifier.
-     */
-    private IdentNode createImplicitIdentifier(final String name) {
-        final FunctionNode fn = lc.getCurrentFunction();
-        return new IdentNode(fn.getToken(), fn.getFinish(), name);
-    }
-
-    @Override
-    public Node leaveTYPEOF(final UnaryNode unaryNode) {
-        final Expression rhs = unaryNode.rhs();
-
-        List<Expression> args = new ArrayList<>();
-        if (rhs instanceof IdentNode && !rhs.getSymbol().isParam() && !rhs.getSymbol().isVar()) {
-            args.add(compilerConstant(SCOPE));
-            args.add((Expression)LiteralNode.newInstance(rhs, ((IdentNode)rhs).getName()).accept(this)); //null
-        } else {
-            args.add(rhs);
-            args.add((Expression)LiteralNode.newInstance(unaryNode).accept(this)); //null, do not reuse token of identifier rhs, it can be e.g. 'this'
-        }
-
-        RuntimeNode runtimeNode = new RuntimeNode(unaryNode, Request.TYPEOF, args);
-        assert runtimeNode.getSymbol() == unaryNode.getSymbol();
-
-        runtimeNode = (RuntimeNode)leaveRuntimeNode(runtimeNode);
-
-        end(unaryNode);
-
-        return runtimeNode;
-    }
-
-    @Override
-    public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
-        return end(ensureSymbol(runtimeNode.getRequest().getReturnType(), runtimeNode));
-    }
-
-    @Override
-    public Node leaveSUB(final UnaryNode unaryNode) {
-        return end(ensureSymbol(arithType(), unaryNode));
-    }
-
-    @Override
-    public Node leaveVOID(final UnaryNode unaryNode) {
-        return end(ensureSymbol(Type.OBJECT, unaryNode));
-    }
-
-    /**
-     * Add is a special binary, as it works not only on arithmetic, but for
-     * strings etc as well.
-     */
-    @Override
-    public Node leaveADD(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
-
-        ensureTypeNotUnknown(lhs);
-        ensureTypeNotUnknown(rhs);
-        //even if we are adding two known types, this can overflow. i.e.
-        //int and number -> number.
-        //int and int are also number though.
-        //something and object is object
-        return end(ensureSymbol(Type.widest(arithType(), Type.widest(lhs.getType(), rhs.getType())), binaryNode));
-    }
-
-    @Override
-    public Node leaveAND(final BinaryNode binaryNode) {
-        return end(ensureSymbol(Type.OBJECT, binaryNode));
-    }
-
-    /**
-     * This is a helper called before an assignment.
-     * @param binaryNode assignment node
-     */
-    private boolean enterAssignmentNode(final BinaryNode binaryNode) {
-        start(binaryNode);
-
-        return true;
-    }
-
-
-    /**
-     * This assign helper is called after an assignment, when all children of
-     * the assign has been processed. It fixes the types and recursively makes
-     * sure that everyhing has slots that should have them in the chain.
-     *
-     * @param binaryNode assignment node
-     */
-    private Node leaveAssignmentNode(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
-        final Type type;
-
-        if (lhs instanceof IdentNode) {
-            final Block     block = lc.getCurrentBlock();
-            final IdentNode ident = (IdentNode)lhs;
-            final String    name  = ident.getName();
-            final Symbol symbol = findSymbol(block, name);
-
-            if (symbol == null) {
-                defineSymbol(block, name, IS_GLOBAL);
-            } else {
-                maybeForceScope(symbol);
-            }
-
-            addLocalDef(name);
-        }
-
-        if (rhs.getType().isNumeric()) {
-            type = Type.widest(lhs.getType(), rhs.getType());
-        } else {
-            type = Type.OBJECT; //force lhs to be an object if not numeric assignment, e.g. strings too.
-        }
-
-        newType(lhs.getSymbol(), type);
-        return end(ensureSymbol(type, binaryNode));
-    }
-
-    private boolean isLocal(FunctionNode function, Symbol symbol) {
-        final FunctionNode definingFn = lc.getDefiningFunction(symbol);
-        // Temp symbols are not assigned to a block, so their defining fn is null; those can be assumed local
-        return definingFn == null || definingFn == function;
-    }
-
-    @Override
-    public boolean enterASSIGN(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN(final BinaryNode binaryNode) {
-        return leaveAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_ADD(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
-
-        final Type widest = Type.widest(lhs.getType(), rhs.getType());
-        //Type.NUMBER if we can't prove that the add doesn't overflow. todo
-        return leaveSelfModifyingAssignmentNode(binaryNode, widest.isNumeric() ? Type.NUMBER : Type.OBJECT);
-    }
-
-    @Override
-    public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_AND(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_OR(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_XOR(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_DIV(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_MOD(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_MUL(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SAR(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SHL(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SHR(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
-        return enterAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveASSIGN_SUB(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode);
-    }
-
-    @Override
-    public Node leaveBIT_AND(final BinaryNode binaryNode) {
-        return end(coerce(binaryNode, Type.INT));
-    }
-
-    @Override
-    public Node leaveBIT_OR(final BinaryNode binaryNode) {
-        return end(coerce(binaryNode, Type.INT));
-    }
-
-    @Override
-    public Node leaveBIT_XOR(final BinaryNode binaryNode) {
-        return end(coerce(binaryNode, Type.INT));
-    }
-
-    @Override
-    public Node leaveCOMMARIGHT(final BinaryNode binaryNode) {
-        return leaveComma(binaryNode, binaryNode.rhs());
-    }
-
-    @Override
-    public Node leaveCOMMALEFT(final BinaryNode binaryNode) {
-        return leaveComma(binaryNode, binaryNode.lhs());
-    }
-
-    private Node leaveComma(final BinaryNode commaNode, final Expression effectiveExpr) {
-        ensureTypeNotUnknown(effectiveExpr);
-        return end(ensureSymbol(effectiveExpr.getType(), commaNode));
-    }
-
-    @Override
-    public Node leaveDIV(final BinaryNode binaryNode) {
-        return leaveBinaryArithmetic(binaryNode);
-    }
-
-    private Node leaveCmp(final BinaryNode binaryNode) {
-        ensureTypeNotUnknown(binaryNode.lhs());
-        ensureTypeNotUnknown(binaryNode.rhs());
-        Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
-        ensureSymbol(widest, binaryNode.lhs());
-        ensureSymbol(widest, binaryNode.rhs());
-        return end(ensureSymbol(Type.BOOLEAN, binaryNode));
-    }
-
-    private Node coerce(final BinaryNode binaryNode, final Type operandType, final Type destType) {
-        // TODO we currently don't support changing inferred type based on uses, only on
-        // definitions. we would need some additional logic. We probably want to do that
-        // in the future, if e.g. a specialized method gets parameter that is only used
-        // as, say, an int : function(x) { return x & 4711 }, and x is not defined in
-        // the function. to make this work, uncomment the following two type inferences
-        // and debug.
-        //newType(binaryNode.lhs().getSymbol(), operandType);
-        //newType(binaryNode.rhs().getSymbol(), operandType);
-        return ensureSymbol(destType, binaryNode);
-    }
-
-    private Node coerce(final BinaryNode binaryNode, final Type type) {
-        return coerce(binaryNode, type, type);
-    }
-
-    //leave a binary node and inherit the widest type of lhs , rhs
-    private Node leaveBinaryArithmetic(final BinaryNode binaryNode) {
-        assert !Compiler.shouldUseIntegerArithmetic();
-        return end(coerce(binaryNode, Type.NUMBER));
-    }
-
-    @Override
-    public Node leaveEQ(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveEQ_STRICT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveGE(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveGT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveIN(final BinaryNode binaryNode) {
-        return leaveBinaryRuntimeOperator(binaryNode, Request.IN);
-    }
-
-    @Override
-    public Node leaveINSTANCEOF(final BinaryNode binaryNode) {
-        return leaveBinaryRuntimeOperator(binaryNode, Request.INSTANCEOF);
-    }
-
-    private Node leaveBinaryRuntimeOperator(final BinaryNode binaryNode, final Request request) {
-        try {
-            // Don't do a full RuntimeNode.accept, as we don't want to double-visit the binary node operands
-            return leaveRuntimeNode(new RuntimeNode(binaryNode, request));
-        } finally {
-            end(binaryNode);
-        }
-    }
-
-    @Override
-    public Node leaveLE(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveLT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveMOD(final BinaryNode binaryNode) {
-        return leaveBinaryArithmetic(binaryNode);
-    }
-
-    @Override
-    public Node leaveMUL(final BinaryNode binaryNode) {
-        return leaveBinaryArithmetic(binaryNode);
-    }
-
-    @Override
-    public Node leaveNE(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveNE_STRICT(final BinaryNode binaryNode) {
-        return leaveCmp(binaryNode);
-    }
-
-    @Override
-    public Node leaveOR(final BinaryNode binaryNode) {
-        return end(ensureSymbol(Type.OBJECT, binaryNode));
-    }
-
-    @Override
-    public Node leaveSAR(final BinaryNode binaryNode) {
-        return end(coerce(binaryNode, Type.INT));
-    }
-
-    @Override
-    public Node leaveSHL(final BinaryNode binaryNode) {
-        return end(coerce(binaryNode, Type.INT));
-    }
-
-    @Override
-    public Node leaveSHR(final BinaryNode binaryNode) {
-        return end(coerce(binaryNode, Type.LONG));
-    }
-
-    @Override
-    public Node leaveSUB(final BinaryNode binaryNode) {
-        return leaveBinaryArithmetic(binaryNode);
-    }
-
-    @Override
-    public Node leaveForNode(final ForNode forNode) {
-        if (forNode.isForIn()) {
-            forNode.setIterator(newInternal(lc.getCurrentFunction().uniqueName(ITERATOR_PREFIX.symbolName()), Type.typeFor(ITERATOR_PREFIX.type()))); //NASHORN-73
-            /*
-             * Iterators return objects, so we need to widen the scope of the
-             * init variable if it, for example, has been assigned double type
-             * see NASHORN-50
-             */
-            newType(forNode.getInit().getSymbol(), Type.OBJECT);
-        }
-
-        end(forNode);
-
-        return forNode;
-    }
-
-    @Override
-    public Node leaveTernaryNode(final TernaryNode ternaryNode) {
-        final Expression trueExpr  = ternaryNode.getTrueExpression();
-        final Expression falseExpr = ternaryNode.getFalseExpression();
-
-        ensureTypeNotUnknown(trueExpr);
-        ensureTypeNotUnknown(falseExpr);
-
-        final Type type = widestReturnType(trueExpr.getType(), falseExpr.getType());
-        return end(ensureSymbol(type, ternaryNode));
-    }
-
-    /**
-     * When doing widening for return types of a function or a ternary operator, it is not valid to widen a boolean to
-     * anything other than Object. Also, widening a numeric type to an object type must widen to Object proper and not
-     * any more specific subclass (e.g. widest of int/long/double and String is Object).
-     * @param t1 type 1
-     * @param t2 type 2
-     * @return wider of t1 and t2, except if one is boolean and the other is neither boolean nor unknown, or if one is
-     * numeric and the other is neither numeric nor unknown in which case {@code Type.OBJECT} is returned.
-     */
-    private static Type widestReturnType(final Type t1, final Type t2) {
-        if (t1.isUnknown()) {
-            return t2;
-        } else if (t2.isUnknown()) {
-            return t1;
-        } else if (t1.isBoolean() != t2.isBoolean() || t1.isNumeric() != t2.isNumeric()) {
-            return Type.OBJECT;
-        }
-        return Type.widest(t1, t2);
-    }
-
-    private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags) {
-        final Class<?> type = cc.type();
-        // Must not call this method for constants with no explicit types; use the one with (..., Type) signature instead.
-        assert type != null;
-        initCompileConstant(cc, block, flags, Type.typeFor(type));
-    }
-
-    private void initCompileConstant(final CompilerConstants cc, final Block block, final int flags, final Type type) {
-        final Symbol symbol = defineSymbol(block, cc.symbolName(), flags);
-        symbol.setTypeOverride(type);
-        symbol.setNeedsSlot(true);
-    }
-
-    /**
-     * Initialize parameters for function node. This may require specializing
-     * types if a specialization profile is known
-     *
-     * @param functionNode the function node
-     */
-    private void initParameters(final FunctionNode functionNode, final Block body) {
-        int pos = 0;
-        for (final IdentNode param : functionNode.getParameters()) {
-            addLocalDef(param.getName());
-
-            final Type callSiteParamType = functionNode.getHints().getParameterType(pos);
-            int flags = IS_PARAM;
-            if (callSiteParamType != null) {
-                LOG.info("Param ", param, " has a callsite type ", callSiteParamType, ". Using that.");
-                flags |= Symbol.IS_SPECIALIZED_PARAM;
-            }
-
-            final Symbol paramSymbol = defineSymbol(body, param.getName(), flags);
-            assert paramSymbol != null;
-
-            newType(paramSymbol, callSiteParamType == null ? Type.UNKNOWN : callSiteParamType);
-
-            LOG.info("Initialized param ", pos, "=", paramSymbol);
-            pos++;
-        }
-
-    }
-
-    /**
-     * This has to run before fix assignment types, store any type specializations for
-     * paramters, then turn then to objects for the generic version of this method
-     *
-     * @param functionNode functionNode
-     */
-    private FunctionNode finalizeParameters(final FunctionNode functionNode) {
-        final List<IdentNode> newParams = new ArrayList<>();
-        final boolean isVarArg = functionNode.isVarArg();
-        final int nparams = functionNode.getParameters().size();
-
-        int specialize = 0;
-        int pos = 0;
-        for (final IdentNode param : functionNode.getParameters()) {
-            final Symbol paramSymbol = functionNode.getBody().getExistingSymbol(param.getName());
-            assert paramSymbol != null;
-            assert paramSymbol.isParam();
-            newParams.add((IdentNode)param.setSymbol(lc, paramSymbol));
-
-            assert paramSymbol != null;
-            Type type = functionNode.getHints().getParameterType(pos);
-            if (type == null) {
-                type = Type.OBJECT;
-            }
-
-            // if we know that a parameter is only used as a certain type throughout
-            // this function, we can tell the runtime system that no matter what the
-            // call site is, use this information:
-            // we also need more than half of the parameters to be specializable
-            // for the heuristic to be worth it, and we need more than one use of
-            // the parameter to consider it, i.e. function(x) { call(x); } doens't count
-            if (paramSymbol.getUseCount() > 1 && !paramSymbol.getSymbolType().isObject()) {
-                LOG.finest("Parameter ", param, " could profit from specialization to ", paramSymbol.getSymbolType());
-                specialize++;
-            }
-
-            newType(paramSymbol, Type.widest(type, paramSymbol.getSymbolType()));
-
-            // parameters should not be slots for a function that uses variable arity signature
-            if (isVarArg) {
-                paramSymbol.setNeedsSlot(false);
-            }
-
-            pos++;
-        }
-
-        FunctionNode newFunctionNode = functionNode;
-
-        if (nparams == 0 || (specialize * 2) < nparams) {
-            newFunctionNode = newFunctionNode.clearSnapshot(lc);
-        }
-
-        return newFunctionNode.setParameters(lc, newParams);
-    }
-
-    /**
-     * Move any properties from a global map into the scope of this method
-     * @param block the function node body for which to init scope vars
-     */
-    private void initFromPropertyMap(final Block block) {
-        // For a script, add scope symbols as defined in the property map
-
-        final PropertyMap map = Context.getGlobalMap();
-
-        for (final Property property : map.getProperties()) {
-            final String key    = property.getKey();
-            final Symbol symbol = defineSymbol(block, key, IS_GLOBAL);
-            newType(symbol, Type.OBJECT);
-            LOG.info("Added global symbol from property map ", symbol);
-        }
-    }
-
-    private static void ensureTypeNotUnknown(final Expression node) {
-
-        final Symbol symbol = node.getSymbol();
-
-        LOG.info("Ensure type not unknown for: ", symbol);
-
-        /*
-         * Note that not just unknowns, but params need to be blown
-         * up to objects, because we can have something like
-         *
-         * function f(a) {
-         *    var b = ~a; //b and a are inferred to be int
-         *    return b;
-         * }
-         *
-         * In this case, it would be correct to say that "if you have
-         * an int at the callsite, just pass it".
-         *
-         * However
-         *
-         * function f(a) {
-         *    var b = ~a;      //b and a are inferred to be int
-         *    return b == 17;  //b is still inferred to be int.
-         * }
-         *
-         * can be called with f("17") and if we assume that b is an
-         * int and don't blow it up to an object in the comparison, we
-         * are screwed. I hate JavaScript.
-         *
-         * This check has to be done for any operation that might take
-         * objects as parameters, for example +, but not *, which is known
-         * to coerce types into doubles
-         */
-        if (node.getType().isUnknown() || (symbol.isParam() && !symbol.isSpecializedParam())) {
-            newType(symbol, Type.OBJECT);
-            symbol.setCanBeUndefined();
-         }
-    }
-
-    private static Symbol pseudoSymbol(final String name) {
-        return new Symbol(name, 0, Type.OBJECT);
-    }
-
-    private Symbol exceptionSymbol() {
-        return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(EXCEPTION_PREFIX.type()));
-    }
-
-    /**
-     * Return the type that arithmetic ops should use. Until we have implemented better type
-     * analysis (range based) or overflow checks that are fast enough for int arithmetic,
-     * this is the number type
-     * @return the arithetic type
-     */
-    private static Type arithType() {
-        return Compiler.shouldUseIntegerArithmetic() ? Type.INT : Type.NUMBER;
-    }
-
-    /**
-     * If types have changed, we can have failed to update vars. For example
-     *
-     * var x = 17; //x is int
-     * x = "apa";  //x is object. This will be converted fine
-     *
-     * @param functionNode
-     */
-    private FunctionNode finalizeTypes(final FunctionNode functionNode) {
-        final Set<Node> changed = new HashSet<>();
-        FunctionNode currentFunctionNode = functionNode;
-        do {
-            changed.clear();
-            final FunctionNode newFunctionNode = (FunctionNode)currentFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-
-                private Expression widen(final Expression node, final Type to) {
-                    if (node instanceof LiteralNode) {
-                        return node;
-                    }
-                    Type from = node.getType();
-                    if (!Type.areEquivalent(from, to) && Type.widest(from, to) == to) {
-                        LOG.fine("Had to post pass widen '", node, "' ", Debug.id(node), " from ", node.getType(), " to ", to);
-                        Symbol symbol = node.getSymbol();
-                        if (symbol.isShared() && symbol.wouldChangeType(to)) {
-                            symbol = temporarySymbols.getTypedTemporarySymbol(to);
-                        }
-                        newType(symbol, to);
-                        final Expression newNode = node.setSymbol(lc, symbol);
-                        changed.add(newNode);
-                        return newNode;
-                    }
-                    return node;
-                }
-
-                @Override
-                public boolean enterFunctionNode(final FunctionNode node) {
-                    return !node.isLazy();
-                }
-
-                //
-                // Eg.
-                //
-                // var d = 17;
-                // var e;
-                // e = d; //initially typed as int for node type, should retype as double
-                // e = object;
-                //
-                // var d = 17;
-                // var e;
-                // e -= d; //initially type number, should number remain with a final conversion supplied by Store. ugly, but the computation result of the sub is numeric
-                // e = object;
-                //
-                @SuppressWarnings("fallthrough")
-                @Override
-                public Node leaveBinaryNode(final BinaryNode binaryNode) {
-                    final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
-                    BinaryNode newBinaryNode = binaryNode;
-
-                    if (isAdd(binaryNode)) {
-                        newBinaryNode = (BinaryNode)widen(newBinaryNode, widest);
-                        if (newBinaryNode.getType().isObject() && !isAddString(newBinaryNode)) {
-                            return new RuntimeNode(newBinaryNode, Request.ADD);
-                        }
-                    } else if (binaryNode.isComparison()) {
-                        final Expression lhs = newBinaryNode.lhs();
-                        final Expression rhs = newBinaryNode.rhs();
-
-                        Type cmpWidest = Type.widest(lhs.getType(), rhs.getType());
-
-                        boolean newRuntimeNode = false, finalized = false;
-                        switch (newBinaryNode.tokenType()) {
-                        case EQ_STRICT:
-                        case NE_STRICT:
-                            if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
-                                newRuntimeNode = true;
-                                cmpWidest = Type.OBJECT;
-                                finalized = true;
-                            }
-                            //fallthru
-                        default:
-                            if (newRuntimeNode || cmpWidest.isObject()) {
-                                return new RuntimeNode(newBinaryNode, Request.requestFor(binaryNode)).setIsFinal(finalized);
-                            }
-                            break;
-                        }
-
-                        return newBinaryNode;
-                    } else {
-                        if (!binaryNode.isAssignment() || binaryNode.isSelfModifying()) {
-                            return newBinaryNode;
-                        }
-                        checkThisAssignment(binaryNode);
-                        newBinaryNode = newBinaryNode.setLHS(widen(newBinaryNode.lhs(), widest));
-                        newBinaryNode = (BinaryNode)widen(newBinaryNode, widest);
-                    }
-
-                    return newBinaryNode;
-
-                }
-
-                private boolean isAdd(final Node node) {
-                    return node.isTokenType(TokenType.ADD);
-                }
-
-                /**
-                 * Determine if the outcome of + operator is a string.
-                 *
-                 * @param node  Node to test.
-                 * @return true if a string result.
-                 */
-                private boolean isAddString(final Node node) {
-                    if (node instanceof BinaryNode && isAdd(node)) {
-                        final BinaryNode binaryNode = (BinaryNode)node;
-                        final Node lhs = binaryNode.lhs();
-                        final Node rhs = binaryNode.rhs();
-
-                        return isAddString(lhs) || isAddString(rhs);
-                    }
-
-                    return node instanceof LiteralNode<?> && ((LiteralNode<?>)node).isString();
-                }
-
-                private void checkThisAssignment(final BinaryNode binaryNode) {
-                    if (binaryNode.isAssignment()) {
-                        if (binaryNode.lhs() instanceof AccessNode) {
-                            final AccessNode accessNode = (AccessNode) binaryNode.lhs();
-
-                            if (accessNode.getBase().getSymbol().isThis()) {
-                                lc.getCurrentFunction().addThisProperty(accessNode.getProperty().getName());
-                            }
-                        }
-                    }
-                }
-            });
-            lc.replace(currentFunctionNode, newFunctionNode);
-            currentFunctionNode = newFunctionNode;
-        } while (!changed.isEmpty());
-
-        return currentFunctionNode;
-    }
-
-    private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode) {
-        return leaveSelfModifyingAssignmentNode(binaryNode, binaryNode.getWidestOperationType());
-    }
-
-    private Node leaveSelfModifyingAssignmentNode(final BinaryNode binaryNode, final Type destType) {
-        //e.g. for -=, Number, no wider, destType (binaryNode.getWidestOperationType())  is the coerce type
-        final Expression lhs = binaryNode.lhs();
-
-        newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType
-
-        return end(ensureSymbol(destType, binaryNode));
-    }
-
-    private Expression ensureSymbol(final Type type, final Expression expr) {
-        LOG.info("New TEMPORARY added to ", lc.getCurrentFunction().getName(), " type=", type);
-        return temporarySymbols.ensureSymbol(lc, type, expr);
-    }
-
-    private Symbol newInternal(final String name, final Type type) {
-        final Symbol iter = defineSymbol(lc.getCurrentBlock(), name, IS_VAR | IS_INTERNAL);
-        iter.setType(type); // NASHORN-73
-        return iter;
-    }
-
-    private static void newType(final Symbol symbol, final Type type) {
-        final Type oldType = symbol.getSymbolType();
-        symbol.setType(type);
-
-        if (symbol.getSymbolType() != oldType) {
-            LOG.info("New TYPE ", type, " for ", symbol," (was ", oldType, ")");
-        }
-
-        if (symbol.isParam()) {
-            symbol.setType(type);
-            LOG.info("Param type change ", symbol);
-        }
-    }
-
-    private void pushLocalsFunction() {
-        localDefs.push(new HashSet<String>());
-        localUses.push(new HashSet<String>());
-    }
-
-    private void pushLocalsBlock() {
-        localDefs.push(new HashSet<>(localDefs.peek()));
-        localUses.push(new HashSet<>(localUses.peek()));
-    }
-
-    private void popLocals() {
-        localDefs.pop();
-        localUses.pop();
-    }
-
-    private boolean isLocalDef(final String name) {
-        return localDefs.peek().contains(name);
-    }
-
-    private void addLocalDef(final String name) {
-        LOG.info("Adding local def of symbol: '", name, "'");
-        localDefs.peek().add(name);
-    }
-
-    private void removeLocalDef(final String name) {
-        LOG.info("Removing local def of symbol: '", name, "'");
-        localDefs.peek().remove(name);
-    }
-
-    private boolean isLocalUse(final String name) {
-        return localUses.peek().contains(name);
-    }
-
-    private void addLocalUse(final String name) {
-        LOG.info("Adding local use of symbol: '", name, "'");
-        localUses.peek().add(name);
-    }
-
-    /**
-     * Pessimistically promote all symbols in current function node to Object types
-     * This is done when the function contains unevaluated black boxes such as
-     * lazy sub-function nodes that have not been compiled.
-     *
-     * @param body body for the function node we are leaving
-     */
-    private static void objectifySymbols(final Block body) {
-        body.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            private void toObject(final Block block) {
-                for (final Symbol symbol : block.getSymbols()) {
-                    if (!symbol.isTemp()) {
-                        newType(symbol, Type.OBJECT);
-                    }
-                }
-            }
-
-            @Override
-            public boolean enterBlock(final Block block) {
-                toObject(block);
-                return true;
-            }
-
-            @Override
-            public boolean enterFunctionNode(final FunctionNode node) {
-                return false;
-            }
-        });
-    }
-
-    private static String name(final Node node) {
-        final String cn = node.getClass().getName();
-        int lastDot = cn.lastIndexOf('.');
-        if (lastDot == -1) {
-            return cn;
-        }
-        return cn.substring(lastDot + 1);
-    }
-
-    private boolean start(final Node node) {
-        return start(node, true);
-    }
-
-    private boolean start(final Node node, final boolean printNode) {
-        if (DEBUG) {
-            final StringBuilder sb = new StringBuilder();
-
-            sb.append("[ENTER ").
-                append(name(node)).
-                append("] ").
-                append(printNode ? node.toString() : "").
-                append(" in '").
-                append(lc.getCurrentFunction().getName()).
-                append("'");
-            LOG.info(sb);
-            LOG.indent();
-        }
-
-        return true;
-    }
-
-    private <T extends Node> T end(final T node) {
-        return end(node, true);
-    }
-
-    private <T extends Node> T end(final T node, final boolean printNode) {
-        if(node instanceof Statement) {
-            // If we're done with a statement, all temporaries can be reused.
-            temporarySymbols.reuse();
-        }
-        if (DEBUG) {
-            final StringBuilder sb = new StringBuilder();
-
-            sb.append("[LEAVE ").
-                append(name(node)).
-                append("] ").
-                append(printNode ? node.toString() : "").
-                append(" in '").
-                append(lc.getCurrentFunction().getName()).
-                append('\'');
-
-            if (node instanceof Expression) {
-                final Symbol symbol = ((Expression)node).getSymbol();
-                if (symbol == null) {
-                    sb.append(" <NO SYMBOL>");
-                } else {
-                    sb.append(" <symbol=").append(symbol).append('>');
-                }
-            }
-
-            LOG.unindent();
-            LOG.info(sb);
-        }
-
-        return node;
-    }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java b/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
index ad9bdb0..5c8f964 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/BranchOptimizer.java
@@ -32,10 +32,10 @@
 import static jdk.nashorn.internal.codegen.Condition.LT;
 import static jdk.nashorn.internal.codegen.Condition.NE;
 
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.TernaryNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
 import jdk.nashorn.internal.ir.UnaryNode;
 
 /**
@@ -57,7 +57,7 @@
     }
 
     private void branchOptimizer(final UnaryNode unaryNode, final Label label, final boolean state) {
-        final Expression rhs = unaryNode.rhs();
+        final Expression rhs = unaryNode.getExpression();
 
         switch (unaryNode.tokenType()) {
         case NOT:
@@ -71,13 +71,7 @@
             break;
         }
 
-        // convert to boolean
-        codegen.load(unaryNode, Type.BOOLEAN);
-        if (state) {
-            method.ifne(label);
-        } else {
-            method.ifeq(label);
-        }
+        loadTestAndJump(unaryNode, label, state);
     }
 
     private void branchOptimizer(final BinaryNode binaryNode, final Label label, final boolean state) {
@@ -88,86 +82,97 @@
         case AND:
             if (state) {
                 final Label skip = new Label("skip");
-                branchOptimizer(lhs, skip, false);
-                branchOptimizer(rhs, label, true);
+                optimizeLogicalOperand(lhs, skip,  false, false);
+                optimizeLogicalOperand(rhs, label, true,  true);
                 method.label(skip);
             } else {
-                branchOptimizer(lhs, label, false);
-                branchOptimizer(rhs, label, false);
+                optimizeLogicalOperand(lhs, label, false, false);
+                optimizeLogicalOperand(rhs, label, false, true);
             }
             return;
 
         case OR:
             if (state) {
-                branchOptimizer(lhs, label, true);
-                branchOptimizer(rhs, label, true);
+                optimizeLogicalOperand(lhs, label, true, false);
+                optimizeLogicalOperand(rhs, label, true, true);
             } else {
                 final Label skip = new Label("skip");
-                branchOptimizer(lhs, skip, true);
-                branchOptimizer(rhs, label, false);
+                optimizeLogicalOperand(lhs, skip,  true,  false);
+                optimizeLogicalOperand(rhs, label, false, true);
                 method.label(skip);
             }
             return;
 
         case EQ:
         case EQ_STRICT:
-            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
+            codegen.loadBinaryOperands(binaryNode);
             method.conditionalJump(state ? EQ : NE, true, label);
             return;
 
         case NE:
         case NE_STRICT:
-            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
+            codegen.loadBinaryOperands(binaryNode);
             method.conditionalJump(state ? NE : EQ, true, label);
             return;
 
         case GE:
-            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
-            method.conditionalJump(state ? GE : LT, !state, label);
+            codegen.loadBinaryOperands(binaryNode);
+            method.conditionalJump(state ? GE : LT, false, label);
             return;
 
         case GT:
-            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
-            method.conditionalJump(state ? GT : LE, !state, label);
+            codegen.loadBinaryOperands(binaryNode);
+            method.conditionalJump(state ? GT : LE, false, label);
             return;
 
         case LE:
-            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
-            method.conditionalJump(state ? LE : GT, state, label);
+            codegen.loadBinaryOperands(binaryNode);
+            method.conditionalJump(state ? LE : GT, true, label);
             return;
 
         case LT:
-            codegen.loadBinaryOperands(lhs, rhs, Type.widest(lhs.getType(), rhs.getType()));
-            method.conditionalJump(state ? LT : GE, state, label);
+            codegen.loadBinaryOperands(binaryNode);
+            method.conditionalJump(state ? LT : GE, true, label);
             return;
 
         default:
             break;
         }
 
-        codegen.load(binaryNode, Type.BOOLEAN);
-        if (state) {
-            method.ifne(label);
-        } else {
-            method.ifeq(label);
-        }
+        loadTestAndJump(binaryNode, label, state);
     }
 
+    private void optimizeLogicalOperand(final Expression expr, final Label label, final boolean state, final boolean isRhs) {
+        final JoinPredecessorExpression jpexpr = (JoinPredecessorExpression)expr;
+        if(LocalVariableConversion.hasLiveConversion(jpexpr)) {
+            final Label after = new Label("after");
+            branchOptimizer(jpexpr.getExpression(), after, !state);
+            method.beforeJoinPoint(jpexpr);
+            method._goto(label);
+            method.label(after);
+            if(isRhs) {
+                method.beforeJoinPoint(jpexpr);
+            }
+        } else {
+            branchOptimizer(jpexpr.getExpression(), label, state);
+        }
+    }
     private void branchOptimizer(final Expression node, final Label label, final boolean state) {
-        if (!(node instanceof TernaryNode)) {
-
-            if (node instanceof BinaryNode) {
-                branchOptimizer((BinaryNode)node, label, state);
-                return;
-            }
-
-            if (node instanceof UnaryNode) {
-                branchOptimizer((UnaryNode)node, label, state);
-                return;
-            }
+        if (node instanceof BinaryNode) {
+            branchOptimizer((BinaryNode)node, label, state);
+            return;
         }
 
-        codegen.load(node, Type.BOOLEAN);
+        if (node instanceof UnaryNode) {
+            branchOptimizer((UnaryNode)node, label, state);
+            return;
+        }
+
+        loadTestAndJump(node, label, state);
+    }
+
+    private void loadTestAndJump(final Expression node, final Label label, final boolean state) {
+        codegen.loadExpressionAsBoolean(node);
         if (state) {
             method.ifne(label);
         } else {
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java
index 09c6a06..386effd 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ClassEmitter.java
@@ -49,25 +49,27 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.className;
 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
 
 import java.io.ByteArrayOutputStream;
 import java.io.PrintWriter;
-import java.util.Arrays;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.EnumSet;
 import java.util.HashSet;
 import java.util.Set;
-
-import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.internal.org.objectweb.asm.util.TraceClassVisitor;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.debug.NashornClassReader;
+import jdk.nashorn.internal.ir.debug.NashornTextifier;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.RewriteException;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Source;
 
@@ -106,6 +108,8 @@
  * @see Compiler
  */
 public class ClassEmitter implements Emitter {
+    /** Default flags for class generation - public class */
+    private static final EnumSet<Flag> DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC);
 
     /** Sanity check flag - have we started on a class? */
     private boolean classStarted;
@@ -123,10 +127,7 @@
     protected final ClassWriter cw;
 
     /** The script environment */
-    protected final ScriptEnvironment env;
-
-    /** Default flags for class generation - oublic class */
-    private static final EnumSet<Flag> DEFAULT_METHOD_FLAGS = EnumSet.of(Flag.PUBLIC);
+    protected final Context context;
 
     /** Compile unit class name. */
     private String unitClassName;
@@ -141,10 +142,8 @@
      * @param env script environment
      * @param cw  ASM classwriter
      */
-    private ClassEmitter(final ScriptEnvironment env, final ClassWriter cw) {
-        assert env != null;
-
-        this.env            = env;
+    private ClassEmitter(final Context context, final ClassWriter cw) {
+        this.context        = context;
         this.cw             = cw;
         this.methodsStarted = new HashSet<>();
     }
@@ -157,8 +156,8 @@
      * @param superClassName  super class name for class
      * @param interfaceNames  names of interfaces implemented by this class, or null if none
      */
-    ClassEmitter(final ScriptEnvironment env, final String className, final String superClassName, final String... interfaceNames) {
-        this(env, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
+    ClassEmitter(final Context context, final String className, final String superClassName, final String... interfaceNames) {
+        this(context, new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS));
         cw.visit(V1_7, ACC_PUBLIC | ACC_SUPER, className, null, superClassName, interfaceNames);
     }
 
@@ -170,8 +169,8 @@
      * @param unitClassName Compile unit class name.
      * @param strictMode    Should we generate this method in strict mode
      */
-    ClassEmitter(final ScriptEnvironment env, final String sourceName, final String unitClassName, final boolean strictMode) {
-        this(env,
+    ClassEmitter(final Context context, final String sourceName, final String unitClassName, final boolean strictMode) {
+        this(context,
              new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS) {
                 private static final String OBJECT_CLASS  = "java/lang/Object";
 
@@ -197,6 +196,10 @@
         defineCommonStatics(strictMode);
     }
 
+    Context getContext() {
+        return context;
+    }
+
     /**
      * Returns the name of the compile unit class name.
      * @return the name of the compile unit class name.
@@ -274,51 +277,51 @@
         }
 
         // $getXXXX$array - get the ith entry from the constants table and cast to XXXX[].
-        for (final Class<?> cls : constantMethodNeeded) {
-            if (cls.isArray()) {
-                defineGetArrayMethod(cls);
+        for (final Class<?> clazz : constantMethodNeeded) {
+            if (clazz.isArray()) {
+                defineGetArrayMethod(clazz);
             }
         }
     }
 
     /**
-     * Constructs a primitive specific method for getting the ith entry from the constants table and cast.
-     * @param cls Array class.
+     * Constructs a primitive specific method for getting the ith entry from the constants table as an array.
+     * @param clazz Array class.
      */
-    private void defineGetArrayMethod(final Class<?> cls) {
+    private void defineGetArrayMethod(final Class<?> clazz) {
         assert unitClassName != null;
 
-        final String        methodName     = getArrayMethodName(cls);
-        final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, cls, int.class);
+        final String        methodName     = getArrayMethodName(clazz);
+        final MethodEmitter getArrayMethod = method(EnumSet.of(Flag.PRIVATE, Flag.STATIC), methodName, clazz, int.class);
 
         getArrayMethod.begin();
         getArrayMethod.getStatic(unitClassName, CONSTANTS.symbolName(), CONSTANTS.descriptor())
                       .load(Type.INT, 0)
                       .arrayload()
-                      .checkcast(cls)
-                      .dup()
-                      .arraylength()
-                      .invoke(staticCallNoLookup(Arrays.class, "copyOf", cls, cls, int.class))
+                      .checkcast(clazz)
+                      .invoke(virtualCallNoLookup(clazz, "clone", Object.class))
+                      .checkcast(clazz)
                       ._return();
         getArrayMethod.end();
     }
 
+
     /**
      * Generate the name of a get array from constant pool method.
-     * @param cls Name of array class.
+     * @param clazz Name of array class.
      * @return Method name.
      */
-    static String getArrayMethodName(final Class<?> cls) {
-        assert cls.isArray();
-        return GET_ARRAY_PREFIX.symbolName() + cls.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName();
+    static String getArrayMethodName(final Class<?> clazz) {
+        assert clazz.isArray();
+        return GET_ARRAY_PREFIX.symbolName() + clazz.getComponentType().getSimpleName() + GET_ARRAY_SUFFIX.symbolName();
     }
 
     /**
      * Ensure a get constant method is issued for the class.
-     * @param cls Class of constant.
+     * @param clazz Class of constant.
      */
-    void needGetConstantMethod(final Class<?> cls) {
-        constantMethodNeeded.add(cls);
+    void needGetConstantMethod(final Class<?> clazz) {
+        constantMethodNeeded.add(clazz);
     }
 
     /**
@@ -376,16 +379,19 @@
     static String disassemble(final byte[] bytecode) {
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
         try (final PrintWriter pw = new PrintWriter(baos)) {
-            new ClassReader(bytecode).accept(new TraceClassVisitor(pw), 0);
+            final NashornClassReader cr = new NashornClassReader(bytecode);
+            final Context ctx = AccessController.doPrivileged(new PrivilegedAction<Context>() {
+                @Override
+                public Context run() {
+                    return Context.getContext();
+                }
+            });
+            final TraceClassVisitor tcv = new TraceClassVisitor(null, new NashornTextifier(ctx.getEnv(), cr), pw);
+            cr.accept(tcv, 0);
         }
-        return new String(baos.toByteArray());
-    }
 
-    /**
-     * @return env used for class emission
-     */
-    ScriptEnvironment getEnv() {
-        return env;
+        final String str = new String(baos.toByteArray());
+        return str;
     }
 
     /**
@@ -475,10 +481,11 @@
      * @return method emitter to use for weaving this method
      */
     MethodEmitter method(final FunctionNode functionNode) {
+        final FunctionSignature signature = new FunctionSignature(functionNode);
         final MethodVisitor mv = cw.visitMethod(
             ACC_PUBLIC | ACC_STATIC | (functionNode.isVarArg() ? ACC_VARARGS : 0),
             functionNode.getName(),
-            new FunctionSignature(functionNode).toString(),
+            signature.toString(),
             null,
             null);
 
@@ -486,6 +493,24 @@
     }
 
     /**
+     * Add a new method to the class, representing a rest-of version of the function node
+     *
+     * @param functionNode the function node to generate a method for
+     * @return method emitter to use for weaving this method
+     */
+    MethodEmitter restOfMethod(final FunctionNode functionNode) {
+        final MethodVisitor mv = cw.visitMethod(
+            ACC_PUBLIC | ACC_STATIC,
+            functionNode.getName(),
+            Type.getMethodDescriptor(functionNode.getReturnType().getTypeClass(), RewriteException.class),
+            null,
+            null);
+
+        return new MethodEmitter(this, mv, functionNode);
+    }
+
+
+    /**
      * Start generating the <clinit> method in the class
      *
      * @return method emitter to use for weaving <clinit>
@@ -636,7 +661,7 @@
         }
     }
 
-    private MethodVisitor methodVisitor(EnumSet<Flag> flags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
+    private MethodVisitor methodVisitor(final EnumSet<Flag> flags, final String methodName, final Class<?> rtype, final Class<?>... ptypes) {
         return cw.visitMethod(Flag.getValue(flags), methodName, methodDescriptor(rtype, ptypes), null, null);
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
index 52bdc7c..a5eb57c 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java
@@ -29,6 +29,7 @@
 import static jdk.nashorn.internal.codegen.ClassEmitter.Flag.STATIC;
 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
 import static jdk.nashorn.internal.codegen.CompilerConstants.GET_MAP;
 import static jdk.nashorn.internal.codegen.CompilerConstants.GET_STRING;
 import static jdk.nashorn.internal.codegen.CompilerConstants.QUICK_PREFIX;
@@ -45,25 +46,39 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.ir.Symbol.HAS_SLOT;
 import static jdk.nashorn.internal.ir.Symbol.IS_INTERNAL;
-import static jdk.nashorn.internal.ir.Symbol.IS_TEMP;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_APPLY_TO_CALL;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_FAST_SCOPE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
 import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_SCOPE;
-import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
 
 import java.io.PrintWriter;
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Deque;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+import java.util.function.Supplier;
+import jdk.nashorn.internal.AssertsEnabled;
+import jdk.nashorn.internal.IntDeque;
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.codegen.RuntimeCallSite.SpecializedRuntimeNode;
 import jdk.nashorn.internal.codegen.types.ArrayType;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
@@ -86,14 +101,20 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessor;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LexicalContextNode;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
 import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
+import jdk.nashorn.internal.ir.LiteralNode.PrimitiveLiteralNode;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ObjectNode;
+import jdk.nashorn.internal.ir.Optimistic;
 import jdk.nashorn.internal.ir.PropertyNode;
 import jdk.nashorn.internal.ir.ReturnNode;
 import jdk.nashorn.internal.ir.RuntimeNode;
@@ -117,20 +138,26 @@
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
 import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.RewriteException;
 import jdk.nashorn.internal.runtime.Scope;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.Undefined;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.Options;
 
 /**
  * This is the lowest tier of the code generator. It takes lowered ASTs emitted
@@ -151,16 +178,42 @@
  * The CodeGenerator visits nodes only once, tags them as resolved and emits
  * bytecode for them.
  */
-final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> {
+@Logger(name="codegen")
+final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContext> implements Loggable {
+
+    private static final Type SCOPE_TYPE = Type.typeFor(ScriptObject.class);
 
     private static final String GLOBAL_OBJECT = Type.getInternalName(Global.class);
 
-    private static final String SCRIPTFUNCTION_IMPL_OBJECT = Type.getInternalName(ScriptFunctionImpl.class);
+    private static final String SCRIPTFUNCTION_IMPL_NAME = Type.getInternalName(ScriptFunctionImpl.class);
+    private static final Type   SCRIPTFUNCTION_IMPL_TYPE   = Type.typeFor(ScriptFunction.class);
+
+    private static final Call CREATE_REWRITE_EXCEPTION = CompilerConstants.staticCallNoLookup(RewriteException.class,
+            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class);
+    private static final Call CREATE_REWRITE_EXCEPTION_REST_OF = CompilerConstants.staticCallNoLookup(RewriteException.class,
+            "create", RewriteException.class, UnwarrantedOptimismException.class, Object[].class, String[].class, int[].class);
+
+    private static final Call ENSURE_INT = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
+            "ensureInt", int.class, Object.class, int.class);
+    private static final Call ENSURE_LONG = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
+            "ensureLong", long.class, Object.class, int.class);
+    private static final Call ENSURE_NUMBER = CompilerConstants.staticCallNoLookup(OptimisticReturnFilters.class,
+            "ensureNumber", double.class, Object.class, int.class);
+
+    private static final Class<?> ITERATOR_CLASS = Iterator.class;
+    static {
+        assert ITERATOR_CLASS == CompilerConstants.ITERATOR_PREFIX.type();
+    }
+    private static final Type ITERATOR_TYPE = Type.typeFor(ITERATOR_CLASS);
+    private static final Type EXCEPTION_TYPE = Type.typeFor(CompilerConstants.EXCEPTION_PREFIX.type());
 
     /** Constant data & installation. The only reason the compiler keeps this is because it is assigned
      *  by reflection in class installation */
     private final Compiler compiler;
 
+    /** Is the current code submitted by 'eval' call? */
+    private final boolean evalCode;
+
     /** Call site flags given to the code generator to be used for all generated call sites */
     private final int callSiteFlags;
 
@@ -180,22 +233,48 @@
     /** Current compile unit */
     private CompileUnit unit;
 
-    private static final DebugLogger LOG   = new DebugLogger("codegen", "nashorn.codegen.debug");
+    private final DebugLogger log;
 
     /** From what size should we use spill instead of fields for JavaScript objects? */
-    private static final int OBJECT_SPILL_THRESHOLD = 300;
+    private static final int OBJECT_SPILL_THRESHOLD = Options.getIntProperty("nashorn.spill.threshold", 256);
 
     private final Set<String> emittedMethods = new HashSet<>();
 
+    // Function Id -> ContinuationInfo. Used by compilation of rest-of function only.
+    private final Map<Integer, ContinuationInfo> fnIdToContinuationInfo = new HashMap<>();
+
+    private final Deque<Label> scopeEntryLabels = new ArrayDeque<>();
+
+    private static final Label METHOD_BOUNDARY = new Label("");
+    private final Deque<Label> catchLabels = new ArrayDeque<>();
+    // Number of live locals on entry to (and thus also break from) labeled blocks.
+    private final IntDeque labeledBlockBreakLiveLocals = new IntDeque();
+
+    //is this a rest of compilation
+    private final int[] continuationEntryPoints;
+
     /**
      * Constructor.
      *
      * @param compiler
      */
-    CodeGenerator(final Compiler compiler) {
+    CodeGenerator(final Compiler compiler, final int[] continuationEntryPoints) {
         super(new CodeGeneratorLexicalContext());
-        this.compiler      = compiler;
-        this.callSiteFlags = compiler.getEnv()._callsite_flags;
+        this.compiler                = compiler;
+        this.evalCode                = compiler.getSource().isEvalCode();
+        this.continuationEntryPoints = continuationEntryPoints;
+        this.callSiteFlags           = compiler.getScriptEnvironment()._callsite_flags;
+        this.log                     = initLogger(compiler.getContext());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     /**
@@ -205,7 +284,15 @@
      * @return the correct flags for a call site in the current function
      */
     int getCallSiteFlags() {
-        return lc.getCurrentFunction().isStrict() ? callSiteFlags | CALLSITE_STRICT : callSiteFlags;
+        return lc.getCurrentFunction().getCallSiteFlags() | callSiteFlags;
+    }
+
+    /**
+     * Are we generating code for 'eval' code?
+     * @return true if currently compiled code is 'eval' code.
+     */
+    boolean isEvalCode() {
+        return evalCode;
     }
 
     /**
@@ -214,38 +301,69 @@
      * @param identNode an identity node to load
      * @return the method generator used
      */
-    private MethodEmitter loadIdent(final IdentNode identNode, final Type type) {
+    private MethodEmitter loadIdent(final IdentNode identNode, final TypeBounds resultBounds) {
         final Symbol symbol = identNode.getSymbol();
 
         if (!symbol.isScope()) {
-            assert symbol.hasSlot() || symbol.isParam();
-            return method.load(symbol).convert(type);
-        }
-
-        final String name   = symbol.getName();
-        final Source source = lc.getCurrentFunction().getSource();
-
-        if (CompilerConstants.__FILE__.name().equals(name)) {
-            return method.load(source.getName());
-        } else if (CompilerConstants.__DIR__.name().equals(name)) {
-            return method.load(source.getBase());
-        } else if (CompilerConstants.__LINE__.name().equals(name)) {
-            return method.load(source.getLine(identNode.position())).convert(Type.OBJECT);
-        } else {
-            assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
-
-            final int flags = CALLSITE_SCOPE | getCallSiteFlags();
-            method.loadCompilerConstant(SCOPE);
-
-            if (isFastScope(symbol)) {
-                // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
-                if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD) {
-                    return loadSharedScopeVar(type, symbol, flags);
-                }
-                return loadFastScopeVar(type, symbol, flags, identNode.isFunction());
+            final Type type = identNode.getType();
+            if(type == Type.UNDEFINED) {
+                return method.loadUndefined(resultBounds.widest);
             }
-            return method.dynamicGet(type, identNode.getName(), flags, identNode.isFunction());
+
+            assert symbol.hasSlot() || symbol.isParam();
+            return method.load(identNode);
         }
+
+        assert identNode.getSymbol().isScope() : identNode + " is not in scope!";
+        final int flags = CALLSITE_SCOPE | getCallSiteFlags();
+        if (isFastScope(symbol)) {
+            // Only generate shared scope getter for fast-scope symbols so we know we can dial in correct scope.
+            if (symbol.getUseCount() > SharedScopeCall.FAST_SCOPE_GET_THRESHOLD && !isOptimisticOrRestOf()) {
+                method.loadCompilerConstant(SCOPE);
+                // As shared scope vars are only used in non-optimistic compilation, we switch from using TypeBounds to
+                // just a single definitive type, resultBounds.widest.
+                loadSharedScopeVar(resultBounds.widest, symbol, flags);
+            } else {
+                new LoadFastScopeVar(identNode, resultBounds, flags).emit();
+            }
+        } else {
+            //slow scope load, we have no proto depth
+            new LoadScopeVar(identNode, resultBounds, flags).emit();
+        }
+
+        return method;
+    }
+
+    private boolean isRestOf() {
+        return continuationEntryPoints != null;
+    }
+
+    private boolean isOptimisticOrRestOf() {
+        return useOptimisticTypes() || isRestOf();
+    }
+
+    private boolean isCurrentContinuationEntryPoint(final int programPoint) {
+        return isRestOf() && getCurrentContinuationEntryPoint() == programPoint;
+    }
+
+    private int[] getContinuationEntryPoints() {
+        return isRestOf() ? continuationEntryPoints : null;
+    }
+
+    private int getCurrentContinuationEntryPoint() {
+        return isRestOf() ? continuationEntryPoints[0] : INVALID_PROGRAM_POINT;
+    }
+
+    private boolean isContinuationEntryPoint(final int programPoint) {
+        if (isRestOf()) {
+            assert continuationEntryPoints != null;
+            for (final int cep : continuationEntryPoints) {
+                if (cep == programPoint) {
+                    return true;
+                }
+            }
+        }
+        return false;
     }
 
     /**
@@ -285,7 +403,7 @@
                 }
                 previousWasBlock = true;
             } else {
-                if ((node instanceof WithNode && previousWasBlock) || (node instanceof FunctionNode && CodeGeneratorLexicalContext.isFunctionDynamicScope((FunctionNode)node))) {
+                if (node instanceof WithNode && previousWasBlock || node instanceof FunctionNode && ((FunctionNode)node).needsDynamicScope()) {
                     // If we hit a scope that can have symbols introduced into it at run time before finding the defining
                     // block, the symbol can't be fast scoped. A WithNode only counts if we've immediately seen a block
                     // before - its block. Otherwise, we are currently processing the WithNode's expression, and that's
@@ -300,14 +418,57 @@
     }
 
     private MethodEmitter loadSharedScopeVar(final Type valueType, final Symbol symbol, final int flags) {
-        method.load(isFastScope(symbol) ? getScopeProtoDepth(lc.getCurrentBlock(), symbol) : -1);
-        final SharedScopeCall scopeCall = lc.getScopeGet(unit, valueType, symbol, flags | CALLSITE_FAST_SCOPE);
-        return scopeCall.generateInvoke(method);
+        assert !isOptimisticOrRestOf();
+        if (isFastScope(symbol)) {
+            method.load(getScopeProtoDepth(lc.getCurrentBlock(), symbol));
+        } else {
+            method.load(-1);
+        }
+        return lc.getScopeGet(unit, symbol, valueType, flags | CALLSITE_FAST_SCOPE).generateInvoke(method);
     }
 
-    private MethodEmitter loadFastScopeVar(final Type valueType, final Symbol symbol, final int flags, final boolean isMethod) {
-        loadFastScopeProto(symbol, false);
-        return method.dynamicGet(valueType, symbol.getName(), flags | CALLSITE_FAST_SCOPE, isMethod);
+    private class LoadScopeVar extends OptimisticOperation {
+        final IdentNode identNode;
+        private final int flags;
+
+        LoadScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
+            super(identNode, resultBounds);
+            this.identNode = identNode;
+            this.flags = flags;
+        }
+
+        @Override
+        void loadStack() {
+            method.loadCompilerConstant(SCOPE);
+            getProto();
+        }
+
+        void getProto() {
+            //empty
+        }
+
+        @Override
+        void consumeStack() {
+            // If this is either __FILE__, __DIR__, or __LINE__ then load the property initially as Object as we'd convert
+            // it anyway for replaceLocationPropertyPlaceholder.
+            if(identNode.isCompileTimePropertyName()) {
+                method.dynamicGet(Type.OBJECT, identNode.getSymbol().getName(), flags, identNode.isFunction());
+                replaceCompileTimeProperty();
+            } else {
+                dynamicGet(identNode.getSymbol().getName(), flags, identNode.isFunction());
+            }
+        }
+    }
+
+    private class LoadFastScopeVar extends LoadScopeVar {
+        LoadFastScopeVar(final IdentNode identNode, final TypeBounds resultBounds, final int flags) {
+            super(identNode, resultBounds, flags | CALLSITE_FAST_SCOPE);
+        }
+
+        @Override
+        void getProto() {
+            loadFastScopeProto(identNode.getSymbol(), false);
+        }
     }
 
     private MethodEmitter storeFastScopeVar(final Symbol symbol, final int flags) {
@@ -317,23 +478,30 @@
     }
 
     private int getScopeProtoDepth(final Block startingBlock, final Symbol symbol) {
+        //walk up the chain from starting block and when we bump into the current function boundary, add the external
+        //information.
+        final FunctionNode fn   = lc.getCurrentFunction();
+        final int          fnId = fn.getId();
+        final int externalDepth = compiler.getScriptFunctionData(fnId).getExternalSymbolDepth(symbol.getName());
+
+        //count the number of scopes from this place to the start of the function
+
+        final int internalDepth = FindScopeDepths.findInternalDepth(lc, fn, startingBlock, symbol);
+        final int scopesToStart = FindScopeDepths.findScopesToStart(lc, fn, startingBlock);
         int depth = 0;
-        final String name = symbol.getName();
-        for(final Iterator<Block> blocks = lc.getBlocks(startingBlock); blocks.hasNext();) {
-            final Block currentBlock = blocks.next();
-            if (currentBlock.getExistingSymbol(name) == symbol) {
-                return depth;
-            }
-            if (currentBlock.needsScope()) {
-                ++depth;
-            }
+        if (internalDepth == -1) {
+            depth = scopesToStart + externalDepth;
+        } else {
+            assert internalDepth <= scopesToStart;
+            depth = internalDepth;
         }
-        return -1;
+
+        return depth;
     }
 
     private void loadFastScopeProto(final Symbol symbol, final boolean swap) {
         final int depth = getScopeProtoDepth(lc.getCurrentBlock(), symbol);
-        assert depth != -1;
+        assert depth != -1 : "Couldn't find scope depth for symbol " + symbol.getName() + " in " + lc.getCurrentFunction();
         if (depth > 0) {
             if (swap) {
                 method.swap();
@@ -348,29 +516,36 @@
     }
 
     /**
-     * Generate code that loads this node to the stack. This method is only
-     * public to be accessible from the maps sub package. Do not call externally
+     * Generate code that loads this node to the stack, not constraining its type
      *
-     * @param node node to load
+     * @param expr node to load
      *
      * @return the method emitter used
      */
-    MethodEmitter load(final Expression node) {
-        return load(node, node.hasType() ? node.getType() : null, false);
+    private MethodEmitter loadExpressionUnbounded(final Expression expr) {
+        return loadExpression(expr, TypeBounds.UNBOUNDED);
+    }
+
+    private MethodEmitter loadExpressionAsObject(final Expression expr) {
+        return loadExpression(expr, TypeBounds.OBJECT);
+    }
+
+    MethodEmitter loadExpressionAsBoolean(final Expression expr) {
+        return loadExpression(expr, TypeBounds.BOOLEAN);
     }
 
     // Test whether conversion from source to target involves a call of ES 9.1 ToPrimitive
     // with possible side effects from calling an object's toString or valueOf methods.
-    private boolean noToPrimitiveConversion(final Type source, final Type target) {
+    private static boolean noToPrimitiveConversion(final Type source, final Type target) {
         // Object to boolean conversion does not cause ToPrimitive call
         return source.isJSPrimitive() || !target.isJSPrimitive() || target.isBoolean();
     }
 
-    MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type) {
-        return loadBinaryOperands(lhs, rhs, type, false);
+    MethodEmitter loadBinaryOperands(final BinaryNode binaryNode) {
+        return loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(binaryNode.getWidestOperandType()), false);
     }
 
-    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final Type type, final boolean baseAlreadyOnStack) {
+    private MethodEmitter loadBinaryOperands(final Expression lhs, final Expression rhs, final TypeBounds explicitOperandBounds, final boolean baseAlreadyOnStack) {
         // ECMAScript 5.1 specification (sections 11.5-11.11 and 11.13) prescribes that when evaluating a binary
         // expression "LEFT op RIGHT", the order of operations must be: LOAD LEFT, LOAD RIGHT, CONVERT LEFT, CONVERT
         // RIGHT, EXECUTE OP. Unfortunately, doing it in this order defeats potential optimizations that arise when we
@@ -381,38 +556,130 @@
         // a primitive value, or RIGHT is an expression that loads without side effects, then we can do the
         // reordering and collapse LOAD/CONVERT into a single operation; otherwise we need to do the more costly
         // separate operations to preserve specification semantics.
-        if (noToPrimitiveConversion(lhs.getType(), type) || rhs.isLocal()) {
+
+        // Operands' load type should not be narrower than the narrowest of the individual operand types, nor narrower
+        // than the lower explicit bound, but it should also not be wider than
+        final Type narrowestOperandType = Type.narrowest(Type.widest(lhs.getType(), rhs.getType()), explicitOperandBounds.widest);
+        final TypeBounds operandBounds = explicitOperandBounds.notNarrowerThan(narrowestOperandType);
+        if (noToPrimitiveConversion(lhs.getType(), explicitOperandBounds.widest) || rhs.isLocal()) {
             // Can reorder. Combine load and convert into single operations.
-            load(lhs, type, baseAlreadyOnStack);
-            load(rhs, type, false);
+            loadExpression(lhs, operandBounds, baseAlreadyOnStack);
+            loadExpression(rhs, operandBounds, false);
         } else {
             // Can't reorder. Load and convert separately.
-            load(lhs, lhs.getType(), baseAlreadyOnStack);
-            load(rhs, rhs.getType(), false);
-            method.swap().convert(type).swap().convert(type);
+            final TypeBounds safeConvertBounds = TypeBounds.UNBOUNDED.notNarrowerThan(narrowestOperandType);
+            loadExpression(lhs, safeConvertBounds, baseAlreadyOnStack);
+            loadExpression(rhs, safeConvertBounds, false);
+            method.swap().convert(operandBounds.within(method.peekType())).swap().convert(operandBounds.within(method.peekType()));
         }
+        assert Type.generic(method.peekType()) == operandBounds.narrowest;
+        assert Type.generic(method.peekType(1)) == operandBounds.narrowest;
 
         return method;
     }
 
-    MethodEmitter loadBinaryOperands(final BinaryNode node) {
-        return loadBinaryOperands(node.lhs(), node.rhs(), node.getType(), false);
-    }
+    private static final class TypeBounds {
+        final Type narrowest;
+        final Type widest;
 
-    MethodEmitter load(final Expression node, final Type type) {
-        return load(node, type, false);
-    }
+        static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
+        static final TypeBounds INT = exact(Type.INT);
+        static final TypeBounds NUMBER = exact(Type.NUMBER);
+        static final TypeBounds OBJECT = exact(Type.OBJECT);
+        static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
 
-    private MethodEmitter load(final Expression node, final Type type, final boolean baseAlreadyOnStack) {
-        final Symbol symbol = node.getSymbol();
-
-        // If we lack symbols, we just generate what we see.
-        if (symbol == null || type == null) {
-            node.accept(this);
-            return method;
+        static TypeBounds exact(final Type type) {
+            return new TypeBounds(type, type);
         }
 
-        assert !type.isUnknown();
+        TypeBounds(final Type narrowest, final Type widest) {
+            assert widest    != null && widest    != Type.UNDEFINED && widest != Type.UNKNOWN : widest;
+            assert narrowest != null && narrowest != Type.UNDEFINED : narrowest;
+            assert !narrowest.widerThan(widest) : narrowest + " wider than " + widest;
+            assert !widest.narrowerThan(narrowest);
+            this.narrowest = Type.generic(narrowest);
+            this.widest = Type.generic(widest);
+        }
+
+        TypeBounds notNarrowerThan(final Type type) {
+            return maybeNew(Type.narrowest(Type.widest(narrowest, type), widest), widest);
+        }
+
+        TypeBounds notWiderThan(final Type type) {
+            return maybeNew(Type.narrowest(narrowest, type), Type.narrowest(widest, type));
+        }
+
+        boolean canBeNarrowerThan(final Type type) {
+            return narrowest.narrowerThan(type);
+        }
+
+        TypeBounds maybeNew(final Type newNarrowest, final Type newWidest) {
+            if(newNarrowest == narrowest && newWidest == widest) {
+                return this;
+            }
+            return new TypeBounds(newNarrowest, newWidest);
+        }
+
+        TypeBounds booleanToInt() {
+            return maybeNew(booleanToInt(narrowest), booleanToInt(widest));
+        }
+
+        TypeBounds objectToNumber() {
+            return maybeNew(objectToNumber(narrowest), objectToNumber(widest));
+        }
+
+        private static Type booleanToInt(final Type t) {
+            return t == Type.BOOLEAN ? Type.INT : t;
+        }
+
+        private static Type objectToNumber(final Type t) {
+            return t.isObject() ? Type.NUMBER : t;
+        }
+
+        Type within(final Type type) {
+            if(type.narrowerThan(narrowest)) {
+                return narrowest;
+            }
+            if(type.widerThan(widest)) {
+                return widest;
+            }
+            return type;
+        }
+
+        @Override
+        public String toString() {
+            return "[" + narrowest + ", " + widest + "]";
+        }
+    }
+
+    MethodEmitter loadExpressionAsType(final Expression expr, final Type type) {
+        if(type == Type.BOOLEAN) {
+            return loadExpressionAsBoolean(expr);
+        } else if(type == Type.UNDEFINED) {
+            assert expr.getType() == Type.UNDEFINED;
+            return loadExpressionAsObject(expr);
+        }
+        // having no upper bound preserves semantics of optimistic operations in the expression (by not having them
+        // converted early) and then applies explicit conversion afterwards.
+        return loadExpression(expr, TypeBounds.UNBOUNDED.notNarrowerThan(type)).convert(type);
+    }
+
+    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds) {
+        return loadExpression(expr, resultBounds, false);
+    }
+
+    /**
+     * Emits code for evaluating an expression and leaving its value on top of the stack, narrowing or widening it if
+     * necessary.
+     * @param expr the expression to load
+     * @param resultBounds the incoming type bounds. The value on the top of the stack is guaranteed to not be of narrower
+     * type than the narrowest bound, or wider type than the widest bound after it is loaded.
+     * @param baseAlreadyOnStack true if the base of an access or index node is already on the stack. Used to avoid
+     * double evaluation of bases in self-assignment expressions to access and index nodes. {@code Type.OBJECT} is used
+     * to indicate the widest possible type.
+     * @return the method emitter
+     */
+    private MethodEmitter loadExpression(final Expression expr, final TypeBounds resultBounds, final boolean baseAlreadyOnStack) {
 
         /*
          * The load may be of type IdentNode, e.g. "x", AccessNode, e.g. "x.y"
@@ -421,35 +688,54 @@
          */
         final CodeGenerator codegen = this;
 
-        node.accept(new NodeVisitor<LexicalContext>(lc) {
+        final Node currentDiscard = codegen.lc.getCurrentDiscard();
+        expr.accept(new NodeOperatorVisitor<LexicalContext>(new LexicalContext()) {
             @Override
             public boolean enterIdentNode(final IdentNode identNode) {
-                loadIdent(identNode, type);
+                loadIdent(identNode, resultBounds);
                 return false;
             }
 
             @Override
             public boolean enterAccessNode(final AccessNode accessNode) {
-                if (!baseAlreadyOnStack) {
-                    load(accessNode.getBase(), Type.OBJECT);
-                }
-                assert method.peekType().isObject();
-                method.dynamicGet(type, accessNode.getProperty().getName(), getCallSiteFlags(), accessNode.isFunction());
+                new OptimisticOperation(accessNode, resultBounds) {
+                    @Override
+                    void loadStack() {
+                        if (!baseAlreadyOnStack) {
+                            loadExpressionAsObject(accessNode.getBase());
+                        }
+                        assert method.peekType().isObject();
+                    }
+                    @Override
+                    void consumeStack() {
+                        final int flags = getCallSiteFlags();
+                        dynamicGet(accessNode.getProperty(), flags, accessNode.isFunction());
+                    }
+                }.emit(baseAlreadyOnStack ? 1 : 0);
                 return false;
             }
 
             @Override
             public boolean enterIndexNode(final IndexNode indexNode) {
-                if (!baseAlreadyOnStack) {
-                    load(indexNode.getBase(), Type.OBJECT);
-                    load(indexNode.getIndex());
-                }
-                method.dynamicGetIndex(type, getCallSiteFlags(), indexNode.isFunction());
+                new OptimisticOperation(indexNode, resultBounds) {
+                    @Override
+                    void loadStack() {
+                        if (!baseAlreadyOnStack) {
+                            loadExpressionAsObject(indexNode.getBase());
+                            loadExpressionUnbounded(indexNode.getIndex());
+                        }
+                    }
+                    @Override
+                    void consumeStack() {
+                        final int flags = getCallSiteFlags();
+                        dynamicGetIndex(flags, indexNode.isFunction());
+                    }
+                }.emit(baseAlreadyOnStack ? 2 : 0);
                 return false;
             }
 
             @Override
-            public boolean enterFunctionNode(FunctionNode functionNode) {
+            public boolean enterFunctionNode(final FunctionNode functionNode) {
                 // function nodes will always leave a constructed function object on stack, no need to load the symbol
                 // separately as in enterDefault()
                 lc.pop(functionNode);
@@ -459,204 +745,485 @@
                 // is the last element in the compilation pipeline, the AST it produces is not used externally. So, we
                 // re-push the original functionNode.
                 lc.push(functionNode);
-                method.convert(type);
                 return false;
             }
 
             @Override
-            public boolean enterCallNode(CallNode callNode) {
-                return codegen.enterCallNode(callNode, type);
+            public boolean enterASSIGN(final BinaryNode binaryNode) {
+                loadASSIGN(binaryNode);
+                return false;
             }
 
             @Override
-            public boolean enterLiteralNode(LiteralNode<?> literalNode) {
-                return codegen.enterLiteralNode(literalNode, type);
+            public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
+                loadASSIGN_ADD(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
+                loadASSIGN_BIT_AND(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
+                loadASSIGN_BIT_OR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
+                loadASSIGN_BIT_XOR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
+                loadASSIGN_DIV(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
+                loadASSIGN_MOD(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
+                loadASSIGN_MUL(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
+                loadASSIGN_SAR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
+                loadASSIGN_SHL(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
+                loadASSIGN_SHR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
+                loadASSIGN_SUB(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterCallNode(final CallNode callNode) {
+                return loadCallNode(callNode, resultBounds);
+            }
+
+            @Override
+            public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
+                loadLiteral(literalNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterTernaryNode(final TernaryNode ternaryNode) {
+                loadTernaryNode(ternaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterADD(final BinaryNode binaryNode) {
+                loadADD(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterSUB(final UnaryNode unaryNode) {
+                loadSUB(unaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterSUB(final BinaryNode binaryNode) {
+                loadSUB(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterMUL(final BinaryNode binaryNode) {
+                loadMUL(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterDIV(final BinaryNode binaryNode) {
+                loadDIV(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterMOD(final BinaryNode binaryNode) {
+                loadMOD(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterSAR(final BinaryNode binaryNode) {
+                loadSAR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterSHL(final BinaryNode binaryNode) {
+                loadSHL(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterSHR(final BinaryNode binaryNode) {
+                loadSHR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
+                loadCOMMALEFT(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
+                loadCOMMARIGHT(binaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterAND(final BinaryNode binaryNode) {
+                loadAND_OR(binaryNode, resultBounds, true);
+                return false;
+            }
+
+            @Override
+            public boolean enterOR(final BinaryNode binaryNode) {
+                loadAND_OR(binaryNode, resultBounds, false);
+                return false;
+            }
+
+            @Override
+            public boolean enterNOT(final UnaryNode unaryNode) {
+                loadNOT(unaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterADD(final UnaryNode unaryNode) {
+                loadADD(unaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterBIT_NOT(final UnaryNode unaryNode) {
+                loadBIT_NOT(unaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterBIT_AND(final BinaryNode binaryNode) {
+                loadBIT_AND(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterBIT_OR(final BinaryNode binaryNode) {
+                loadBIT_OR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterBIT_XOR(final BinaryNode binaryNode) {
+                loadBIT_XOR(binaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterVOID(final UnaryNode unaryNode) {
+                loadVOID(unaryNode, resultBounds);
+                return false;
+            }
+
+            @Override
+            public boolean enterEQ(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.EQ);
+                return false;
+            }
+
+            @Override
+            public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.EQ);
+                return false;
+            }
+
+            @Override
+            public boolean enterGE(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.GE);
+                return false;
+            }
+
+            @Override
+            public boolean enterGT(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.GT);
+                return false;
+            }
+
+            @Override
+            public boolean enterLE(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.LE);
+                return false;
+            }
+
+            @Override
+            public boolean enterLT(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.LT);
+                return false;
+            }
+
+            @Override
+            public boolean enterNE(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.NE);
+                return false;
+            }
+
+            @Override
+            public boolean enterNE_STRICT(final BinaryNode binaryNode) {
+                loadCmp(binaryNode, Condition.NE);
+                return false;
+            }
+
+            @Override
+            public boolean enterObjectNode(final ObjectNode objectNode) {
+                loadObjectNode(objectNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
+                loadRuntimeNode(runtimeNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterNEW(final UnaryNode unaryNode) {
+                loadNEW(unaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterDECINC(final UnaryNode unaryNode) {
+                loadDECINC(unaryNode);
+                return false;
+            }
+
+            @Override
+            public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinExpr) {
+                loadExpression(joinExpr.getExpression(), resultBounds);
+                return false;
             }
 
             @Override
             public boolean enterDefault(final Node otherNode) {
-                final Node currentDiscard = codegen.lc.getCurrentDiscard();
-                otherNode.accept(codegen); // generate code for whatever we are looking at.
-                if(currentDiscard != otherNode) {
-                    method.load(symbol); // load the final symbol to the stack (or nop if no slot, then result is already there)
-                    assert method.peekType() != null;
-                    method.convert(type);
-                }
-                return false;
+                // Must have handled all expressions that can legally be encountered.
+                throw new AssertionError(otherNode.getClass().getName());
             }
         });
-
+        if(currentDiscard != expr) {
+            coerceStackTop(resultBounds);
+        }
         return method;
     }
 
-    @Override
-    public boolean enterAccessNode(final AccessNode accessNode) {
-        load(accessNode);
-        return false;
+    private MethodEmitter coerceStackTop(final TypeBounds typeBounds) {
+        return method.convert(typeBounds.within(method.peekType()));
     }
 
     /**
-     * Initialize a specific set of vars to undefined. This has to be done at
-     * the start of each method for local variables that aren't passed as
-     * parameters.
-     *
-     * @param symbols list of symbols.
-     */
-    private void initSymbols(final Iterable<Symbol> symbols) {
-        final LinkedList<Symbol> numbers = new LinkedList<>();
-        final LinkedList<Symbol> objects = new LinkedList<>();
-
-        for (final Symbol symbol : symbols) {
-            /*
-             * The following symbols are guaranteed to be defined and thus safe
-             * from having undefined written to them: parameters internals this
-             *
-             * Otherwise we must, unless we perform control/escape analysis,
-             * assign them undefined.
-             */
-            final boolean isInternal = symbol.isParam() || symbol.isInternal() || symbol.isThis() || !symbol.canBeUndefined();
-
-            if (symbol.hasSlot() && !isInternal) {
-                assert symbol.getSymbolType().isNumber() || symbol.getSymbolType().isObject() : "no potentially undefined narrower local vars than doubles are allowed: " + symbol + " in " + lc.getCurrentFunction();
-                if (symbol.getSymbolType().isNumber()) {
-                    numbers.add(symbol);
-                } else if (symbol.getSymbolType().isObject()) {
-                    objects.add(symbol);
-                }
-            }
-        }
-
-        initSymbols(numbers, Type.NUMBER);
-        initSymbols(objects, Type.OBJECT);
-    }
-
-    private void initSymbols(final LinkedList<Symbol> symbols, final Type type) {
-        final Iterator<Symbol> it = symbols.iterator();
-        if(it.hasNext()) {
-            method.loadUndefined(type);
-            boolean hasNext;
-            do {
-                final Symbol symbol = it.next();
-                hasNext = it.hasNext();
-                if(hasNext) {
-                    method.dup();
-                }
-                method.store(symbol);
-            } while(hasNext);
-        }
-    }
-
-    /**
-     * Create symbol debug information.
+     * Closes any still open entries for this block's local variables in the bytecode local variable table.
      *
      * @param block block containing symbols.
      */
-    private void symbolInfo(final Block block) {
+    private void closeBlockVariables(final Block block) {
         for (final Symbol symbol : block.getSymbols()) {
-            if (symbol.hasSlot()) {
-                method.localVariable(symbol, block.getEntryLabel(), block.getBreakLabel());
+            if (symbol.isBytecodeLocal()) {
+                method.closeLocalVariable(symbol, block.getBreakLabel());
             }
         }
     }
 
     @Override
     public boolean enterBlock(final Block block) {
+        method.label(block.getEntryLabel());
+        if(!method.isReachable()) {
+            return false;
+        }
         if(lc.isFunctionBody() && emittedMethods.contains(lc.getCurrentFunction().getName())) {
             return false;
         }
-        method.label(block.getEntryLabel());
         initLocals(block);
 
+        assert lc.getUsedSlotCount() == method.getFirstTemp();
         return true;
     }
 
+    private boolean useOptimisticTypes() {
+        return !lc.inSplitNode() && compiler.useOptimisticTypes();
+    }
+
     @Override
     public Node leaveBlock(final Block block) {
-        method.label(block.getBreakLabel());
-        symbolInfo(block);
+        popBlockScope(block);
+        method.beforeJoinPoint(block);
 
-        if (block.needsScope() && !block.isTerminal()) {
-            popBlockScope(block);
-        }
+        closeBlockVariables(block);
+        lc.releaseSlots();
+        assert !method.isReachable() || (lc.isFunctionBody() ? 0 : lc.getUsedSlotCount()) == method.getFirstTemp() :
+            "reachable="+method.isReachable() +
+            " isFunctionBody=" + lc.isFunctionBody() +
+            " usedSlotCount=" + lc.getUsedSlotCount() +
+            " firstTemp=" + method.getFirstTemp();
+
         return block;
     }
 
     private void popBlockScope(final Block block) {
-        final Label exitLabel     = new Label("block_exit");
-        final Label recoveryLabel = new Label("block_catch");
-        final Label skipLabel     = new Label("skip_catch");
+        final Label breakLabel = block.getBreakLabel();
 
-        /* pop scope a la try-finally */
-        method.loadCompilerConstant(SCOPE);
-        method.invoke(ScriptObject.GET_PROTO);
-        method.storeCompilerConstant(SCOPE);
-        method._goto(skipLabel);
-        method.label(exitLabel);
+        if(!block.needsScope() || lc.isFunctionBody()) {
+            emitBlockBreakLabel(breakLabel);
+            return;
+        }
 
-        method._catch(recoveryLabel);
+        final Label beginTryLabel = scopeEntryLabels.pop();
+        final Label recoveryLabel = new Label("block_popscope_catch");
+        emitBlockBreakLabel(breakLabel);
+        final boolean bodyCanThrow = breakLabel.isAfter(beginTryLabel);
+        if(bodyCanThrow) {
+            method._try(beginTryLabel, breakLabel, recoveryLabel);
+        }
+
+        Label afterCatchLabel = null;
+
+        if(method.isReachable()) {
+            popScope();
+            if(bodyCanThrow) {
+                afterCatchLabel = new Label("block_after_catch");
+                method._goto(afterCatchLabel);
+            }
+        }
+
+        if(bodyCanThrow) {
+            assert !method.isReachable();
+            method._catch(recoveryLabel);
+            popScopeException();
+            method.athrow();
+        }
+        if(afterCatchLabel != null) {
+            method.label(afterCatchLabel);
+        }
+    }
+
+    private void emitBlockBreakLabel(final Label breakLabel) {
+        // TODO: this is totally backwards. Block should not be breakable, LabelNode should be breakable.
+        final LabelNode labelNode = lc.getCurrentBlockLabelNode();
+        if(labelNode != null) {
+            // Only have conversions if we're reachable
+            assert labelNode.getLocalVariableConversion() == null || method.isReachable();
+            method.beforeJoinPoint(labelNode);
+            method.breakLabel(breakLabel, labeledBlockBreakLiveLocals.pop());
+        } else {
+            method.label(breakLabel);
+        }
+    }
+
+    private void popScope() {
+        popScopes(1);
+    }
+
+    /**
+     * Pop scope as part of an exception handler. Similar to {@code popScope()} but also takes care of adjusting the
+     * number of scopes that needs to be popped in case a rest-of continuation handler encounters an exception while
+     * performing a ToPrimitive conversion.
+     */
+    private void popScopeException() {
+        popScope();
+        final ContinuationInfo ci = getContinuationInfo();
+        if(ci != null) {
+            final Label catchLabel = ci.catchLabel;
+            if(catchLabel != METHOD_BOUNDARY && catchLabel == catchLabels.peek()) {
+                ++ci.exceptionScopePops;
+            }
+        }
+    }
+
+    private void popScopesUntil(final LexicalContextNode until) {
+        popScopes(lc.getScopeNestingLevelTo(until));
+    }
+
+    private void popScopes(final int count) {
+        if(count == 0) {
+            return;
+        }
+        assert count > 0; // together with count == 0 check, asserts nonnegative count
+        if (!method.hasScope()) {
+            // We can sometimes invoke this method even if the method has no slot for the scope object. Typical example:
+            // for(;;) { with({}) { break; } }. WithNode normally creates a scope, but if it uses no identifiers and
+            // nothing else forces creation of a scope in the method, we just won't have the :scope local variable.
+            return;
+        }
         method.loadCompilerConstant(SCOPE);
-        method.invoke(ScriptObject.GET_PROTO);
+        for(int i = 0; i < count; ++i) {
+            method.invoke(ScriptObject.GET_PROTO);
+        }
         method.storeCompilerConstant(SCOPE);
-        method.athrow();
-        method.label(skipLabel);
-        method._try(block.getEntryLabel(), exitLabel, recoveryLabel, Throwable.class);
     }
 
     @Override
     public boolean enterBreakNode(final BreakNode breakNode) {
-        lineNumber(breakNode);
-
-        final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabel());
-        for (int i = 0; i < lc.getScopeNestingLevelTo(breakFrom); i++) {
-            closeWith();
+        if(!method.isReachable()) {
+            return false;
         }
-        method.splitAwareGoto(lc, breakFrom.getBreakLabel());
+        enterStatement(breakNode);
+
+        method.beforeJoinPoint(breakNode);
+        final BreakableNode breakFrom = lc.getBreakable(breakNode.getLabelName());
+        popScopesUntil(breakFrom);
+        final Label breakLabel = breakFrom.getBreakLabel();
+        breakLabel.markAsBreakTarget();
+        method.splitAwareGoto(lc, breakLabel, breakFrom);
 
         return false;
     }
 
     private int loadArgs(final List<Expression> args) {
-        return loadArgs(args, null, false, args.size());
-    }
-
-    private int loadArgs(final List<Expression> args, final String signature, final boolean isVarArg, final int argCount) {
+        final int argCount = args.size();
         // arg have already been converted to objects here.
-        if (isVarArg || argCount > LinkerCallSite.ARGLIMIT) {
+        if (argCount > LinkerCallSite.ARGLIMIT) {
             loadArgsArray(args);
             return 1;
         }
 
-        // pad with undefined if size is too short. argCount is the real number of args
-        int n = 0;
-        final Type[] params = signature == null ? null : Type.getMethodArguments(signature);
         for (final Expression arg : args) {
             assert arg != null;
-            if (n >= argCount) {
-                load(arg);
-                method.pop(); // we had to load the arg for its side effects
-            } else if (params != null) {
-                load(arg, params[n]);
-            } else {
-                load(arg);
-            }
-            n++;
+            loadExpressionUnbounded(arg);
         }
-
-        while (n < argCount) {
-            method.loadUndefined(Type.OBJECT);
-            n++;
-        }
-
         return argCount;
     }
 
-
-    @Override
-    public boolean enterCallNode(final CallNode callNode) {
-        return enterCallNode(callNode, callNode.getType());
-    }
-
-    private boolean enterCallNode(final CallNode callNode, final Type callNodeType) {
+    private boolean loadCallNode(final CallNode callNode, final TypeBounds resultBounds) {
         lineNumber(callNode.getLineNumber());
 
         final List<Expression> args = callNode.getArgs();
@@ -668,68 +1235,122 @@
 
             private MethodEmitter sharedScopeCall(final IdentNode identNode, final int flags) {
                 final Symbol symbol = identNode.getSymbol();
-                int    scopeCallFlags = flags;
-                method.loadCompilerConstant(SCOPE);
-                if (isFastScope(symbol)) {
-                    method.load(getScopeProtoDepth(currentBlock, symbol));
-                    scopeCallFlags |= CALLSITE_FAST_SCOPE;
-                } else {
-                    method.load(-1); // Bypass fast-scope code in shared callsite
-                }
-                loadArgs(args);
-                final Type[] paramTypes = method.getTypesFromStack(args.size());
-                final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol, identNode.getType(), callNodeType, paramTypes, scopeCallFlags);
-                return scopeCall.generateInvoke(method);
+                final boolean isFastScope = isFastScope(symbol);
+                final int scopeCallFlags = flags | (isFastScope ? CALLSITE_FAST_SCOPE : 0);
+                new OptimisticOperation(callNode, resultBounds) {
+                    @Override
+                    void loadStack() {
+                        method.loadCompilerConstant(SCOPE);
+                        if (isFastScope) {
+                            method.load(getScopeProtoDepth(currentBlock, symbol));
+                        } else {
+                            method.load(-1); // Bypass fast-scope code in shared callsite
+                        }
+                        loadArgs(args);
+                    }
+                    @Override
+                    void consumeStack() {
+                        final Type[] paramTypes = method.getTypesFromStack(args.size());
+                        // We have trouble finding e.g. in Type.typeFor(asm.Type) because it can't see the Context class
+                        // loader, so we need to weaken reference signatures to Object.
+                        for(int i = 0; i < paramTypes.length; ++i) {
+                            paramTypes[i] = Type.generic(paramTypes[i]);
+                        }
+                        // As shared scope calls are only used in non-optimistic compilation, we switch from using
+                        // TypeBounds to just a single definitive type, resultBounds.widest.
+                        final SharedScopeCall scopeCall = codegenLexicalContext.getScopeCall(unit, symbol,
+                                identNode.getType(), resultBounds.widest, paramTypes, scopeCallFlags);
+                        scopeCall.generateInvoke(method);
+                    }
+                }.emit();
+                return method;
             }
 
-            private void scopeCall(final IdentNode node, final int flags) {
-                load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
-                // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
-                method.loadUndefined(Type.OBJECT); //the 'this' object
-                method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
+            private void scopeCall(final IdentNode ident, final int flags) {
+                new OptimisticOperation(callNode, resultBounds) {
+                    int argsCount;
+                    @Override
+                    void loadStack() {
+                        loadExpressionAsObject(ident); // foo() makes no sense if foo == 3
+                        // ScriptFunction will see CALLSITE_SCOPE and will bind scope accordingly.
+                        method.loadUndefined(Type.OBJECT); //the 'this'
+                        argsCount = loadArgs(args);
+                    }
+                    @Override
+                    void consumeStack() {
+                        dynamicCall(2 + argsCount, flags);
+                    }
+                }.emit();
             }
 
-            private void evalCall(final IdentNode node, final int flags) {
-                load(node, Type.OBJECT); // Type.OBJECT as foo() makes no sense if foo == 3
-
-                final Label not_eval  = new Label("not_eval");
+            private void evalCall(final IdentNode ident, final int flags) {
+                final Label invoke_direct_eval  = new Label("invoke_direct_eval");
+                final Label is_not_eval  = new Label("is_not_eval");
                 final Label eval_done = new Label("eval_done");
 
-                // check if this is the real built-in eval
-                method.dup();
-                globalIsEval();
+                new OptimisticOperation(callNode, resultBounds) {
+                    int argsCount;
+                    @Override
+                    void loadStack() {
+                        /**
+                         * We want to load 'eval' to check if it is indeed global builtin eval.
+                         * If this eval call is inside a 'with' statement, dyn:getMethod|getProp|getElem
+                         * would be generated if ident is a "isFunction". But, that would result in a
+                         * bound function from WithObject. We don't want that as bound function as that
+                         * won't be detected as builtin eval. So, we make ident as "not a function" which
+                         * results in "dyn:getProp|getElem|getMethod" being generated and so WithObject
+                         * would return unbounded eval function.
+                         *
+                         * Example:
+                         *
+                         *  var global = this;
+                         *  function func() {
+                         *      with({ eval: global.eval) { eval("var x = 10;") }
+                         *  }
+                         */
+                        loadExpressionAsObject(ident.setIsNotFunction()); // Type.OBJECT as foo() makes no sense if foo == 3
+                        globalIsEval();
+                        method.ifeq(is_not_eval);
 
-                method.ifeq(not_eval);
-                // We don't need ScriptFunction object for 'eval'
-                method.pop();
+                        // Load up self (scope).
+                        method.loadCompilerConstant(SCOPE);
+                        final List<Expression> evalArgs = callNode.getEvalArgs().getArgs();
+                        // load evaluated code
+                        loadExpressionAsObject(evalArgs.get(0));
+                        // load second and subsequent args for side-effect
+                        final int numArgs = evalArgs.size();
+                        for (int i = 1; i < numArgs; i++) {
+                            loadAndDiscard(evalArgs.get(i));
+                        }
+                        method._goto(invoke_direct_eval);
 
-                method.loadCompilerConstant(SCOPE); // Load up self (scope).
+                        method.label(is_not_eval);
+                        // load this time but with dyn:getMethod|getProp|getElem
+                        loadExpressionAsObject(ident); // Type.OBJECT as foo() makes no sense if foo == 3
+                        // This is some scope 'eval' or global eval replaced by user
+                        // but not the built-in ECMAScript 'eval' function call
+                        method.loadNull();
+                        argsCount = loadArgs(callNode.getArgs());
+                    }
 
-                final CallNode.EvalArgs evalArgs = callNode.getEvalArgs();
-                // load evaluated code
-                load(evalArgs.getCode(), Type.OBJECT);
-                // load second and subsequent args for side-effect
-                final List<Expression> args = callNode.getArgs();
-                final int numArgs = args.size();
-                for (int i = 1; i < numArgs; i++) {
-                    load(args.get(i)).pop();
-                }
-                // special/extra 'eval' arguments
-                load(evalArgs.getThis());
-                method.load(evalArgs.getLocation());
-                method.load(evalArgs.getStrictMode());
-                method.convert(Type.OBJECT);
+                    @Override
+                    void consumeStack() {
+                        // Ordinary call
+                        dynamicCall(2 + argsCount, flags);
+                        method._goto(eval_done);
 
-                // direct call to Global.directEval
-                globalDirectEval();
-                method.convert(callNodeType);
-                method._goto(eval_done);
-
-                method.label(not_eval);
-                // This is some scope 'eval' or global eval replaced by user
-                // but not the built-in ECMAScript 'eval' function call
-                method.loadNull();
-                method.dynamicCall(callNodeType, 2 + loadArgs(args), flags);
+                        method.label(invoke_direct_eval);
+                        // Special/extra 'eval' arguments. These can be loaded late (in consumeStack) as we know none of
+                        // them can ever be optimistic.
+                        method.loadCompilerConstant(THIS);
+                        method.load(callNode.getEvalArgs().getLocation());
+                        method.load(CodeGenerator.this.lc.getCurrentFunction().isStrict());
+                        // direct call to Global.directEval
+                        globalDirectEval();
+                        convertOptimisticReturnValue();
+                        coerceStackTop(resultBounds);
+                    }
+                }.emit();
 
                 method.label(eval_done);
             }
@@ -748,13 +1369,14 @@
                     if (callNode.isEval()) {
                         evalCall(node, flags);
                     } else if (useCount <= SharedScopeCall.FAST_SCOPE_CALL_THRESHOLD
-                            || (!isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD)
-                            || CodeGenerator.this.lc.inDynamicScope()) {
+                            || !isFastScope(symbol) && useCount <= SharedScopeCall.SLOW_SCOPE_CALL_THRESHOLD
+                            || CodeGenerator.this.lc.inDynamicScope()
+                            || isOptimisticOrRestOf()) {
                         scopeCall(node, flags);
                     } else {
                         sharedScopeCall(node, flags);
                     }
-                    assert method.peekType().equals(callNodeType) : method.peekType() + "!=" + callNode.getType();
+                    assert method.peekType().equals(resultBounds.within(callNode.getType())) : method.peekType() + " != " + resultBounds + "(" + callNode.getType() + ")";
                 } else {
                     enterDefault(node);
                 }
@@ -764,104 +1386,170 @@
 
             @Override
             public boolean enterAccessNode(final AccessNode node) {
-                load(node.getBase(), Type.OBJECT);
-                method.dup();
-                method.dynamicGet(node.getType(), node.getProperty().getName(), getCallSiteFlags(), true);
-                method.swap();
-                method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags());
+                //check if this is an apply to call node. only real applies, that haven't been
+                //shadowed from their way to the global scope counts
+
+                //call nodes have program points.
+
+                final int flags = getCallSiteFlags() | (callNode.isApplyToCall() ? CALLSITE_APPLY_TO_CALL : 0);
+
+                new OptimisticOperation(callNode, resultBounds) {
+                    int argCount;
+                    @Override
+                    void loadStack() {
+                        loadExpressionAsObject(node.getBase());
+                        method.dup();
+                        // NOTE: not using a nested OptimisticOperation on this dynamicGet, as we expect to get back
+                        // a callable object. Nobody in their right mind would optimistically type this call site.
+                        assert !node.isOptimistic();
+                        method.dynamicGet(node.getType(), node.getProperty(), flags, true);
+                        method.swap();
+                        argCount = loadArgs(args);
+                    }
+                    @Override
+                    void consumeStack() {
+                        dynamicCall(2 + argCount, flags);
+                    }
+                }.emit();
 
                 return false;
             }
 
             @Override
             public boolean enterFunctionNode(final FunctionNode origCallee) {
-                // NOTE: visiting the callee will leave a constructed ScriptFunction object on the stack if
-                // callee.needsCallee() == true
-                final FunctionNode callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
+                new OptimisticOperation(callNode, resultBounds) {
+                    FunctionNode callee;
+                    int argsCount;
+                    @Override
+                    void loadStack() {
+                        callee = (FunctionNode)origCallee.accept(CodeGenerator.this);
+                        if (callee.isStrict()) { // "this" is undefined
+                            method.loadUndefined(Type.OBJECT);
+                        } else { // get global from scope (which is the self)
+                            globalInstance();
+                        }
+                        argsCount = loadArgs(args);
+                    }
 
-                final boolean      isVarArg = callee.isVarArg();
-                final int          argCount = isVarArg ? -1 : callee.getParameters().size();
-
-                final String signature = new FunctionSignature(true, callee.needsCallee(), callee.getReturnType(), isVarArg ? null : callee.getParameters()).toString();
-
-                if (callee.isStrict()) { // self is undefined
-                    method.loadUndefined(Type.OBJECT);
-                } else { // get global from scope (which is the self)
-                    globalInstance();
-                }
-                loadArgs(args, signature, isVarArg, argCount);
-                assert callee.getCompileUnit() != null : "no compile unit for " + callee.getName() + " " + Debug.id(callee) + " " + callNode;
-                method.invokestatic(callee.getCompileUnit().getUnitClassName(), callee.getName(), signature);
-                assert method.peekType().equals(callee.getReturnType()) : method.peekType() + " != " + callee.getReturnType();
-                method.convert(callNodeType);
+                    @Override
+                    void consumeStack() {
+                        final int flags = getCallSiteFlags();
+                        //assert callNodeType.equals(callee.getReturnType()) : callNodeType + " != " + callee.getReturnType();
+                        dynamicCall(2 + argsCount, flags);
+                    }
+                }.emit();
                 return false;
             }
 
             @Override
             public boolean enterIndexNode(final IndexNode node) {
-                load(node.getBase(), Type.OBJECT);
-                method.dup();
-                final Type indexType = node.getIndex().getType();
-                if (indexType.isObject() || indexType.isBoolean()) {
-                    load(node.getIndex(), Type.OBJECT); //TODO
-                } else {
-                    load(node.getIndex());
-                }
-                method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
-                method.swap();
-                method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags());
-
+                new OptimisticOperation(callNode, resultBounds) {
+                    int argsCount;
+                    @Override
+                    void loadStack() {
+                        loadExpressionAsObject(node.getBase());
+                        method.dup();
+                        final Type indexType = node.getIndex().getType();
+                        if (indexType.isObject() || indexType.isBoolean()) {
+                            loadExpressionAsObject(node.getIndex()); //TODO boolean
+                        } else {
+                            loadExpressionUnbounded(node.getIndex());
+                        }
+                        // NOTE: not using a nested OptimisticOperation on this dynamicGetIndex, as we expect to get
+                        // back a callable object. Nobody in their right mind would optimistically type this call site.
+                        assert !node.isOptimistic();
+                        method.dynamicGetIndex(node.getType(), getCallSiteFlags(), true);
+                        method.swap();
+                        argsCount = loadArgs(args);
+                    }
+                    @Override
+                    void consumeStack() {
+                        final int flags = getCallSiteFlags();
+                        dynamicCall(2 + argsCount, flags);
+                    }
+                }.emit();
                 return false;
             }
 
             @Override
             protected boolean enterDefault(final Node node) {
-                // Load up function.
-                load(function, Type.OBJECT); //TODO, e.g. booleans can be used as functions
-                method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
-                method.dynamicCall(callNodeType, 2 + loadArgs(args), getCallSiteFlags() | CALLSITE_SCOPE);
-
+                new OptimisticOperation(callNode, resultBounds) {
+                    int argsCount;
+                    @Override
+                    void loadStack() {
+                        // Load up function.
+                        loadExpressionAsObject(function); //TODO, e.g. booleans can be used as functions
+                        method.loadUndefined(Type.OBJECT); // ScriptFunction will figure out the correct this when it sees CALLSITE_SCOPE
+                        argsCount = loadArgs(args);
+                        }
+                        @Override
+                        void consumeStack() {
+                            final int flags = getCallSiteFlags() | CALLSITE_SCOPE;
+                            dynamicCall(2 + argsCount, flags);
+                        }
+                }.emit();
                 return false;
             }
         });
 
-        method.store(callNode.getSymbol());
-
         return false;
     }
 
+    /**
+     * Returns the flags with optimistic flag and program point removed.
+     * @param flags the flags that need optimism stripped from them.
+     * @return flags without optimism
+     */
+    static int nonOptimisticFlags(final int flags) {
+        return flags & ~(CALLSITE_OPTIMISTIC | -1 << CALLSITE_PROGRAM_POINT_SHIFT);
+    }
+
     @Override
     public boolean enterContinueNode(final ContinueNode continueNode) {
-        lineNumber(continueNode);
-
-        final LoopNode continueTo = lc.getContinueTo(continueNode.getLabel());
-        for (int i = 0; i < lc.getScopeNestingLevelTo(continueTo); i++) {
-            closeWith();
+        if(!method.isReachable()) {
+            return false;
         }
-        method.splitAwareGoto(lc, continueTo.getContinueLabel());
+        enterStatement(continueNode);
+        method.beforeJoinPoint(continueNode);
+
+        final LoopNode continueTo = lc.getContinueTo(continueNode.getLabelName());
+        popScopesUntil(continueTo);
+        final Label continueLabel = continueTo.getContinueLabel();
+        continueLabel.markAsBreakTarget();
+        method.splitAwareGoto(lc, continueLabel, continueTo);
 
         return false;
     }
 
     @Override
     public boolean enterEmptyNode(final EmptyNode emptyNode) {
-        lineNumber(emptyNode);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(emptyNode);
 
         return false;
     }
 
     @Override
     public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
-        lineNumber(expressionStatement);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(expressionStatement);
 
-        expressionStatement.getExpression().accept(this);
+        loadAndDiscard(expressionStatement.getExpression());
+        assert method.getStackSize() == 0;
 
         return false;
     }
 
     @Override
     public boolean enterBlockStatement(final BlockStatement blockStatement) {
-        lineNumber(blockStatement);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(blockStatement);
 
         blockStatement.getBlock().accept(this);
 
@@ -870,83 +1558,70 @@
 
     @Override
     public boolean enterForNode(final ForNode forNode) {
-        lineNumber(forNode);
-
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(forNode);
         if (forNode.isForIn()) {
             enterForIn(forNode);
         } else {
-            enterFor(forNode);
+            final Expression init = forNode.getInit();
+            if (init != null) {
+                loadAndDiscard(init);
+            }
+            enterForOrWhile(forNode, forNode.getModify());
         }
 
         return false;
     }
 
-    private void enterFor(final ForNode forNode) {
-        final Expression init   = forNode.getInit();
-        final Expression test   = forNode.getTest();
-        final Block      body   = forNode.getBody();
-        final Expression modify = forNode.getModify();
-
-        if (init != null) {
-            init.accept(this);
-        }
-
-        final Label loopLabel = new Label("loop");
-        final Label testLabel = new Label("test");
-
-        method._goto(testLabel);
-        method.label(loopLabel);
-        body.accept(this);
-        method.label(forNode.getContinueLabel());
-
-        if (!body.isTerminal() && modify != null) {
-            load(modify);
-        }
-
-        method.label(testLabel);
-        if (test != null) {
-            new BranchOptimizer(this, method).execute(test, loopLabel, true);
-        } else {
-            method._goto(loopLabel);
-        }
-
-        method.label(forNode.getBreakLabel());
-    }
-
     private void enterForIn(final ForNode forNode) {
-        final Block body   = forNode.getBody();
-        final Expression  modify = forNode.getModify();
-
-        final Symbol iter      = forNode.getIterator();
-        final Label  loopLabel = new Label("loop");
-
-        final Expression init = forNode.getInit();
-
-        load(modify, Type.OBJECT);
+        loadExpression(forNode.getModify(), TypeBounds.OBJECT);
         method.invoke(forNode.isForEach() ? ScriptRuntime.TO_VALUE_ITERATOR : ScriptRuntime.TO_PROPERTY_ITERATOR);
-        method.store(iter);
-        method._goto(forNode.getContinueLabel());
-        method.label(loopLabel);
+        final Symbol iterSymbol = forNode.getIterator();
+        final int iterSlot = iterSymbol.getSlot(Type.OBJECT);
+        method.store(iterSymbol, ITERATOR_TYPE);
 
-        new Store<Expression>(init) {
+        method.beforeJoinPoint(forNode);
+
+        final Label continueLabel = forNode.getContinueLabel();
+        final Label breakLabel    = forNode.getBreakLabel();
+
+        method.label(continueLabel);
+        method.load(ITERATOR_TYPE, iterSlot);
+        method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "hasNext", boolean.class));
+        final JoinPredecessorExpression test = forNode.getTest();
+        final Block body = forNode.getBody();
+        if(LocalVariableConversion.hasLiveConversion(test)) {
+            final Label afterConversion = new Label("for_in_after_test_conv");
+            method.ifne(afterConversion);
+            method.beforeJoinPoint(test);
+            method._goto(breakLabel);
+            method.label(afterConversion);
+        } else {
+            method.ifeq(breakLabel);
+        }
+
+        new Store<Expression>(forNode.getInit()) {
             @Override
             protected void storeNonDiscard() {
-                return;
+                // This expression is neither part of a discard, nor needs to be left on the stack after it was
+                // stored, so we override storeNonDiscard to be a no-op.
             }
+
             @Override
             protected void evaluate() {
-                method.load(iter);
-                method.invoke(interfaceCallNoLookup(Iterator.class, "next", Object.class));
+                method.load(ITERATOR_TYPE, iterSlot);
+                // TODO: optimistic for-in iteration
+                method.invoke(interfaceCallNoLookup(ITERATOR_CLASS, "next", Object.class));
             }
         }.store();
-
         body.accept(this);
 
-        method.label(forNode.getContinueLabel());
-        method.load(iter);
-        method.invoke(interfaceCallNoLookup(Iterator.class, "hasNext", boolean.class));
-        method.ifne(loopLabel);
-        method.label(forNode.getBreakLabel());
+        if(method.isReachable()) {
+            method._goto(continueLabel);
+        }
+        method.label(breakLabel);
     }
 
     /**
@@ -955,13 +1630,16 @@
      * @param block block with local vars.
      */
     private void initLocals(final Block block) {
-        lc.nextFreeSlot(block);
+        lc.onEnterBlock(block);
 
         final boolean isFunctionBody = lc.isFunctionBody();
-
         final FunctionNode function = lc.getCurrentFunction();
         if (isFunctionBody) {
-            if(method.hasScope()) {
+            initializeMethodParameters(function);
+            if(!function.isVarArg()) {
+                expandParameterSlots(function);
+            }
+            if (method.hasScope()) {
                 if (function.needsParentScope()) {
                     method.loadCompilerConstant(CALLEE);
                     method.invoke(ScriptFunction.GET_SCOPE);
@@ -988,76 +1666,173 @@
 
             // TODO for LET we can do better: if *block* does not contain any eval/with, we don't need its vars in scope.
 
-            final List<String> nameList = new ArrayList<>();
-            final List<Symbol> locals   = new ArrayList<>();
-
-            // Initalize symbols and values
-            final List<Symbol> newSymbols = new ArrayList<>();
-            final List<Symbol> values     = new ArrayList<>();
-
             final boolean hasArguments = function.needsArguments();
-
+            final List<MapTuple<Symbol>> tuples = new ArrayList<>();
+            final Iterator<IdentNode> paramIter = function.getParameters().iterator();
             for (final Symbol symbol : block.getSymbols()) {
-
-                if (symbol.isInternal() || symbol.isThis() || symbol.isTemp()) {
+                if (symbol.isInternal() || symbol.isThis()) {
                     continue;
                 }
 
                 if (symbol.isVar()) {
+                    assert !varsInScope || symbol.isScope();
                     if (varsInScope || symbol.isScope()) {
-                        nameList.add(symbol.getName());
-                        newSymbols.add(symbol);
-                        values.add(null);
                         assert symbol.isScope()   : "scope for " + symbol + " should have been set in Lower already " + function.getName();
                         assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already" + function.getName();
+
+                        //this tuple will not be put fielded, as it has no value, just a symbol
+                        tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, null));
                     } else {
-                        assert symbol.hasSlot() : symbol + " should have a slot only, no scope";
-                        locals.add(symbol);
+                        assert symbol.hasSlot() || symbol.slotCount() == 0 : symbol + " should have a slot only, no scope";
                     }
                 } else if (symbol.isParam() && (varsInScope || hasArguments || symbol.isScope())) {
-                    nameList.add(symbol.getName());
-                    newSymbols.add(symbol);
-                    values.add(hasArguments ? null : symbol);
-                    assert symbol.isScope()   : "scope for " + symbol + " should have been set in Lower already " + function.getName() + " varsInScope="+varsInScope+" hasArguments="+hasArguments+" symbol.isScope()=" + symbol.isScope();
+                    assert symbol.isScope()   : "scope for " + symbol + " should have been set in AssignSymbols already " + function.getName() + " varsInScope="+varsInScope+" hasArguments="+hasArguments+" symbol.isScope()=" + symbol.isScope();
                     assert !(hasArguments && symbol.hasSlot())  : "slot for " + symbol + " should have been removed in Lower already " + function.getName();
+
+                    final Type   paramType;
+                    final Symbol paramSymbol;
+
+                    if (hasArguments) {
+                        assert !symbol.hasSlot()  : "slot for " + symbol + " should have been removed in Lower already ";
+                        paramSymbol = null;
+                        paramType   = null;
+                    } else {
+                        paramSymbol = symbol;
+                        // NOTE: We're relying on the fact here that Block.symbols is a LinkedHashMap, hence it will
+                        // return symbols in the order they were defined, and parameters are defined in the same order
+                        // they appear in the function. That's why we can have a single pass over the parameter list
+                        // with an iterator, always just scanning forward for the next parameter that matches the symbol
+                        // name.
+                        for(;;) {
+                            final IdentNode nextParam = paramIter.next();
+                            if(nextParam.getName().equals(symbol.getName())) {
+                                paramType = nextParam.getType();
+                                break;
+                            }
+                        }
+                    }
+
+                    tuples.add(new MapTuple<Symbol>(symbol.getName(), symbol, paramType, paramSymbol) {
+                        //this symbol will be put fielded, we can't initialize it as undefined with a known type
+                        @Override
+                        public Class<?> getValueType() {
+                            if (OBJECT_FIELDS_ONLY || value == null || paramType == null) {
+                                return Object.class;
+                            }
+                            return paramType.isBoolean() ? Object.class : paramType.getTypeClass();
+                        }
+                    });
                 }
             }
 
-            // we may have locals that need to be initialized
-            initSymbols(locals);
-
             /*
              * Create a new object based on the symbols and values, generate
              * bootstrap code for object
              */
-            new FieldObjectCreator<Symbol>(this, nameList, newSymbols, values, true, hasArguments) {
+            new FieldObjectCreator<Symbol>(this, tuples, true, hasArguments) {
                 @Override
-                protected void loadValue(final Symbol value) {
-                    method.load(value);
+                protected void loadValue(final Symbol value, final Type type) {
+                    method.load(value, type);
                 }
             }.makeObject(method);
-
-            // runScript(): merge scope into global
+            // program function: merge scope into global
             if (isFunctionBody && function.isProgram()) {
                 method.invoke(ScriptRuntime.MERGE_SCOPE);
             }
 
             method.storeCompilerConstant(SCOPE);
-        } else {
+            if(!isFunctionBody) {
+                // Function body doesn't need a try/catch to restore scope, as it'd be a dead store anyway. Allowing it
+                // actually causes issues with UnwarrantedOptimismException handlers as ASM will sort this handler to
+                // the top of the exception handler table, so it'll be triggered instead of the UOE handlers.
+                final Label scopeEntryLabel = new Label("scope_entry");
+                scopeEntryLabels.push(scopeEntryLabel);
+                method.label(scopeEntryLabel);
+            }
+        } else if (isFunctionBody && function.isVarArg()) {
             // Since we don't have a scope, parameters didn't get assigned array indices by the FieldObjectCreator, so
             // we need to assign them separately here.
             int nextParam = 0;
-            if (isFunctionBody && function.isVarArg()) {
-                for (final IdentNode param : function.getParameters()) {
-                    param.getSymbol().setFieldIndex(nextParam++);
-                }
+            for (final IdentNode param : function.getParameters()) {
+                param.getSymbol().setFieldIndex(nextParam++);
             }
-
-            initSymbols(block.getSymbols());
         }
 
         // Debugging: print symbols? @see --print-symbols flag
-        printSymbols(block, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
+        printSymbols(block, function, (isFunctionBody ? "Function " : "Block in ") + (function.getIdent() == null ? "<anonymous>" : function.getIdent().getName()));
+    }
+
+    /**
+     * Incoming method parameters are always declared on method entry; declare them in the local variable table.
+     * @param function function for which code is being generated.
+     */
+    private void initializeMethodParameters(final FunctionNode function) {
+        final Label functionStart = new Label("fn_start");
+        method.label(functionStart);
+        int nextSlot = 0;
+        if(function.needsCallee()) {
+            initializeInternalFunctionParameter(CALLEE, function, functionStart, nextSlot++);
+        }
+        initializeInternalFunctionParameter(THIS, function, functionStart, nextSlot++);
+        if(function.isVarArg()) {
+            initializeInternalFunctionParameter(VARARGS, function, functionStart, nextSlot++);
+        } else {
+            for(final IdentNode param: function.getParameters()) {
+                final Symbol symbol = param.getSymbol();
+                if(symbol.isBytecodeLocal()) {
+                    method.initializeMethodParameter(symbol, param.getType(), functionStart);
+                }
+            }
+        }
+    }
+
+    private void initializeInternalFunctionParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
+        final Symbol symbol = initializeInternalFunctionOrSplitParameter(cc, fn, functionStart, slot);
+        // Internal function params (:callee, this, and :varargs) are never expanded to multiple slots
+        assert symbol.getFirstSlot() == slot;
+    }
+
+    private Symbol initializeInternalFunctionOrSplitParameter(final CompilerConstants cc, final FunctionNode fn, final Label functionStart, final int slot) {
+        final Symbol symbol = fn.getBody().getExistingSymbol(cc.symbolName());
+        final Type type = Type.typeFor(cc.type());
+        method.initializeMethodParameter(symbol, type, functionStart);
+        method.onLocalStore(type, slot);
+        return symbol;
+    }
+
+    /**
+     * Parameters come into the method packed into local variable slots next to each other. Nashorn on the other hand
+     * can use 1-6 slots for a local variable depending on all the types it needs to store. When this method is invoked,
+     * the symbols are already allocated such wider slots, but the values are still in tightly packed incoming slots,
+     * and we need to spread them into their new locations.
+     * @param function the function for which parameter-spreading code needs to be emitted
+     */
+    private void expandParameterSlots(final FunctionNode function) {
+        final List<IdentNode> parameters = function.getParameters();
+        // Calculate the total number of incoming parameter slots
+        int currentIncomingSlot = function.needsCallee() ? 2 : 1;
+        for(final IdentNode parameter: parameters) {
+            currentIncomingSlot += parameter.getType().getSlots();
+        }
+        // Starting from last parameter going backwards, move the parameter values into their new slots.
+        for(int i = parameters.size(); i-- > 0;) {
+            final IdentNode parameter = parameters.get(i);
+            final Type parameterType = parameter.getType();
+            final int typeWidth = parameterType.getSlots();
+            currentIncomingSlot -= typeWidth;
+            final Symbol symbol = parameter.getSymbol();
+            final int slotCount = symbol.slotCount();
+            assert slotCount > 0;
+            // Scoped parameters must not hold more than one value
+            assert symbol.isBytecodeLocal() || slotCount == typeWidth;
+
+            // Mark it as having its value stored into it by the method invocation.
+            method.onLocalStore(parameterType, currentIncomingSlot);
+            if(currentIncomingSlot != symbol.getSlot(parameterType)) {
+                method.load(parameterType, currentIncomingSlot);
+                method.store(symbol, parameterType);
+            }
+        }
     }
 
     private void initArguments(final FunctionNode function) {
@@ -1075,15 +1850,45 @@
         method.storeCompilerConstant(ARGUMENTS);
     }
 
+    private boolean skipFunction(final FunctionNode functionNode) {
+        final ScriptEnvironment env = compiler.getScriptEnvironment();
+        final boolean lazy = env._lazy_compilation;
+        final boolean onDemand = compiler.isOnDemandCompilation();
+
+        // If this is on-demand or lazy compilation, don't compile a nested (not topmost) function.
+        if((onDemand || lazy) && lc.getOutermostFunction() != functionNode) {
+            return true;
+        }
+
+        // If lazy compiling with optimistic types, don't compile the program eagerly either. It will soon be
+        // invalidated anyway. In presence of a class cache, this further means that an obsoleted program version
+        // lingers around. Also, currently loading previously persisted optimistic types information only works if
+        // we're on-demand compiling a function, so with this strategy the :program method can also have the warmup
+        // benefit of using previously persisted types.
+        //
+        // NOTE that this means the first compiled class will effectively just have a :createProgramFunction method, and
+        // the RecompilableScriptFunctionData (RSFD) object in its constants array. It won't even have the :program
+        // method. This is by design. It does mean that we're wasting one compiler execution (and we could minimize this
+        // by just running it up to scope depth calculation, which creates the RSFDs and then this limited codegen).
+        // We could emit an initial separate compile unit with the initial version of :program in it to better utilize
+        // the compilation pipeline, but that would need more invasive changes, as currently the assumption that
+        // :program is emitted into the first compilation unit of the function lives in many places.
+        return !onDemand && lazy && env._optimistic_types && functionNode.isProgram();
+    }
+
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        if (functionNode.isLazy()) {
-            // Must do it now; can't postpone it until leaveFunctionNode()
-            newFunctionObject(functionNode, functionNode);
+        final int fnId = functionNode.getId();
+
+        if (skipFunction(functionNode)) {
+            // In case we are not generating code for the function, we must create or retrieve the function object and
+            // load it on the stack here.
+            newFunctionObject(functionNode, false);
             return false;
         }
 
         final String fnName = functionNode.getName();
+
         // NOTE: we only emit the method for a function with the given name once. We can have multiple functions with
         // the same name as a result of inlining finally blocks. However, in the future -- with type specialization,
         // notably -- we might need to check for both name *and* signature. Of course, even that might not be
@@ -1092,35 +1897,67 @@
         // to decide to either generate a unique method for each inlined copy of the function, maybe figure out its
         // exact type closure and deduplicate based on that, or just decide that functions in finally blocks aren't
         // worth it, and generate one method with most generic type closure.
-        if(!emittedMethods.contains(fnName)) {
-            LOG.info("=== BEGIN ", fnName);
+        if (!emittedMethods.contains(fnName)) {
+            log.info("=== BEGIN ", fnName);
 
             assert functionNode.getCompileUnit() != null : "no compile unit for " + fnName + " " + Debug.id(functionNode);
             unit = lc.pushCompileUnit(functionNode.getCompileUnit());
             assert lc.hasCompileUnits();
 
-            method = lc.pushMethodEmitter(unit.getClassEmitter().method(functionNode));
+            final ClassEmitter classEmitter = unit.getClassEmitter();
+            pushMethodEmitter(isRestOf() ? classEmitter.restOfMethod(functionNode) : classEmitter.method(functionNode));
+            method.setPreventUndefinedLoad();
+            if(useOptimisticTypes()) {
+                lc.pushUnwarrantedOptimismHandlers();
+            }
+
             // new method - reset last line number
             lastLineNumber = -1;
-            // Mark end for variable tables.
+
             method.begin();
+
+            if (isRestOf()) {
+                final ContinuationInfo ci = new ContinuationInfo();
+                fnIdToContinuationInfo.put(fnId, ci);
+                method.gotoLoopStart(ci.getHandlerLabel());
+            }
         }
 
         return true;
     }
 
+    private void pushMethodEmitter(final MethodEmitter newMethod) {
+        method = lc.pushMethodEmitter(newMethod);
+        catchLabels.push(METHOD_BOUNDARY);
+    }
+
+    private void popMethodEmitter() {
+        method = lc.popMethodEmitter(method);
+        assert catchLabels.peek() == METHOD_BOUNDARY;
+        catchLabels.pop();
+    }
+
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         try {
-            if(emittedMethods.add(functionNode.getName())) {
+            final boolean markOptimistic;
+            if (emittedMethods.add(functionNode.getName())) {
+                markOptimistic = generateUnwarrantedOptimismExceptionHandlers(functionNode);
+                generateContinuationHandler();
                 method.end(); // wrap up this method
                 unit   = lc.popCompileUnit(functionNode.getCompileUnit());
-                method = lc.popMethodEmitter(method);
-                LOG.info("=== END ", functionNode.getName());
+                popMethodEmitter();
+                log.info("=== END ", functionNode.getName());
+            } else {
+                markOptimistic = false;
             }
 
-            final FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.EMITTED);
-            newFunctionObject(newFunctionNode, functionNode);
+            FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.BYTECODE_GENERATED);
+            if (markOptimistic) {
+                newFunctionNode = newFunctionNode.setFlag(lc, FunctionNode.IS_DEOPTIMIZABLE);
+            }
+
+            newFunctionObject(newFunctionNode, true);
             return newFunctionNode;
         } catch (final Throwable t) {
             Context.printStackTrace(t);
@@ -1131,64 +1968,64 @@
     }
 
     @Override
-    public boolean enterIdentNode(final IdentNode identNode) {
-        return false;
-    }
-
-    @Override
     public boolean enterIfNode(final IfNode ifNode) {
-        lineNumber(ifNode);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(ifNode);
 
         final Expression test = ifNode.getTest();
         final Block pass = ifNode.getPass();
         final Block fail = ifNode.getFail();
+        final boolean hasFailConversion = LocalVariableConversion.hasLiveConversion(ifNode);
 
         final Label failLabel  = new Label("if_fail");
-        final Label afterLabel = fail == null ? failLabel : new Label("if_done");
+        final Label afterLabel = (fail == null && !hasFailConversion) ? null : new Label("if_done");
 
-        new BranchOptimizer(this, method).execute(test, failLabel, false);
-
-        boolean passTerminal = false;
-        boolean failTerminal = false;
+        emitBranch(test, failLabel, false);
 
         pass.accept(this);
-        if (!pass.hasTerminalFlags()) {
+        if(method.isReachable() && afterLabel != null) {
             method._goto(afterLabel); //don't fallthru to fail block
-        } else {
-            passTerminal = pass.isTerminal();
         }
+        method.label(failLabel);
 
         if (fail != null) {
-            method.label(failLabel);
             fail.accept(this);
-            failTerminal = fail.isTerminal();
+        } else if(hasFailConversion) {
+            method.beforeJoinPoint(ifNode);
         }
 
-        //if if terminates, put the after label there
-        if (!passTerminal || !failTerminal) {
+        if(afterLabel != null) {
             method.label(afterLabel);
         }
 
         return false;
     }
 
-    @Override
-    public boolean enterIndexNode(final IndexNode indexNode) {
-        load(indexNode);
-        return false;
+    private void emitBranch(final Expression test, final Label label, final boolean jumpWhenTrue) {
+        new BranchOptimizer(this, method).execute(test, label, jumpWhenTrue);
+    }
+
+    private void enterStatement(final Statement statement) {
+        lineNumber(statement);
     }
 
     private void lineNumber(final Statement statement) {
         lineNumber(statement.getLineNumber());
     }
 
-    private void lineNumber(int lineNumber) {
+    private void lineNumber(final int lineNumber) {
         if (lineNumber != lastLineNumber) {
             method.lineNumber(lineNumber);
         }
         lastLineNumber = lineNumber;
     }
 
+    int getLastLineNumber() {
+        return lastLineNumber;
+    }
+
     /**
      * Load a list of nodes as an array of a specific type
      * The array will contain the visited nodes.
@@ -1219,26 +2056,34 @@
                 unit = lc.pushCompileUnit(arrayUnit.getCompileUnit());
 
                 final String className = unit.getUnitClassName();
+                assert unit != null;
                 final String name      = currentFunction.uniqueName(SPLIT_PREFIX.symbolName());
                 final String signature = methodDescriptor(type, ScriptFunction.class, Object.class, ScriptObject.class, type);
 
-                final MethodEmitter me = unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature);
-                method = lc.pushMethodEmitter(me);
+                pushMethodEmitter(unit.getClassEmitter().method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), name, signature));
 
                 method.setFunctionNode(currentFunction);
                 method.begin();
 
+                defineCommonSplitMethodParameters();
+                defineSplitMethodParameter(3, arrayType);
+
                 fixScopeSlot(currentFunction);
 
-                method.load(arrayType, SPLIT_ARRAY_ARG.slot());
+                lc.enterSplitNode();
 
+                final int arraySlot = SPLIT_ARRAY_ARG.slot();
                 for (int i = arrayUnit.getLo(); i < arrayUnit.getHi(); i++) {
+                    method.load(arrayType, arraySlot);
                     storeElement(nodes, elementType, postsets[i]);
                 }
 
+                method.load(arrayType, arraySlot);
                 method._return();
+                lc.exitSplitNode();
                 method.end();
-                method = lc.popMethodEmitter(me);
+                lc.releaseSlots();
+                popMethodEmitter();
 
                 assert method == savedMethod;
                 method.loadCompilerConstant(CALLEE);
@@ -1255,15 +2100,19 @@
             return method;
         }
 
-        for (final int postset : postsets) {
-            storeElement(nodes, elementType, postset);
+        if(postsets.length > 0) {
+            final int arraySlot = method.getUsedSlotsWithLiveTemporaries();
+            method.storeTemp(arrayType, arraySlot);
+            for (final int postset : postsets) {
+                method.load(arrayType, arraySlot);
+                storeElement(nodes, elementType, postset);
+            }
+            method.load(arrayType, arraySlot);
         }
-
         return method;
     }
 
     private void storeElement(final Expression[] nodes, final Type elementType, final int index) {
-        method.dup();
         method.load(index);
 
         final Expression element = nodes[index];
@@ -1271,7 +2120,7 @@
         if (element == null) {
             method.loadEmpty(elementType);
         } else {
-            load(element, elementType);
+            loadExpressionAsType(element, elementType);
         }
 
         method.arraystore();
@@ -1284,7 +2133,7 @@
         for (int i = 0; i < args.size(); i++) {
             method.dup();
             method.load(i);
-            load(args.get(i), Type.OBJECT); //has to be upcast to object or we fail
+            loadExpression(args.get(i), TypeBounds.OBJECT); // variable arity methods always take objects
             method.arraystore();
         }
 
@@ -1314,44 +2163,48 @@
      * @param object object to load
      */
     void loadConstant(final Object object) {
-        final String       unitClassName = unit.getUnitClassName();
-        final ClassEmitter classEmitter  = unit.getClassEmitter();
+        loadConstant(object, unit, method);
+    }
+
+    private void loadConstant(final Object object, final CompileUnit compileUnit, final MethodEmitter methodEmitter) {
+        final String       unitClassName = compileUnit.getUnitClassName();
+        final ClassEmitter classEmitter  = compileUnit.getClassEmitter();
         final int          index         = compiler.getConstantData().add(object);
         final Class<?>     cls           = object.getClass();
 
         if (cls == PropertyMap.class) {
-            method.load(index);
-            method.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
+            methodEmitter.load(index);
+            methodEmitter.invokestatic(unitClassName, GET_MAP.symbolName(), methodDescriptor(PropertyMap.class, int.class));
             classEmitter.needGetConstantMethod(PropertyMap.class);
         } else if (cls.isArray()) {
-            method.load(index);
+            methodEmitter.load(index);
             final String methodName = ClassEmitter.getArrayMethodName(cls);
-            method.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
+            methodEmitter.invokestatic(unitClassName, methodName, methodDescriptor(cls, int.class));
             classEmitter.needGetConstantMethod(cls);
         } else {
-            method.loadConstants().load(index).arrayload();
+            methodEmitter.loadConstants().load(index).arrayload();
             if (object instanceof ArrayData) {
                 // avoid cast to non-public ArrayData subclass
-                method.checkcast(ArrayData.class);
-                method.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
+                methodEmitter.checkcast(ArrayData.class);
+                methodEmitter.invoke(virtualCallNoLookup(ArrayData.class, "copy", ArrayData.class));
             } else if (cls != Object.class) {
-                method.checkcast(cls);
+                methodEmitter.checkcast(cls);
             }
         }
     }
 
     // literal values
-    private MethodEmitter loadLiteral(final LiteralNode<?> node, final Type type) {
+    private void loadLiteral(final LiteralNode<?> node, final TypeBounds resultBounds) {
         final Object value = node.getValue();
 
         if (value == null) {
             method.loadNull();
         } else if (value instanceof Undefined) {
-            method.loadUndefined(Type.OBJECT);
+            method.loadUndefined(resultBounds.within(Type.OBJECT));
         } else if (value instanceof String) {
             final String string = (String)value;
 
-            if (string.length() > (MethodEmitter.LARGE_STRING_THRESHOLD / 3)) { // 3 == max bytes per encoded char
+            if (string.length() > MethodEmitter.LARGE_STRING_THRESHOLD / 3) { // 3 == max bytes per encoded char
                 loadConstant(string);
             } else {
                 method.load(string);
@@ -1361,31 +2214,40 @@
         } else if (value instanceof Boolean) {
             method.load((Boolean)value);
         } else if (value instanceof Integer) {
-            if(type.isEquivalentTo(Type.NUMBER)) {
+            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
+                method.load((Integer)value);
+                method.convert(Type.OBJECT);
+            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
                 method.load(((Integer)value).doubleValue());
-            } else if(type.isEquivalentTo(Type.LONG)) {
+            } else if(!resultBounds.canBeNarrowerThan(Type.LONG)) {
                 method.load(((Integer)value).longValue());
             } else {
                 method.load((Integer)value);
             }
         } else if (value instanceof Long) {
-            if(type.isEquivalentTo(Type.NUMBER)) {
+            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
+                method.load((Long)value);
+                method.convert(Type.OBJECT);
+            } else if(!resultBounds.canBeNarrowerThan(Type.NUMBER)) {
                 method.load(((Long)value).doubleValue());
             } else {
                 method.load((Long)value);
             }
         } else if (value instanceof Double) {
-            method.load((Double)value);
+            if(!resultBounds.canBeNarrowerThan(Type.OBJECT)) {
+                method.load((Double)value);
+                method.convert(Type.OBJECT);
+            } else {
+                method.load((Double)value);
+            }
         } else if (node instanceof ArrayLiteralNode) {
             final ArrayLiteralNode arrayLiteral = (ArrayLiteralNode)node;
             final ArrayType atype = arrayLiteral.getArrayType();
             loadArray(arrayLiteral, atype);
             globalAllocateArray(atype);
         } else {
-            assert false : "Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value;
+            throw new UnsupportedOperationException("Unknown literal for " + node.getClass() + " " + value.getClass() + " " + value);
         }
-
-        return method;
     }
 
     private MethodEmitter loadRegexToken(final RegexToken value) {
@@ -1422,35 +2284,65 @@
         return method;
     }
 
-    @Override
-    public boolean enterLiteralNode(final LiteralNode<?> literalNode) {
-        return enterLiteralNode(literalNode, literalNode.getType());
+    /**
+     * Check if a property value contains a particular program point
+     * @param value value
+     * @param pp    program point
+     * @return true if it's there.
+     */
+    private static boolean propertyValueContains(final Expression value, final int pp) {
+        return new Supplier<Boolean>() {
+            boolean contains;
+
+            @Override
+            public Boolean get() {
+                value.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                    @Override
+                    public boolean enterFunctionNode(final FunctionNode functionNode) {
+                        return false;
+                    }
+
+                    @Override
+                    public boolean enterObjectNode(final ObjectNode objectNode) {
+                        return false;
+                    }
+
+                    @Override
+                    public boolean enterDefault(final Node node) {
+                        if (contains) {
+                            return false;
+                        }
+                        if (node instanceof Optimistic && ((Optimistic)node).getProgramPoint() == pp) {
+                            contains = true;
+                            return false;
+                        }
+                        return true;
+                    }
+                });
+
+                return contains;
+            }
+        }.get();
     }
 
-    private boolean enterLiteralNode(final LiteralNode<?> literalNode, final Type type) {
-        assert literalNode.getSymbol() != null : literalNode + " has no symbol";
-        loadLiteral(literalNode, type).convert(type).store(literalNode.getSymbol());
-        return false;
-    }
-
-    @Override
-    public boolean enterObjectNode(final ObjectNode objectNode) {
+    private void loadObjectNode(final ObjectNode objectNode) {
         final List<PropertyNode> elements = objectNode.getElements();
 
-        final List<String>     keys    = new ArrayList<>();
-        final List<Symbol>     symbols = new ArrayList<>();
-        final List<Expression> values  = new ArrayList<>();
+        final List<MapTuple<Expression>> tuples = new ArrayList<>();
+        final List<PropertyNode> gettersSetters = new ArrayList<>();
+        final int ccp = getCurrentContinuationEntryPoint();
 
-        boolean hasGettersSetters = false;
         Expression protoNode = null;
+        boolean restOfProperty = false;
 
-        for (PropertyNode propertyNode: elements) {
-            final Expression   value        = propertyNode.getValue();
-            final String       key          = propertyNode.getKeyName();
-            final Symbol       symbol       = value == null ? null : propertyNode.getKey().getSymbol();
+        for (final PropertyNode propertyNode : elements) {
+            final Expression value = propertyNode.getValue();
+            final String key = propertyNode.getKeyName();
+            // Just use a pseudo-symbol. We just need something non null; use the name and zero flags.
+            final Symbol symbol = value == null ? null : new Symbol(key, 0);
 
             if (value == null) {
-                hasGettersSetters = true;
+                gettersSetters.add(propertyNode);
             } else if (propertyNode.getKey() instanceof IdentNode &&
                        key.equals(ScriptObject.PROTO_PROPERTY_NAME)) {
                 // ES6 draft compliant __proto__ inside object literal
@@ -1459,89 +2351,84 @@
                 continue;
             }
 
-            keys.add(key);
-            symbols.add(symbol);
-            values.add(value);
+            restOfProperty |=
+                value != null &&
+                isValid(ccp) &&
+                propertyValueContains(value, ccp);
+
+            //for literals, a value of null means object type, i.e. the value null or getter setter function
+            //(I think)
+            final Class<?> valueType = (OBJECT_FIELDS_ONLY || value == null || value.getType().isBoolean()) ? Object.class : value.getType().getTypeClass();
+            tuples.add(new MapTuple<Expression>(key, symbol, Type.typeFor(valueType), value) {
+                @Override
+                public Class<?> getValueType() {
+                    return type.getTypeClass();
+                }
+            });
         }
 
+        final ObjectCreator<?> oc;
         if (elements.size() > OBJECT_SPILL_THRESHOLD) {
-            new SpillObjectCreator(this, keys, symbols, values).makeObject(method);
+            oc = new SpillObjectCreator(this, tuples);
         } else {
-            new FieldObjectCreator<Expression>(this, keys, symbols, values) {
+            oc = new FieldObjectCreator<Expression>(this, tuples) {
                 @Override
-                protected void loadValue(final Expression node) {
-                    load(node);
-                }
+                protected void loadValue(final Expression node, final Type type) {
+                    loadExpressionAsType(node, type);
+                }};
+        }
+        oc.makeObject(method);
 
-                /**
-                 * Ensure that the properties start out as object types so that
-                 * we can do putfield initializations instead of dynamicSetIndex
-                 * which would be the case to determine initial property type
-                 * otherwise.
-                 *
-                 * Use case, it's very expensive to do a million var x = {a:obj, b:obj}
-                 * just to have to invalidate them immediately on initialization
-                 *
-                 * see NASHORN-594
-                 */
-                @Override
-                protected MapCreator newMapCreator(final Class<?> fieldObjectClass) {
-                    return new MapCreator(fieldObjectClass, keys, symbols) {
-                        @Override
-                        protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) {
-                            return super.getPropertyFlags(symbol, hasArguments) | Property.IS_ALWAYS_OBJECT;
-                        }
-                    };
-                }
-
-            }.makeObject(method);
+        //if this is a rest of method and our continuation point was found as one of the values
+        //in the properties above, we need to reset the map to oc.getMap() in the continuation
+        //handler
+        if (restOfProperty) {
+            final ContinuationInfo ci = getContinuationInfo();
+            // Can be set at most once for a single rest-of method
+            assert ci.getObjectLiteralMap() == null;
+            ci.setObjectLiteralMap(oc.getMap());
+            ci.setObjectLiteralStackDepth(method.getStackSize());
         }
 
         method.dup();
         if (protoNode != null) {
-            load(protoNode);
+            loadExpressionAsObject(protoNode);
             // take care of { __proto__: 34 } or some such!
             method.convert(Type.OBJECT);
             method.invoke(ScriptObject.SET_PROTO_FROM_LITERAL);
         } else {
-            globalObjectPrototype();
-            method.invoke(ScriptObject.SET_PROTO);
+            method.invoke(ScriptObject.SET_GLOBAL_OBJECT_PROTO);
         }
 
-        if (hasGettersSetters) {
-            for (final PropertyNode propertyNode : elements) {
-                final FunctionNode getter       = propertyNode.getGetter();
-                final FunctionNode setter       = propertyNode.getSetter();
+        for (final PropertyNode propertyNode : gettersSetters) {
+            final FunctionNode getter = propertyNode.getGetter();
+            final FunctionNode setter = propertyNode.getSetter();
 
-                if (getter == null && setter == null) {
-                    continue;
-                }
+            assert getter != null || setter != null;
 
-                method.dup().loadKey(propertyNode.getKey());
-
-                if (getter == null) {
-                    method.loadNull();
-                } else {
-                    getter.accept(this);
-                }
-
-                if (setter == null) {
-                    method.loadNull();
-                } else {
-                    setter.accept(this);
-                }
-
-                method.invoke(ScriptObject.SET_USER_ACCESSORS);
+            method.dup().loadKey(propertyNode.getKey());
+            if (getter == null) {
+                method.loadNull();
+            } else {
+                getter.accept(this);
             }
-        }
 
-        method.store(objectNode.getSymbol());
-        return false;
+            if (setter == null) {
+                method.loadNull();
+            } else {
+                setter.accept(this);
+            }
+
+            method.invoke(ScriptObject.SET_USER_ACCESSORS);
+        }
     }
 
     @Override
     public boolean enterReturnNode(final ReturnNode returnNode) {
-        lineNumber(returnNode);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(returnNode);
 
         method.registerReturn();
 
@@ -1549,7 +2436,7 @@
 
         final Expression expression = returnNode.getExpression();
         if (expression != null) {
-            load(expression);
+            loadExpressionUnbounded(expression);
         } else {
             method.loadUndefined(returnType);
         }
@@ -1559,11 +2446,83 @@
         return false;
     }
 
+    private boolean undefinedCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
+        final Request request = runtimeNode.getRequest();
+
+        if (!Request.isUndefinedCheck(request)) {
+            return false;
+        }
+
+        final Expression lhs = args.get(0);
+        final Expression rhs = args.get(1);
+
+        final Symbol lhsSymbol = lhs instanceof IdentNode ? ((IdentNode)lhs).getSymbol() : null;
+        final Symbol rhsSymbol = rhs instanceof IdentNode ? ((IdentNode)rhs).getSymbol() : null;
+        // One must be a "undefined" identifier, otherwise we can't get here
+        assert lhsSymbol != null || rhsSymbol != null;
+
+        final Symbol undefinedSymbol;
+        if (isUndefinedSymbol(lhsSymbol)) {
+            undefinedSymbol = lhsSymbol;
+        } else {
+            assert isUndefinedSymbol(rhsSymbol);
+            undefinedSymbol = rhsSymbol;
+        }
+
+        assert undefinedSymbol != null; //remove warning
+        if (!undefinedSymbol.isScope()) {
+            return false; //disallow undefined as local var or parameter
+        }
+
+        if (lhsSymbol == undefinedSymbol && lhs.getType().isPrimitive()) {
+            //we load the undefined first. never mind, because this will deoptimize anyway
+            return false;
+        }
+
+        if(isDeoptimizedExpression(lhs)) {
+            // This is actually related to "lhs.getType().isPrimitive()" above: any expression being deoptimized in
+            // the current chain of rest-of compilations used to have a type narrower than Object (so it was primitive).
+            // We must not perform undefined check specialization for them, as then we'd violate the basic rule of
+            // "Thou shalt not alter the stack shape between a deoptimized method and any of its (transitive) rest-ofs."
+            return false;
+        }
+
+        //make sure that undefined has not been overridden or scoped as a local var
+        //between us and global
+        if (!compiler.isGlobalSymbol(lc.getCurrentFunction(), "undefined")) {
+            return false;
+        }
+
+        final boolean isUndefinedCheck = request == Request.IS_UNDEFINED;
+        final Expression expr = undefinedSymbol == lhsSymbol ? rhs : lhs;
+        if (expr.getType().isPrimitive()) {
+            loadAndDiscard(expr); //throw away lhs, but it still needs to be evaluated for side effects, even if not in scope, as it can be optimistic
+            method.load(!isUndefinedCheck);
+        } else {
+            final Label checkTrue  = new Label("ud_check_true");
+            final Label end        = new Label("end");
+            loadExpressionAsObject(expr);
+            method.loadUndefined(Type.OBJECT);
+            method.if_acmpeq(checkTrue);
+            method.load(!isUndefinedCheck);
+            method._goto(end);
+            method.label(checkTrue);
+            method.load(isUndefinedCheck);
+            method.label(end);
+        }
+
+        return true;
+    }
+
+    private static boolean isUndefinedSymbol(final Symbol symbol) {
+        return symbol != null && "undefined".equals(symbol.getName());
+    }
+
     private static boolean isNullLiteral(final Node node) {
         return node instanceof LiteralNode<?> && ((LiteralNode<?>) node).isNull();
     }
 
-    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args, final String signature) {
+    private boolean nullCheck(final RuntimeNode runtimeNode, final List<Expression> args) {
         final Request request = runtimeNode.getRequest();
 
         if (!Request.isEQ(request) && !Request.isNE(request)) {
@@ -1581,185 +2540,171 @@
             rhs = tmp;
         }
 
-        // this is a null literal check, so if there is implicit coercion
-        // involved like {D}x=null, we will fail - this is very rare
-        if (isNullLiteral(rhs) && lhs.getType().isObject()) {
-            final Label trueLabel  = new Label("trueLabel");
-            final Label falseLabel = new Label("falseLabel");
-            final Label endLabel   = new Label("end");
-
-            load(lhs);
-            method.dup();
-            if (Request.isEQ(request)) {
-                method.ifnull(trueLabel);
-            } else if (Request.isNE(request)) {
-                method.ifnonnull(trueLabel);
-            } else {
-                assert false : "Invalid request " + request;
-            }
-
-            method.label(falseLabel);
-            load(rhs);
-            method.invokestatic(CompilerConstants.className(ScriptRuntime.class), request.toString(), signature);
-            method._goto(endLabel);
-
-            method.label(trueLabel);
-            // if NE (not strict) this can be "undefined != null" which is supposed to be false
-            if (request == Request.NE) {
-                method.loadUndefined(Type.OBJECT);
-                final Label isUndefined = new Label("isUndefined");
-                final Label afterUndefinedCheck = new Label("afterUndefinedCheck");
-                method.if_acmpeq(isUndefined);
-                // not undefined
-                method.load(true);
-                method._goto(afterUndefinedCheck);
-                method.label(isUndefined);
-                method.load(false);
-                method.label(afterUndefinedCheck);
-            } else {
-                method.pop();
-                method.load(true);
-            }
-            method.label(endLabel);
-            method.convert(runtimeNode.getType());
-            method.store(runtimeNode.getSymbol());
-
-            return true;
-        }
-
-        return false;
-    }
-
-    private boolean specializationCheck(final RuntimeNode.Request request, final Expression node, final List<Expression> args) {
-        if (!request.canSpecialize()) {
+        if (!isNullLiteral(rhs)) {
             return false;
         }
 
-        assert args.size() == 2;
-        final Type returnType = node.getType();
-
-        load(args.get(0));
-        load(args.get(1));
-
-        Request finalRequest = request;
-
-        //if the request is a comparison, i.e. one that can be reversed
-        //it keeps its semantic, but make sure that the object comes in
-        //last
-        final Request reverse = Request.reverse(request);
-        if (method.peekType().isObject() && reverse != null) { //rhs is object
-            if (!method.peekType(1).isObject()) { //lhs is not object
-                method.swap(); //prefer object as lhs
-                finalRequest = reverse;
-            }
+        if (!lhs.getType().isObject()) {
+            return false;
         }
 
-        method.dynamicRuntimeCall(
-                new SpecializedRuntimeNode(
-                    finalRequest,
-                    new Type[] {
-                        method.peekType(1),
-                        method.peekType()
-                    },
-                    returnType).getInitialName(),
-                returnType,
-                finalRequest);
+        if(isDeoptimizedExpression(lhs)) {
+            // This is actually related to "!lhs.getType().isObject()" above: any expression being deoptimized in
+            // the current chain of rest-of compilations used to have a type narrower than Object. We must not
+            // perform null check specialization for them, as then we'd no longer be loading aconst_null on stack
+            // and thus violate the basic rule of "Thou shalt not alter the stack shape between a deoptimized
+            // method and any of its (transitive) rest-ofs."
+            // NOTE also that if we had a representation for well-known constants (e.g. null, 0, 1, -1, etc.) in
+            // Label$Stack.localLoads then this wouldn't be an issue, as we would never (somewhat ridiculously)
+            // allocate a temporary local to hold the result of aconst_null before attempting an optimistic
+            // operation.
+            return false;
+        }
 
-        method.convert(node.getType());
-        method.store(node.getSymbol());
+        // this is a null literal check, so if there is implicit coercion
+        // involved like {D}x=null, we will fail - this is very rare
+        final Label trueLabel  = new Label("trueLabel");
+        final Label falseLabel = new Label("falseLabel");
+        final Label endLabel   = new Label("end");
+
+        loadExpressionUnbounded(lhs);    //lhs
+        final Label popLabel;
+        if (!Request.isStrict(request)) {
+            method.dup(); //lhs lhs
+            popLabel = new Label("pop");
+        } else {
+            popLabel = null;
+        }
+
+        if (Request.isEQ(request)) {
+            method.ifnull(!Request.isStrict(request) ? popLabel : trueLabel);
+            if (!Request.isStrict(request)) {
+                method.loadUndefined(Type.OBJECT);
+                method.if_acmpeq(trueLabel);
+            }
+            method.label(falseLabel);
+            method.load(false);
+            method._goto(endLabel);
+            if (!Request.isStrict(request)) {
+                method.label(popLabel);
+                method.pop();
+            }
+            method.label(trueLabel);
+            method.load(true);
+            method.label(endLabel);
+        } else if (Request.isNE(request)) {
+            method.ifnull(!Request.isStrict(request) ? popLabel : falseLabel);
+            if (!Request.isStrict(request)) {
+                method.loadUndefined(Type.OBJECT);
+                method.if_acmpeq(falseLabel);
+            }
+            method.label(trueLabel);
+            method.load(true);
+            method._goto(endLabel);
+            if (!Request.isStrict(request)) {
+                method.label(popLabel);
+                method.pop();
+            }
+            method.label(falseLabel);
+            method.load(false);
+            method.label(endLabel);
+        }
+
+        assert runtimeNode.getType().isBoolean();
+        method.convert(runtimeNode.getType());
 
         return true;
     }
 
-    private static boolean isReducible(final Request request) {
-        return Request.isComparison(request) || request == Request.ADD;
+    /**
+     * Was this expression or any of its subexpressions deoptimized in the current recompilation chain of rest-of methods?
+     * @param rootExpr the expression being tested
+     * @return true if the expression or any of its subexpressions was deoptimized in the current recompilation chain.
+     */
+    private boolean isDeoptimizedExpression(final Expression rootExpr) {
+        if(!isRestOf()) {
+            return false;
+        }
+        return new Supplier<Boolean>() {
+            boolean contains;
+            @Override
+            public Boolean get() {
+                rootExpr.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                    @Override
+                    public boolean enterFunctionNode(final FunctionNode functionNode) {
+                        return false;
+                    }
+                    @Override
+                    public boolean enterDefault(final Node node) {
+                        if(!contains && node instanceof Optimistic) {
+                            final int pp = ((Optimistic)node).getProgramPoint();
+                            contains = isValid(pp) && isContinuationEntryPoint(pp);
+                        }
+                        return !contains;
+                    }
+                });
+                return contains;
+            }
+        }.get();
     }
 
-    @Override
-    public boolean enterRuntimeNode(final RuntimeNode runtimeNode) {
-        /*
-         * First check if this should be something other than a runtime node
-         * AccessSpecializer might have changed the type
-         *
-         * TODO - remove this - Access Specializer will always know after Attr/Lower
-         */
-        final List<Expression> args = runtimeNode.getArgs();
-        if (runtimeNode.isPrimitive() && !runtimeNode.isFinal() && isReducible(runtimeNode.getRequest())) {
-            final Expression lhs = args.get(0);
-            assert args.size() > 1 : runtimeNode + " must have two args";
-            final Expression rhs = args.get(1);
+    private void loadRuntimeNode(final RuntimeNode runtimeNode) {
+        final List<Expression> args = new ArrayList<>(runtimeNode.getArgs());
+        if (nullCheck(runtimeNode, args)) {
+           return;
+        } else if(undefinedCheck(runtimeNode, args)) {
+            return;
+        }
+        // Revert a false undefined check to a strict equality check
+        final RuntimeNode newRuntimeNode;
+        final Request request = runtimeNode.getRequest();
+        if (Request.isUndefinedCheck(request)) {
+            newRuntimeNode = runtimeNode.setRequest(request == Request.IS_UNDEFINED ? Request.EQ_STRICT : Request.NE_STRICT);
+        } else {
+            newRuntimeNode = runtimeNode;
+        }
 
-            final Type   type   = runtimeNode.getType();
-            final Symbol symbol = runtimeNode.getSymbol();
-
-            switch (runtimeNode.getRequest()) {
-            case EQ:
-            case EQ_STRICT:
-                return enterCmp(lhs, rhs, Condition.EQ, type, symbol);
-            case NE:
-            case NE_STRICT:
-                return enterCmp(lhs, rhs, Condition.NE, type, symbol);
-            case LE:
-                return enterCmp(lhs, rhs, Condition.LE, type, symbol);
-            case LT:
-                return enterCmp(lhs, rhs, Condition.LT, type, symbol);
-            case GE:
-                return enterCmp(lhs, rhs, Condition.GE, type, symbol);
-            case GT:
-                return enterCmp(lhs, rhs, Condition.GT, type, symbol);
-            case ADD:
-                Type widest = Type.widest(lhs.getType(), rhs.getType());
-                load(lhs, widest);
-                load(rhs, widest);
-                method.add();
-                method.convert(type);
-                method.store(symbol);
-                return false;
-            default:
-                // it's ok to send this one on with only primitive arguments, maybe INSTANCEOF(true, true) or similar
-                // assert false : runtimeNode + " has all primitive arguments. This is an inconsistent state";
-                break;
+        new OptimisticOperation(newRuntimeNode, TypeBounds.UNBOUNDED) {
+            @Override
+            void loadStack() {
+                for (final Expression arg : args) {
+                    loadExpression(arg, TypeBounds.OBJECT);
+                }
             }
-        }
+            @Override
+            void consumeStack() {
+                method.invokestatic(
+                        CompilerConstants.className(ScriptRuntime.class),
+                        newRuntimeNode.getRequest().toString(),
+                        new FunctionSignature(
+                            false,
+                            false,
+                            newRuntimeNode.getType(),
+                            args.size()).toString());
+            }
+        }.emit();
 
-        if (nullCheck(runtimeNode, args, new FunctionSignature(false, false, runtimeNode.getType(), args).toString())) {
-           return false;
-        }
-
-        if (!runtimeNode.isFinal() && specializationCheck(runtimeNode.getRequest(), runtimeNode, args)) {
-           return false;
-        }
-
-        for (final Expression arg : args) {
-            load(arg, Type.OBJECT);
-        }
-
-        method.invokestatic(
-            CompilerConstants.className(ScriptRuntime.class),
-            runtimeNode.getRequest().toString(),
-            new FunctionSignature(
-                false,
-                false,
-                runtimeNode.getType(),
-                args.size()).toString());
-        method.convert(runtimeNode.getType());
-        method.store(runtimeNode.getSymbol());
-
-        return false;
+        method.convert(newRuntimeNode.getType());
     }
 
     @Override
     public boolean enterSplitNode(final SplitNode splitNode) {
+        if(!method.isReachable()) {
+            return false;
+        }
+
         final CompileUnit splitCompileUnit = splitNode.getCompileUnit();
 
         final FunctionNode fn   = lc.getCurrentFunction();
         final String className  = splitCompileUnit.getUnitClassName();
         final String name       = splitNode.getName();
 
+        final Type returnType = fn.getReturnType();
+
         final Class<?>   rtype          = fn.getReturnType().getTypeClass();
         final boolean    needsArguments = fn.needsArguments();
         final Class<?>[] ptypes         = needsArguments ?
-                new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class, Object.class} :
+                new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class, ScriptObject.class} :
                 new Class<?>[] {ScriptFunction.class, Object.class, ScriptObject.class};
 
         final MethodEmitter caller = method;
@@ -1777,7 +2722,7 @@
                         rtype,
                         ptypes);
 
-        method = lc.pushMethodEmitter(splitEmitter);
+        pushMethodEmitter(splitEmitter);
         method.setFunctionNode(fn);
 
         assert fn.needsCallee() : "split function should require callee";
@@ -1788,22 +2733,49 @@
             caller.loadCompilerConstant(ARGUMENTS);
         }
         caller.invoke(splitCall);
-        caller.storeCompilerConstant(RETURN);
+        caller.storeCompilerConstant(RETURN, returnType);
 
         method.begin();
+
+        defineCommonSplitMethodParameters();
+        if(needsArguments) {
+            defineSplitMethodParameter(3, ARGUMENTS);
+        }
+
         // Copy scope to its target slot as first thing because the original slot could be used by return symbol.
         fixScopeSlot(fn);
 
-        method.loadUndefined(fn.getReturnType());
-        method.storeCompilerConstant(RETURN);
+        final int returnSlot = fn.compilerConstant(RETURN).getSlot(returnType);
+        method.defineBlockLocalVariable(returnSlot, returnSlot + returnType.getSlots());
+        method.loadUndefined(returnType);
+        method.storeCompilerConstant(RETURN, returnType);
 
+        lc.enterSplitNode();
         return true;
     }
 
+    private void defineCommonSplitMethodParameters() {
+        defineSplitMethodParameter(0, CALLEE);
+        defineSplitMethodParameter(1, THIS);
+        defineSplitMethodParameter(2, SCOPE);
+    }
+
+    private void defineSplitMethodParameter(final int slot, final CompilerConstants cc) {
+        defineSplitMethodParameter(slot, Type.typeFor(cc.type()));
+    }
+
+    private void defineSplitMethodParameter(final int slot, final Type type) {
+        method.defineBlockLocalVariable(slot, slot + type.getSlots());
+        method.onLocalStore(type, slot);
+    }
+
     private void fixScopeSlot(final FunctionNode functionNode) {
         // TODO hack to move the scope to the expected slot (needed because split methods reuse the same slots as the root method)
-        if (functionNode.compilerConstant(SCOPE).getSlot() != SCOPE.slot()) {
-            method.load(Type.typeFor(ScriptObject.class), SCOPE.slot());
+        final int actualScopeSlot = functionNode.compilerConstant(SCOPE).getSlot(SCOPE_TYPE);
+        final int defaultScopeSlot = SCOPE.slot();
+        if (actualScopeSlot != defaultScopeSlot) {
+            method.defineBlockLocalVariable(actualScopeSlot, actualScopeSlot + 1);
+            method.load(SCOPE_TYPE, defaultScopeSlot);
             method.storeCompilerConstant(SCOPE);
         }
     }
@@ -1811,22 +2783,30 @@
     @Override
     public Node leaveSplitNode(final SplitNode splitNode) {
         assert method instanceof SplitMethodEmitter;
-        final boolean     hasReturn = method.hasReturn();
-        final List<Label> targets   = method.getExternalTargets();
+        lc.exitSplitNode();
+        final boolean hasReturn = method.hasReturn();
+        final SplitMethodEmitter splitMethod = ((SplitMethodEmitter)method);
+        final List<Label> targets = splitMethod.getExternalTargets();
+        final List<BreakableNode> targetNodes  = splitMethod.getExternalTargetNodes();
+        final Type returnType = lc.getCurrentFunction().getReturnType();
 
         try {
             // Wrap up this method.
 
-            method.loadCompilerConstant(RETURN);
-            method._return(lc.getCurrentFunction().getReturnType());
+            if(method.isReachable()) {
+                method.loadCompilerConstant(RETURN, returnType);
+                method._return(returnType);
+            }
             method.end();
 
+            lc.releaseSlots();
+
             unit   = lc.popCompileUnit(splitNode.getCompileUnit());
-            method = lc.popMethodEmitter(method);
+            popMethodEmitter();
 
         } catch (final Throwable t) {
             Context.printStackTrace(t);
-            final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + lc.getCurrentFunction().getSource().getName());
+            final VerifyError e = new VerifyError("Code generation bug in \"" + splitNode.getName() + "\": likely stack misaligned: " + t + " " + getCurrentSource().getName());
             e.initCause(t);
             throw e;
         }
@@ -1853,8 +2833,8 @@
             caller.ifne(breakLabel);
             //has to be zero
             caller.label(new Label("split_return"));
-            caller.loadCompilerConstant(RETURN);
-            caller._return(lc.getCurrentFunction().getReturnType());
+            caller.loadCompilerConstant(RETURN, returnType);
+            caller._return(returnType);
             caller.label(breakLabel);
         } else {
             assert !targets.isEmpty();
@@ -1870,15 +2850,22 @@
             for (int i = low; i <= targetCount; i++) {
                 caller.label(labels[i - low]);
                 if (i == 0) {
-                    caller.loadCompilerConstant(RETURN);
-                    caller._return(lc.getCurrentFunction().getReturnType());
+                    caller.loadCompilerConstant(RETURN, returnType);
+                    caller._return(returnType);
                 } else {
                     // Clear split state.
                     caller.loadCompilerConstant(SCOPE);
                     caller.checkcast(Scope.class);
                     caller.load(-1);
                     caller.invoke(Scope.SET_SPLIT_STATE);
-                    caller.splitAwareGoto(lc, targets.get(i - 1));
+                    final BreakableNode targetNode = targetNodes.get(i - 1);
+                    final Label label = targets.get(i - 1);
+                    final JoinPredecessor jumpOrigin = splitNode.getJumpOrigin(label);
+                    if(jumpOrigin != null) {
+                        method.beforeJoinPoint(jumpOrigin);
+                    }
+                    popScopesUntil(targetNode);
+                    caller.splitAwareGoto(lc, targets.get(i - 1), targetNode);
                 }
             }
             caller.label(breakLabel);
@@ -1894,31 +2881,39 @@
 
     @Override
     public boolean enterSwitchNode(final SwitchNode switchNode) {
-        lineNumber(switchNode);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(switchNode);
 
         final Expression     expression  = switchNode.getExpression();
-        final Symbol         tag         = switchNode.getTag();
-        final boolean        allInteger  = tag.getSymbolType().isInteger();
         final List<CaseNode> cases       = switchNode.getCases();
-        final CaseNode       defaultCase = switchNode.getDefaultCase();
-        final Label          breakLabel  = switchNode.getBreakLabel();
-
-        Label defaultLabel = breakLabel;
-        boolean hasDefault = false;
-
-        if (defaultCase != null) {
-            defaultLabel = defaultCase.getEntry();
-            hasDefault = true;
-        }
 
         if (cases.isEmpty()) {
             // still evaluate expression for side-effects.
-            load(expression).pop();
-            method.label(breakLabel);
+            loadAndDiscard(expression);
             return false;
         }
 
-        if (allInteger) {
+        final CaseNode defaultCase       = switchNode.getDefaultCase();
+        final Label    breakLabel        = switchNode.getBreakLabel();
+        final int      liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
+
+        if (defaultCase != null && cases.size() == 1) {
+            // default case only
+            assert cases.get(0) == defaultCase;
+            loadAndDiscard(expression);
+            defaultCase.getBody().accept(this);
+            method.breakLabel(breakLabel, liveLocalsOnBreak);
+            return false;
+        }
+
+        // NOTE: it can still change in the tableswitch/lookupswitch case if there's no default case
+        // but we need to add a synthetic default case for local variable conversions
+        Label defaultLabel = defaultCase != null ? defaultCase.getEntry() : breakLabel;
+        final boolean hasSkipConversion = LocalVariableConversion.hasLiveConversion(switchNode);
+
+        if (switchNode.isInteger()) {
             // Tree for sorting values.
             final TreeMap<Integer, Label> tree = new TreeMap<>();
 
@@ -1931,7 +2926,7 @@
                     final Label   entry = caseNode.getEntry();
 
                     // Take first duplicate.
-                    if (!(tree.containsKey(value))) {
+                    if (!tree.containsKey(value)) {
                         tree.put(value, entry);
                     }
                 }
@@ -1945,7 +2940,7 @@
             // Discern low, high and range.
             final int lo    = values[0];
             final int hi    = values[size - 1];
-            final int range = hi - lo + 1;
+            final long range = (long)hi - (long)lo + 1;
 
             // Find an unused value for default.
             int deflt = Integer.MIN_VALUE;
@@ -1958,7 +2953,7 @@
             }
 
             // Load switch expression.
-            load(expression);
+            loadExpressionUnbounded(expression);
             final Type type = expression.getType();
 
             // If expression not int see if we can convert, if not use deflt to trigger default.
@@ -1968,11 +2963,15 @@
                 method.invoke(staticCallNoLookup(ScriptRuntime.class, "switchTagAsInt", int.class, exprClass.isPrimitive()? exprClass : Object.class, int.class));
             }
 
-            // If reasonable size and not too sparse (80%), use table otherwise use lookup.
-            if (range > 0 && range < 4096 && range < (size * 5 / 4)) {
-                final Label[] table = new Label[range];
+            if(hasSkipConversion) {
+                assert defaultLabel == breakLabel;
+                defaultLabel = new Label("switch_skip");
+            }
+            // TABLESWITCH needs (range + 3) 32-bit values; LOOKUPSWITCH needs ((size * 2) + 2). Choose the one with
+            // smaller representation, favor TABLESWITCH when they're equal size.
+            if (range + 1 <= (size * 2) && range <= Integer.MAX_VALUE) {
+                final Label[] table = new Label[(int)range];
                 Arrays.fill(table, defaultLabel);
-
                 for (int i = 0; i < size; i++) {
                     final int value = values[i];
                     table[value - lo] = labels[i];
@@ -1987,97 +2986,163 @@
 
                 method.lookupswitch(defaultLabel, ints, labels);
             }
+            // This is a synthetic "default case" used in absence of actual default case, created if we need to apply
+            // local variable conversions if neither case is taken.
+            if(hasSkipConversion) {
+                method.label(defaultLabel);
+                method.beforeJoinPoint(switchNode);
+                method._goto(breakLabel);
+            }
         } else {
-            load(expression, Type.OBJECT);
-            method.store(tag);
+            final Symbol tagSymbol = switchNode.getTag();
+            // TODO: we could have non-object tag
+            final int tagSlot = tagSymbol.getSlot(Type.OBJECT);
+            loadExpressionAsObject(expression);
+            method.store(tagSymbol, Type.OBJECT);
 
             for (final CaseNode caseNode : cases) {
                 final Expression test = caseNode.getTest();
 
                 if (test != null) {
-                    method.load(tag);
-                    load(test, Type.OBJECT);
+                    method.load(Type.OBJECT, tagSlot);
+                    loadExpressionAsObject(test);
                     method.invoke(ScriptRuntime.EQ_STRICT);
                     method.ifne(caseNode.getEntry());
                 }
             }
 
-            method._goto(hasDefault ? defaultLabel : breakLabel);
+            if (defaultCase != null) {
+                method._goto(defaultLabel);
+            } else {
+                method.beforeJoinPoint(switchNode);
+                method._goto(breakLabel);
+            }
         }
 
+        // First case is only reachable through jump
+        assert !method.isReachable();
+
         for (final CaseNode caseNode : cases) {
+            final Label fallThroughLabel;
+            if(caseNode.getLocalVariableConversion() != null && method.isReachable()) {
+                fallThroughLabel = new Label("fallthrough");
+                method._goto(fallThroughLabel);
+            } else {
+                fallThroughLabel = null;
+            }
             method.label(caseNode.getEntry());
+            method.beforeJoinPoint(caseNode);
+            if(fallThroughLabel != null) {
+                method.label(fallThroughLabel);
+            }
             caseNode.getBody().accept(this);
         }
 
-        if (!switchNode.isTerminal()) {
-            method.label(breakLabel);
-        }
+        method.breakLabel(breakLabel, liveLocalsOnBreak);
 
         return false;
     }
 
     @Override
     public boolean enterThrowNode(final ThrowNode throwNode) {
-        lineNumber(throwNode);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(throwNode);
 
         if (throwNode.isSyntheticRethrow()) {
+            method.beforeJoinPoint(throwNode);
+
             //do not wrap whatever this is in an ecma exception, just rethrow it
-            load(throwNode.getExpression());
+            final IdentNode exceptionExpr = (IdentNode)throwNode.getExpression();
+            final Symbol exceptionSymbol = exceptionExpr.getSymbol();
+            method.load(exceptionSymbol, EXCEPTION_TYPE);
+            method.checkcast(EXCEPTION_TYPE.getTypeClass());
             method.athrow();
             return false;
         }
 
-        final Source source     = lc.getCurrentFunction().getSource();
-
+        final Source     source     = getCurrentSource();
         final Expression expression = throwNode.getExpression();
         final int        position   = throwNode.position();
         final int        line       = throwNode.getLineNumber();
         final int        column     = source.getColumn(position);
 
-        load(expression, Type.OBJECT);
+        // NOTE: we first evaluate the expression, and only after it was evaluated do we create the new ECMAException
+        // object and then somewhat cumbersomely move it beneath the evaluated expression on the stack. The reason for
+        // this is that if expression is optimistic (or contains an optimistic subexpression), we'd potentially access
+        // the not-yet-<init>ialized object on the stack from the UnwarrantedOptimismException handler, and bytecode
+        // verifier forbids that.
+        loadExpressionAsObject(expression);
 
         method.load(source.getName());
         method.load(line);
         method.load(column);
         method.invoke(ECMAException.CREATE);
 
+        method.beforeJoinPoint(throwNode);
         method.athrow();
 
         return false;
     }
 
+    private Source getCurrentSource() {
+        return lc.getCurrentFunction().getSource();
+    }
+
     @Override
     public boolean enterTryNode(final TryNode tryNode) {
-        lineNumber(tryNode);
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(tryNode);
 
         final Block       body        = tryNode.getBody();
         final List<Block> catchBlocks = tryNode.getCatchBlocks();
-        final Symbol      symbol      = tryNode.getException();
+        final Symbol      vmException = tryNode.getException();
         final Label       entry       = new Label("try");
         final Label       recovery    = new Label("catch");
-        final Label       exit        = tryNode.getExit();
+        final Label       exit        = new Label("end_try");
         final Label       skip        = new Label("skip");
 
+        method.canThrow(recovery);
+        // Effect any conversions that might be observed at the entry of the catch node before entering the try node.
+        // This is because even the first instruction in the try block must be presumed to be able to transfer control
+        // to the catch block. Note that this doesn't kill the original values; in this regard it works a lot like
+        // conversions of assignments within the try block.
+        method.beforeTry(tryNode, recovery);
         method.label(entry);
-
-        body.accept(this);
-
-        if (!body.hasTerminalFlags()) {
-            method._goto(skip);
+        catchLabels.push(recovery);
+        try {
+            body.accept(this);
+        } finally {
+            assert catchLabels.peek() == recovery;
+            catchLabels.pop();
         }
 
         method.label(exit);
+        final boolean bodyCanThrow = exit.isAfter(entry);
+        if(!bodyCanThrow) {
+            // The body can't throw an exception; don't even bother emitting the catch handlers, they're all dead code.
+            return false;
+        }
 
+        method._try(entry, exit, recovery, Throwable.class);
+
+        if (method.isReachable()) {
+            method._goto(skip);
+        }
         method._catch(recovery);
-        method.store(symbol);
+        method.store(vmException, EXCEPTION_TYPE);
 
-        for (int i = 0; i < catchBlocks.size(); i++) {
+        final int catchBlockCount = catchBlocks.size();
+        final Label afterCatch = new Label("after_catch");
+        for (int i = 0; i < catchBlockCount; i++) {
+            assert method.isReachable();
             final Block catchBlock = catchBlocks.get(i);
 
-            //TODO this is very ugly - try not to call enter/leave methods directly
-            //better to use the implicit lexical context scoping given by the visitor's
-            //accept method.
+            // Because of the peculiarities of the flow control, we need to use an explicit push/enterBlock/leaveBlock
+            // here.
             lc.push(catchBlock);
             enterBlock(catchBlock);
 
@@ -2089,13 +3154,14 @@
             new Store<IdentNode>(exception) {
                 @Override
                 protected void storeNonDiscard() {
-                    return;
+                    // This expression is neither part of a discard, nor needs to be left on the stack after it was
+                    // stored, so we override storeNonDiscard to be a no-op.
                 }
 
                 @Override
                 protected void evaluate() {
                     if (catchNode.isSyntheticRethrow()) {
-                        method.load(symbol);
+                        method.load(vmException, EXCEPTION_TYPE);
                         return;
                     }
                     /*
@@ -2104,61 +3170,58 @@
                      * caught object itself to the script catch var.
                      */
                     final Label notEcmaException = new Label("no_ecma_exception");
-                    method.load(symbol).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
+                    method.load(vmException, EXCEPTION_TYPE).dup()._instanceof(ECMAException.class).ifeq(notEcmaException);
                     method.checkcast(ECMAException.class); //TODO is this necessary?
                     method.getField(ECMAException.THROWN);
                     method.label(notEcmaException);
                 }
             }.store();
 
-            final Label next;
-
-            if (exceptionCondition != null) {
-                next = new Label("next");
-                load(exceptionCondition, Type.BOOLEAN).ifeq(next);
+            final boolean isConditionalCatch = exceptionCondition != null;
+            final Label nextCatch;
+            if (isConditionalCatch) {
+                loadExpressionAsBoolean(exceptionCondition);
+                nextCatch = new Label("next_catch");
+                method.ifeq(nextCatch);
             } else {
-                next = null;
+                nextCatch = null;
             }
 
             catchBody.accept(this);
-
-            if (i + 1 != catchBlocks.size() && !catchBody.hasTerminalFlags()) {
-                method._goto(skip);
-            }
-
-            if (next != null) {
-                if (i + 1 == catchBlocks.size()) {
-                    // no next catch block - rethrow if condition failed
-                    method._goto(skip);
-                    method.label(next);
-                    method.load(symbol).athrow();
-                } else {
-                    method.label(next);
-                }
-            }
-
             leaveBlock(catchBlock);
             lc.pop(catchBlock);
+            if(method.isReachable()) {
+                method._goto(afterCatch);
+            }
+            if(nextCatch != null) {
+                method.label(nextCatch);
+            }
         }
 
+        assert !method.isReachable();
+        // afterCatch could be the same as skip, except that we need to establish that the vmException is dead.
+        method.label(afterCatch);
+        if(method.isReachable()) {
+            method.markDeadLocalVariable(vmException);
+        }
         method.label(skip);
-        method._try(entry, exit, recovery, Throwable.class);
 
         // Finally body is always inlined elsewhere so it doesn't need to be emitted
-
         return false;
     }
 
     @Override
     public boolean enterVarNode(final VarNode varNode) {
-
+        if(!method.isReachable()) {
+            return false;
+        }
         final Expression init = varNode.getInit();
 
         if (init == null) {
             return false;
         }
 
-        lineNumber(varNode);
+        enterStatement(varNode);
 
         final IdentNode identNode = varNode.getName();
         final Symbol identSymbol = identNode.getSymbol();
@@ -2172,58 +3235,195 @@
         }
 
         if (needsScope) {
-            load(init);
-            int flags = CALLSITE_SCOPE | getCallSiteFlags();
+            loadExpressionUnbounded(init);
+            final int flags = CALLSITE_SCOPE | getCallSiteFlags();
             if (isFastScope(identSymbol)) {
                 storeFastScopeVar(identSymbol, flags);
             } else {
                 method.dynamicSet(identNode.getName(), flags);
             }
         } else {
-            load(init, identNode.getType());
-            method.store(identSymbol);
+            final Type identType = identNode.getType();
+            if(identType == Type.UNDEFINED) {
+                // The symbol must not be slotted; the initializer is either itself undefined (explicit assignment of
+                // undefined to undefined), or the left hand side is a dead variable.
+                assert !identNode.getSymbol().isScope();
+                assert init.getType() == Type.UNDEFINED || identNode.getSymbol().slotCount() == 0;
+                loadAndDiscard(init);
+                return false;
+            }
+            loadExpressionAsType(init, identType);
+            storeIdentWithCatchConversion(identNode, identType);
         }
 
         return false;
     }
 
+    private void storeIdentWithCatchConversion(final IdentNode identNode, final Type type) {
+        // Assignments happening in try/catch blocks need to ensure that they also store a possibly wider typed value
+        // that will be live at the exit from the try block
+        final LocalVariableConversion conversion = identNode.getLocalVariableConversion();
+        final Symbol symbol = identNode.getSymbol();
+        if(conversion != null && conversion.isLive()) {
+            assert symbol == conversion.getSymbol();
+            assert symbol.isBytecodeLocal();
+            // Only a single conversion from the target type to the join type is expected.
+            assert conversion.getNext() == null;
+            assert conversion.getFrom() == type;
+            // We must propagate potential type change to the catch block
+            final Label catchLabel = catchLabels.peek();
+            assert catchLabel != METHOD_BOUNDARY; // ident conversion only exists in try blocks
+            assert catchLabel.isReachable();
+            final Type joinType = conversion.getTo();
+            final Label.Stack catchStack = catchLabel.getStack();
+            final int joinSlot = symbol.getSlot(joinType);
+            // With nested try/catch blocks (incl. synthetic ones for finally), we can have a supposed conversion for
+            // the exception symbol in the nested catch, but it isn't live in the outer catch block, so prevent doing
+            // conversions for it. E.g. in "try { try { ... } catch(e) { e = 1; } } catch(e2) { ... }", we must not
+            // introduce an I->O conversion on "e = 1" assignment as "e" is not live in "catch(e2)".
+            if(catchStack.getUsedSlotsWithLiveTemporaries() > joinSlot) {
+                method.dup();
+                method.convert(joinType);
+                method.store(symbol, joinType);
+                catchLabel.getStack().onLocalStore(joinType, joinSlot, true);
+                method.canThrow(catchLabel);
+                // Store but keep the previous store live too.
+                method.store(symbol, type, false);
+                return;
+            }
+        }
+
+        method.store(symbol, type, true);
+    }
+
     @Override
     public boolean enterWhileNode(final WhileNode whileNode) {
-        final Expression test          = whileNode.getTest();
-        final Block      body          = whileNode.getBody();
-        final Label      breakLabel    = whileNode.getBreakLabel();
-        final Label      continueLabel = whileNode.getContinueLabel();
-        final boolean    isDoWhile     = whileNode.isDoWhile();
-        final Label      loopLabel     = new Label("loop");
-
-        if (!isDoWhile) {
-            method._goto(continueLabel);
+        if(!method.isReachable()) {
+            return false;
         }
-
-        method.label(loopLabel);
-        body.accept(this);
-        if (!whileNode.isTerminal()) {
-            method.label(continueLabel);
-            lineNumber(whileNode);
-            new BranchOptimizer(this, method).execute(test, loopLabel, true);
-            method.label(breakLabel);
+        if(whileNode.isDoWhile()) {
+            enterDoWhile(whileNode);
+        } else {
+            enterStatement(whileNode);
+            enterForOrWhile(whileNode, null);
         }
-
         return false;
     }
 
-    private void closeWith() {
-        if (method.hasScope()) {
-            method.loadCompilerConstant(SCOPE);
-            method.invoke(ScriptRuntime.CLOSE_WITH);
-            method.storeCompilerConstant(SCOPE);
+    private void enterForOrWhile(final LoopNode loopNode, final JoinPredecessorExpression modify) {
+        // NOTE: the usual pattern for compiling test-first loops is "GOTO test; body; test; IFNE body". We use the less
+        // conventional "test; IFEQ break; body; GOTO test; break;". It has one extra unconditional GOTO in each repeat
+        // of the loop, but it's not a problem for modern JIT compilers. We do this because our local variable type
+        // tracking is unfortunately not really prepared for out-of-order execution, e.g. compiling the following
+        // contrived but legal JavaScript code snippet would fail because the test changes the type of "i" from object
+        // to double: var i = {valueOf: function() { return 1} }; while(--i >= 0) { ... }
+        // Instead of adding more complexity to the local variable type tracking, we instead choose to emit this
+        // different code shape.
+        final int liveLocalsOnBreak = method.getUsedSlotsWithLiveTemporaries();
+        final JoinPredecessorExpression test = loopNode.getTest();
+        if(Expression.isAlwaysFalse(test)) {
+            loadAndDiscard(test);
+            return;
+        }
+
+        method.beforeJoinPoint(loopNode);
+
+        final Label continueLabel = loopNode.getContinueLabel();
+        final Label repeatLabel = modify != null ? new Label("for_repeat") : continueLabel;
+        method.label(repeatLabel);
+        final int liveLocalsOnContinue = method.getUsedSlotsWithLiveTemporaries();
+
+        final Block   body                  = loopNode.getBody();
+        final Label   breakLabel            = loopNode.getBreakLabel();
+        final boolean testHasLiveConversion = test != null && LocalVariableConversion.hasLiveConversion(test);
+
+        if(Expression.isAlwaysTrue(test)) {
+            if(test != null) {
+                loadAndDiscard(test);
+                if(testHasLiveConversion) {
+                    method.beforeJoinPoint(test);
+                }
+            }
+        } else if (test != null) {
+            if (testHasLiveConversion) {
+                emitBranch(test.getExpression(), body.getEntryLabel(), true);
+                method.beforeJoinPoint(test);
+                method._goto(breakLabel);
+            } else {
+                emitBranch(test.getExpression(), breakLabel, false);
+            }
+        }
+
+        body.accept(this);
+        if(repeatLabel != continueLabel) {
+            emitContinueLabel(continueLabel, liveLocalsOnContinue);
+        }
+
+        if(method.isReachable()) {
+            if(modify != null) {
+                lineNumber(loopNode);
+                loadAndDiscard(modify);
+                method.beforeJoinPoint(modify);
+            }
+            method._goto(repeatLabel);
+        }
+
+        method.breakLabel(breakLabel, liveLocalsOnBreak);
+    }
+
+    private void emitContinueLabel(final Label continueLabel, final int liveLocals) {
+        final boolean reachable = method.isReachable();
+        method.breakLabel(continueLabel, liveLocals);
+        // If we reach here only through a continue statement (e.g. body does not exit normally) then the
+        // continueLabel can have extra non-temp symbols (e.g. exception from a try/catch contained in the body). We
+        // must make sure those are thrown away.
+        if(!reachable) {
+            method.undefineLocalVariables(lc.getUsedSlotCount(), false);
         }
     }
 
+    private void enterDoWhile(final WhileNode whileNode) {
+        final int liveLocalsOnContinueOrBreak = method.getUsedSlotsWithLiveTemporaries();
+        method.beforeJoinPoint(whileNode);
+
+        final Block body = whileNode.getBody();
+        body.accept(this);
+
+        emitContinueLabel(whileNode.getContinueLabel(), liveLocalsOnContinueOrBreak);
+        if(method.isReachable()) {
+            lineNumber(whileNode);
+            final JoinPredecessorExpression test = whileNode.getTest();
+            final Label bodyEntryLabel = body.getEntryLabel();
+            final boolean testHasLiveConversion = LocalVariableConversion.hasLiveConversion(test);
+            if(Expression.isAlwaysFalse(test)) {
+                loadAndDiscard(test);
+                if(testHasLiveConversion) {
+                    method.beforeJoinPoint(test);
+                }
+            } else if(testHasLiveConversion) {
+                // If we have conversions after the test in do-while, they need to be effected on both branches.
+                final Label beforeExit = new Label("do_while_preexit");
+                emitBranch(test.getExpression(), beforeExit, false);
+                method.beforeJoinPoint(test);
+                method._goto(bodyEntryLabel);
+                method.label(beforeExit);
+                method.beforeJoinPoint(test);
+            } else {
+                emitBranch(test.getExpression(), bodyEntryLabel, true);
+            }
+        }
+        method.breakLabel(whileNode.getBreakLabel(), liveLocalsOnContinueOrBreak);
+    }
+
+
     @Override
     public boolean enterWithNode(final WithNode withNode) {
+        if(!method.isReachable()) {
+            return false;
+        }
+        enterStatement(withNode);
         final Expression expression = withNode.getExpression();
-        final Node       body       = withNode.getBody();
+        final Block      body       = withNode.getBody();
 
         // It is possible to have a "pathological" case where the with block does not reference *any* identifiers. It's
         // pointless, but legal. In that case, if nothing else in the method forced the assignment of a slot to the
@@ -2231,28 +3431,26 @@
         // for its side effect and visit the body, and not bother opening and closing a WithObject.
         final boolean hasScope = method.hasScope();
 
-        final Label tryLabel;
         if (hasScope) {
-            tryLabel = new Label("with_try");
-            method.label(tryLabel);
             method.loadCompilerConstant(SCOPE);
-        } else {
-            tryLabel = null;
         }
 
-        load(expression, Type.OBJECT);
+        loadExpressionAsObject(expression);
 
+        final Label tryLabel;
         if (hasScope) {
             // Construct a WithObject if we have a scope
             method.invoke(ScriptRuntime.OPEN_WITH);
             method.storeCompilerConstant(SCOPE);
+            tryLabel = new Label("with_try");
+            method.label(tryLabel);
         } else {
             // We just loaded the expression for its side effect and to check
             // for null or undefined value.
             globalCheckObjectCoercible();
+            tryLabel = null;
         }
 
-
         // Always process body
         body.accept(this);
 
@@ -2262,62 +3460,78 @@
             final Label catchLabel = new Label("with_catch");
             final Label exitLabel  = new Label("with_exit");
 
-            if (!body.isTerminal()) {
-                closeWith();
-                method._goto(exitLabel);
+            method.label(endLabel);
+            // Somewhat conservatively presume that if the body is not empty, it can throw an exception. In any case,
+            // we must prevent trying to emit a try-catch for empty range, as it causes a verification error.
+            final boolean bodyCanThrow = endLabel.isAfter(tryLabel);
+            if(bodyCanThrow) {
+                method._try(tryLabel, endLabel, catchLabel);
             }
 
-            method.label(endLabel);
+            final boolean reachable = method.isReachable();
+            if(reachable) {
+                popScope();
+                if(bodyCanThrow) {
+                    method._goto(exitLabel);
+                }
+            }
 
-            method._catch(catchLabel);
-            closeWith();
-            method.athrow();
-
-            method.label(exitLabel);
-
-            method._try(tryLabel, endLabel, catchLabel);
+            if(bodyCanThrow) {
+                method._catch(catchLabel);
+                popScopeException();
+                method.athrow();
+                if(reachable) {
+                    method.label(exitLabel);
+                }
+            }
         }
         return false;
     }
 
-    @Override
-    public boolean enterADD(final UnaryNode unaryNode) {
-        load(unaryNode.rhs(), unaryNode.getType());
-        assert unaryNode.getType().isNumeric();
-        method.store(unaryNode.getSymbol());
-        return false;
+    private void loadADD(final UnaryNode unaryNode, final TypeBounds resultBounds) {
+        loadExpression(unaryNode.getExpression(), resultBounds.booleanToInt().notWiderThan(Type.NUMBER));
+        if(method.peekType() == Type.BOOLEAN) {
+            // It's a no-op in bytecode, but we must make sure it is treated as an int for purposes of type signatures
+            method.convert(Type.INT);
+        }
     }
 
-    @Override
-    public boolean enterBIT_NOT(final UnaryNode unaryNode) {
-        load(unaryNode.rhs(), Type.INT).load(-1).xor().store(unaryNode.getSymbol());
-        return false;
+    private void loadBIT_NOT(final UnaryNode unaryNode) {
+        loadExpression(unaryNode.getExpression(), TypeBounds.INT).load(-1).xor();
     }
 
-    @Override
-    public boolean enterDECINC(final UnaryNode unaryNode) {
-        final Expression rhs         = unaryNode.rhs();
+    private void loadDECINC(final UnaryNode unaryNode) {
+        final Expression operand     = unaryNode.getExpression();
         final Type       type        = unaryNode.getType();
+        final TypeBounds typeBounds  = new TypeBounds(type, Type.NUMBER);
         final TokenType  tokenType   = unaryNode.tokenType();
         final boolean    isPostfix   = tokenType == TokenType.DECPOSTFIX || tokenType == TokenType.INCPOSTFIX;
         final boolean    isIncrement = tokenType == TokenType.INCPREFIX || tokenType == TokenType.INCPOSTFIX;
 
         assert !type.isObject();
 
-        new SelfModifyingStore<UnaryNode>(unaryNode, rhs) {
+        new SelfModifyingStore<UnaryNode>(unaryNode, operand) {
+
+            private void loadRhs() {
+                loadExpression(operand, typeBounds, true);
+            }
 
             @Override
             protected void evaluate() {
-                load(rhs, type, true);
-                if (!isPostfix) {
-                    if (type.isInteger()) {
-                        method.load(isIncrement ? 1 : -1);
-                    } else if (type.isLong()) {
-                        method.load(isIncrement ? 1L : -1L);
-                    } else {
-                        method.load(isIncrement ? 1.0 : -1.0);
-                    }
-                    method.add();
+                if(isPostfix) {
+                    loadRhs();
+                } else {
+                    new OptimisticOperation(unaryNode, typeBounds) {
+                        @Override
+                        void loadStack() {
+                            loadRhs();
+                            loadMinusOne();
+                        }
+                        @Override
+                        void consumeStack() {
+                            doDecInc(getProgramPoint());
+                        }
+                    }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(operand));
                 }
             }
 
@@ -2325,448 +3539,461 @@
             protected void storeNonDiscard() {
                 super.storeNonDiscard();
                 if (isPostfix) {
-                    if (type.isInteger()) {
-                        method.load(isIncrement ? 1 : -1);
-                    } else if (type.isLong()) {
-                        method.load(isIncrement ? 1L : 1L);
-                    } else {
-                        method.load(isIncrement ? 1.0 : -1.0);
-                    }
-                    method.add();
+                    new OptimisticOperation(unaryNode, typeBounds) {
+                        @Override
+                        void loadStack() {
+                            loadMinusOne();
+                        }
+                        @Override
+                        void consumeStack() {
+                            doDecInc(getProgramPoint());
+                        }
+                    }.emit(1); // 1 for non-incremented result on the top of the stack pushed in evaluate()
                 }
             }
-        }.store();
 
-        return false;
+            private void loadMinusOne() {
+                if (type.isInteger()) {
+                    method.load(isIncrement ? 1 : -1);
+                } else if (type.isLong()) {
+                    method.load(isIncrement ? 1L : -1L);
+                } else {
+                    method.load(isIncrement ? 1.0 : -1.0);
+                }
+            }
+
+            private void doDecInc(final int programPoint) {
+                method.add(programPoint);
+            }
+        }.store();
     }
 
-    @Override
-    public boolean enterDISCARD(final UnaryNode unaryNode) {
-        final Expression rhs = unaryNode.rhs();
+    private static int getOptimisticIgnoreCountForSelfModifyingExpression(final Expression target) {
+        return target instanceof AccessNode ? 1 : target instanceof IndexNode ? 2 : 0;
+    }
 
-        lc.pushDiscard(rhs);
-        load(rhs);
+    private void loadAndDiscard(final Expression expr) {
+        // TODO: move checks for discarding to actual expression load code (e.g. as we do with void). That way we might
+        // be able to eliminate even more checks.
+        if(expr instanceof PrimitiveLiteralNode | isLocalVariable(expr)) {
+            assert lc.getCurrentDiscard() != expr;
+            // Don't bother evaluating expressions without side effects. Typical usage is "void 0" for reliably generating
+            // undefined.
+            return;
+        }
 
-        if (lc.getCurrentDiscard() == rhs) {
-            assert !rhs.isAssignment();
+        lc.pushDiscard(expr);
+        loadExpression(expr, TypeBounds.UNBOUNDED);
+        if (lc.getCurrentDiscard() == expr) {
+            assert !expr.isAssignment();
+            // NOTE: if we had a way to load with type void, we could avoid popping
             method.pop();
             lc.popDiscard();
         }
-
-        return false;
     }
 
-    @Override
-    public boolean enterNEW(final UnaryNode unaryNode) {
-        final CallNode callNode = (CallNode)unaryNode.rhs();
+    private void loadNEW(final UnaryNode unaryNode) {
+        final CallNode callNode = (CallNode)unaryNode.getExpression();
         final List<Expression> args   = callNode.getArgs();
 
         // Load function reference.
-        load(callNode.getFunction(), Type.OBJECT); // must detect type error
+        loadExpressionAsObject(callNode.getFunction()); // must detect type error
 
         method.dynamicNew(1 + loadArgs(args), getCallSiteFlags());
-        method.store(unaryNode.getSymbol());
-
-        return false;
     }
 
-    @Override
-    public boolean enterNOT(final UnaryNode unaryNode) {
-        final Expression rhs = unaryNode.rhs();
-
-        load(rhs, Type.BOOLEAN);
-
-        final Label trueLabel  = new Label("true");
-        final Label afterLabel = new Label("after");
-
-        method.ifne(trueLabel);
-        method.load(true);
-        method._goto(afterLabel);
-        method.label(trueLabel);
-        method.load(false);
-        method.label(afterLabel);
-        method.store(unaryNode.getSymbol());
-
-        return false;
-    }
-
-    @Override
-    public boolean enterSUB(final UnaryNode unaryNode) {
-        assert unaryNode.getType().isNumeric();
-        load(unaryNode.rhs(), unaryNode.getType()).neg().store(unaryNode.getSymbol());
-        return false;
-    }
-
-    @Override
-    public boolean enterVOID(final UnaryNode unaryNode) {
-        load(unaryNode.rhs()).pop();
-        method.loadUndefined(Type.OBJECT);
-
-        return false;
-    }
-
-    private void enterNumericAdd(final Expression lhs, final Expression rhs, final Type type, final Symbol symbol) {
-        loadBinaryOperands(lhs, rhs, type);
-        method.add(); //if the symbol is optimistic, it always needs to be written, not on the stack?
-        method.store(symbol);
-    }
-
-    @Override
-    public boolean enterADD(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
-
-        final Type type = binaryNode.getType();
-        if (type.isNumeric()) {
-            enterNumericAdd(lhs, rhs, type, binaryNode.getSymbol());
+    private void loadNOT(final UnaryNode unaryNode) {
+        final Expression expr = unaryNode.getExpression();
+        if(expr instanceof UnaryNode && expr.isTokenType(TokenType.NOT)) {
+            // !!x is idiomatic boolean cast in JavaScript
+            loadExpressionAsBoolean(((UnaryNode)expr).getExpression());
         } else {
-            loadBinaryOperands(binaryNode);
-            method.add();
-            method.store(binaryNode.getSymbol());
-        }
+            final Label trueLabel  = new Label("true");
+            final Label afterLabel = new Label("after");
 
-        return false;
+            emitBranch(expr, trueLabel, true);
+            method.load(true);
+            method._goto(afterLabel);
+            method.label(trueLabel);
+            method.load(false);
+            method.label(afterLabel);
+        }
     }
 
-    private boolean enterAND_OR(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
+    private void loadSUB(final UnaryNode unaryNode, final TypeBounds resultBounds) {
+        final Type type = unaryNode.getType();
+        assert type.isNumeric();
+        final TypeBounds numericBounds = resultBounds.booleanToInt();
+        new OptimisticOperation(unaryNode, numericBounds) {
+            @Override
+            void loadStack() {
+                final Expression expr = unaryNode.getExpression();
+                loadExpression(expr, numericBounds.notWiderThan(Type.NUMBER));
+            }
+            @Override
+            void consumeStack() {
+                // Must do an explicit conversion to the operation's type when it's double so that we correctly handle
+                // negation of an int 0 to a double -0. With this, we get the correct negation of a local variable after
+                // it deoptimized, e.g. "iload_2; i2d; dneg". Without this, we get "iload_2; ineg; i2d".
+                if(type.isNumber()) {
+                    method.convert(type);
+                }
+                method.neg(getProgramPoint());
+            }
+        }.emit();
+    }
+
+    public void loadVOID(final UnaryNode unaryNode, final TypeBounds resultBounds) {
+        loadAndDiscard(unaryNode.getExpression());
+        if(lc.getCurrentDiscard() == unaryNode) {
+            lc.popDiscard();
+        } else {
+            method.loadUndefined(resultBounds.widest);
+        }
+    }
+
+    public void loadADD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
+        new OptimisticOperation(binaryNode, resultBounds) {
+            @Override
+            void loadStack() {
+                final TypeBounds operandBounds;
+                final boolean isOptimistic = isValid(getProgramPoint());
+                if(isOptimistic) {
+                    operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
+                } else {
+                    // Non-optimistic, non-FP +. Allow it to overflow.
+                    operandBounds = new TypeBounds(binaryNode.getWidestOperandType(), Type.OBJECT);
+                }
+                loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false);
+            }
+
+            @Override
+            void consumeStack() {
+                method.add(getProgramPoint());
+            }
+        }.emit();
+    }
+
+    private void loadAND_OR(final BinaryNode binaryNode, final TypeBounds resultBounds, final boolean isAnd) {
+        final Type narrowestOperandType = Type.widestReturnType(binaryNode.lhs().getType(), binaryNode.rhs().getType());
 
         final Label skip = new Label("skip");
+        if(narrowestOperandType == Type.BOOLEAN) {
+            // optimize all-boolean logical expressions
+            final Label onTrue = new Label("andor_true");
+            emitBranch(binaryNode, onTrue, true);
+            method.load(false);
+            method._goto(skip);
+            method.label(onTrue);
+            method.load(true);
+            method.label(skip);
+            return;
+        }
 
-        load(lhs, Type.OBJECT).dup().convert(Type.BOOLEAN);
+        final TypeBounds outBounds = resultBounds.notNarrowerThan(narrowestOperandType);
+        final JoinPredecessorExpression lhs = (JoinPredecessorExpression)binaryNode.lhs();
+        final boolean lhsConvert = LocalVariableConversion.hasLiveConversion(lhs);
+        final Label evalRhs = lhsConvert ? new Label("eval_rhs") : null;
 
-        if (binaryNode.tokenType() == TokenType.AND) {
-            method.ifeq(skip);
+        loadExpression(lhs, outBounds).dup().convert(Type.BOOLEAN);
+        if (isAnd) {
+            if(lhsConvert) {
+                method.ifne(evalRhs);
+            } else {
+                method.ifeq(skip);
+            }
+        } else if(lhsConvert) {
+            method.ifeq(evalRhs);
         } else {
             method.ifne(skip);
         }
 
+        if(lhsConvert) {
+            method.beforeJoinPoint(lhs);
+            method._goto(skip);
+            method.label(evalRhs);
+        }
+
         method.pop();
-        load(rhs, Type.OBJECT);
+        final JoinPredecessorExpression rhs = (JoinPredecessorExpression)binaryNode.rhs();
+        loadExpression(rhs, outBounds);
+        method.beforeJoinPoint(rhs);
         method.label(skip);
-        method.store(binaryNode.getSymbol());
-
-        return false;
     }
 
-    @Override
-    public boolean enterAND(final BinaryNode binaryNode) {
-        return enterAND_OR(binaryNode);
+    private static boolean isLocalVariable(final Expression lhs) {
+        return lhs instanceof IdentNode && isLocalVariable((IdentNode)lhs);
     }
 
-    @Override
-    public boolean enterASSIGN(final BinaryNode binaryNode) {
+    private static boolean isLocalVariable(final IdentNode lhs) {
+        return lhs.getSymbol().isBytecodeLocal();
+    }
+
+    // NOTE: does not use resultBounds as the assignment is driven by the type of the RHS
+    private void loadASSIGN(final BinaryNode binaryNode) {
         final Expression lhs = binaryNode.lhs();
         final Expression rhs = binaryNode.rhs();
 
-        final Type lhsType = lhs.getType();
         final Type rhsType = rhs.getType();
-
-        if (!lhsType.isEquivalentTo(rhsType)) {
-            //this is OK if scoped, only locals are wrong
+        // Detect dead assignments
+        if(lhs instanceof IdentNode) {
+            final Symbol symbol = ((IdentNode)lhs).getSymbol();
+            if(!symbol.isScope() && !symbol.hasSlotFor(rhsType) && lc.getCurrentDiscard() == binaryNode) {
+                loadAndDiscard(rhs);
+                lc.popDiscard();
+                method.markDeadLocalVariable(symbol);
+                return;
+            }
         }
 
         new Store<BinaryNode>(binaryNode, lhs) {
             @Override
             protected void evaluate() {
-                if ((lhs instanceof IdentNode) && !lhs.getSymbol().isScope()) {
-                    load(rhs, lhsType);
-                } else {
-                    load(rhs);
-                }
+                // NOTE: we're loading with "at least as wide as" so optimistic operations on the right hand side
+                // remain optimistic, and then explicitly convert to the required type if needed.
+                loadExpressionAsType(rhs, rhsType);
             }
         }.store();
-
-        return false;
     }
 
     /**
-     * Helper class for assignment ops, e.g. *=, += and so on..
+     * Binary self-assignment that can be optimistic: +=, -=, *=, and /=.
      */
-    private abstract class AssignOp extends SelfModifyingStore<BinaryNode> {
-
-        /** The type of the resulting operation */
-        private final Type opType;
+    private abstract class BinaryOptimisticSelfAssignment extends SelfModifyingStore<BinaryNode> {
 
         /**
          * Constructor
          *
          * @param node the assign op node
          */
-        AssignOp(final BinaryNode node) {
-            this(node.getType(), node);
+        BinaryOptimisticSelfAssignment(final BinaryNode node) {
+            super(node, node.lhs());
         }
 
-        /**
-         * Constructor
-         *
-         * @param opType type of the computation - overriding the type of the node
-         * @param node the assign op node
-         */
-        AssignOp(final Type opType, final BinaryNode node) {
+        protected abstract void op(OptimisticOperation oo);
+
+        @Override
+        protected void evaluate() {
+            final Expression lhs = assignNode.lhs();
+            final Type widest = assignNode.isTokenType(TokenType.ASSIGN_ADD) ? Type.OBJECT : assignNode.getWidestOperationType();
+            final TypeBounds bounds = new TypeBounds(assignNode.getType(), widest);
+            new OptimisticOperation(assignNode, bounds) {
+                @Override
+                void loadStack() {
+                    loadBinaryOperands(lhs, assignNode.rhs(), bounds, true);
+                }
+                @Override
+                void consumeStack() {
+                    op(this);
+                }
+            }.emit(getOptimisticIgnoreCountForSelfModifyingExpression(lhs));
+            method.convert(assignNode.getType());
+        }
+    }
+
+    /**
+     * Non-optimistic binary self-assignment operation. Basically, everything except +=, -=, *=, and /=.
+     */
+    private abstract class BinarySelfAssignment extends SelfModifyingStore<BinaryNode> {
+        BinarySelfAssignment(final BinaryNode node) {
             super(node, node.lhs());
-            this.opType = opType;
         }
 
         protected abstract void op();
 
         @Override
         protected void evaluate() {
-            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), opType, true);
+            loadBinaryOperands(assignNode.lhs(), assignNode.rhs(), TypeBounds.UNBOUNDED.notWiderThan(assignNode.getWidestOperandType()), true);
             op();
-            method.convert(assignNode.getType());
         }
     }
 
-    @Override
-    public boolean enterASSIGN_ADD(final BinaryNode binaryNode) {
-        assert RuntimeNode.Request.ADD.canSpecialize();
-        final Type lhsType = binaryNode.lhs().getType();
-        final Type rhsType = binaryNode.rhs().getType();
-        final boolean specialize = binaryNode.getType() == Type.OBJECT;
-
-        new AssignOp(binaryNode) {
-
+    private void loadASSIGN_ADD(final BinaryNode binaryNode) {
+        new BinaryOptimisticSelfAssignment(binaryNode) {
             @Override
-            protected void op() {
-                if (specialize) {
-                    method.dynamicRuntimeCall(
-                            new SpecializedRuntimeNode(
-                                Request.ADD,
-                                new Type[] {
-                                    lhsType,
-                                    rhsType,
-                                },
-                                Type.OBJECT).getInitialName(),
-                            Type.OBJECT,
-                            Request.ADD);
-                } else {
-                    method.add();
-                }
-            }
-
-            @Override
-            protected void evaluate() {
-                super.evaluate();
+            protected void op(final OptimisticOperation oo) {
+                assert !(binaryNode.getType().isObject() && oo.isOptimistic);
+                method.add(oo.getProgramPoint());
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_BIT_AND(final BinaryNode binaryNode) {
-        new AssignOp(Type.INT, binaryNode) {
+    private void loadASSIGN_BIT_AND(final BinaryNode binaryNode) {
+        new BinarySelfAssignment(binaryNode) {
             @Override
             protected void op() {
                 method.and();
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_BIT_OR(final BinaryNode binaryNode) {
-        new AssignOp(Type.INT, binaryNode) {
+    private void loadASSIGN_BIT_OR(final BinaryNode binaryNode) {
+        new BinarySelfAssignment(binaryNode) {
             @Override
             protected void op() {
                 method.or();
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_BIT_XOR(final BinaryNode binaryNode) {
-        new AssignOp(Type.INT, binaryNode) {
+    private void loadASSIGN_BIT_XOR(final BinaryNode binaryNode) {
+        new BinarySelfAssignment(binaryNode) {
             @Override
             protected void op() {
                 method.xor();
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_DIV(final BinaryNode binaryNode) {
-        new AssignOp(binaryNode) {
+    private void loadASSIGN_DIV(final BinaryNode binaryNode) {
+        new BinaryOptimisticSelfAssignment(binaryNode) {
             @Override
-            protected void op() {
-                method.div();
+            protected void op(final OptimisticOperation oo) {
+                method.div(oo.getProgramPoint());
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_MOD(final BinaryNode binaryNode) {
-        new AssignOp(binaryNode) {
+    private void loadASSIGN_MOD(final BinaryNode binaryNode) {
+        new BinaryOptimisticSelfAssignment(binaryNode) {
             @Override
-            protected void op() {
-                method.rem();
+            protected void op(final OptimisticOperation oo) {
+                method.rem(oo.getProgramPoint());
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_MUL(final BinaryNode binaryNode) {
-        new AssignOp(binaryNode) {
+    private void loadASSIGN_MUL(final BinaryNode binaryNode) {
+        new BinaryOptimisticSelfAssignment(binaryNode) {
             @Override
-            protected void op() {
-                method.mul();
+            protected void op(final OptimisticOperation oo) {
+                method.mul(oo.getProgramPoint());
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_SAR(final BinaryNode binaryNode) {
-        new AssignOp(Type.INT, binaryNode) {
+    private void loadASSIGN_SAR(final BinaryNode binaryNode) {
+        new BinarySelfAssignment(binaryNode) {
             @Override
             protected void op() {
                 method.sar();
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_SHL(final BinaryNode binaryNode) {
-        new AssignOp(Type.INT, binaryNode) {
+    private void loadASSIGN_SHL(final BinaryNode binaryNode) {
+        new BinarySelfAssignment(binaryNode) {
             @Override
             protected void op() {
                 method.shl();
             }
         }.store();
-
-        return false;
     }
 
-    @Override
-    public boolean enterASSIGN_SHR(final BinaryNode binaryNode) {
-        new AssignOp(Type.INT, binaryNode) {
+    private void loadASSIGN_SHR(final BinaryNode binaryNode) {
+        new BinarySelfAssignment(binaryNode) {
             @Override
             protected void op() {
-                method.shr();
-                method.convert(Type.LONG).load(JSType.MAX_UINT).and();
+                doSHR();
             }
-        }.store();
 
-        return false;
+        }.store();
     }
 
-    @Override
-    public boolean enterASSIGN_SUB(final BinaryNode binaryNode) {
-        new AssignOp(binaryNode) {
+    private void doSHR() {
+        // TODO: make SHR optimistic
+        method.shr().convert(Type.LONG).load(JSType.MAX_UINT).and();
+    }
+
+    private void loadASSIGN_SUB(final BinaryNode binaryNode) {
+        new BinaryOptimisticSelfAssignment(binaryNode) {
             @Override
-            protected void op() {
-                method.sub();
+            protected void op(final OptimisticOperation oo) {
+                method.sub(oo.getProgramPoint());
             }
         }.store();
-
-        return false;
     }
 
     /**
      * Helper class for binary arithmetic ops
      */
     private abstract class BinaryArith {
+        protected abstract void op(int programPoint);
 
-        protected abstract void op();
+        protected void evaluate(final BinaryNode node, final TypeBounds resultBounds) {
+            final TypeBounds numericBounds = resultBounds.booleanToInt().objectToNumber();
+            new OptimisticOperation(node, numericBounds) {
+                @Override
+                void loadStack() {
+                    final TypeBounds operandBounds;
+                    if(numericBounds.narrowest == Type.NUMBER) {
+                        // Result should be double always. Propagate it into the operands so we don't have lots of I2D
+                        // and L2D after operand evaluation.
+                        assert numericBounds.widest == Type.NUMBER;
+                        operandBounds = numericBounds;
+                    } else {
+                        final boolean isOptimistic = isValid(getProgramPoint());
+                        if(isOptimistic) {
+                            operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
+                        } else if(node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
+                            // Non-optimistic division must always take double arguments as its result must also be
+                            // double.
+                            operandBounds = TypeBounds.NUMBER;
+                        } else {
+                            // Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
+                            operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
+                                    numericBounds.widest), Type.NUMBER);
+                        }
+                    }
+                    loadBinaryOperands(node.lhs(), node.rhs(), operandBounds, false);
+                }
 
-        protected void evaluate(final BinaryNode node) {
-            loadBinaryOperands(node);
-            op();
-            method.store(node.getSymbol());
+                @Override
+                void consumeStack() {
+                    op(getProgramPoint());
+                }
+            }.emit();
         }
     }
 
-    @Override
-    public boolean enterBIT_AND(final BinaryNode binaryNode) {
+    private void loadBIT_AND(final BinaryNode binaryNode) {
+        loadBinaryOperands(binaryNode);
+        method.and();
+    }
+
+    private void loadBIT_OR(final BinaryNode binaryNode) {
+        loadBinaryOperands(binaryNode);
+        method.or();
+    }
+
+    private void loadBIT_XOR(final BinaryNode binaryNode) {
+        loadBinaryOperands(binaryNode);
+        method.xor();
+    }
+
+    private void loadCOMMARIGHT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
+        loadAndDiscard(binaryNode.lhs());
+        loadExpression(binaryNode.rhs(), resultBounds);
+    }
+
+    private void loadCOMMALEFT(final BinaryNode binaryNode, final TypeBounds resultBounds) {
+        loadExpression(binaryNode.lhs(), resultBounds);
+        loadAndDiscard(binaryNode.rhs());
+    }
+
+    private void loadDIV(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         new BinaryArith() {
             @Override
-            protected void op() {
-                method.and();
+            protected void op(final int programPoint) {
+                method.div(programPoint);
             }
-        }.evaluate(binaryNode);
-
-        return false;
+        }.evaluate(binaryNode, resultBounds);
     }
 
-    @Override
-    public boolean enterBIT_OR(final BinaryNode binaryNode) {
-        new BinaryArith() {
-            @Override
-            protected void op() {
-                method.or();
-            }
-        }.evaluate(binaryNode);
+    private void loadCmp(final BinaryNode binaryNode, final Condition cond) {
+        assert comparisonOperandsArePrimitive(binaryNode) : binaryNode;
+        loadBinaryOperands(binaryNode);
 
-        return false;
-    }
-
-    @Override
-    public boolean enterBIT_XOR(final BinaryNode binaryNode) {
-        new BinaryArith() {
-            @Override
-            protected void op() {
-                method.xor();
-            }
-        }.evaluate(binaryNode);
-
-        return false;
-    }
-
-    private boolean enterComma(final BinaryNode binaryNode) {
-        final Expression lhs = binaryNode.lhs();
-        final Expression rhs = binaryNode.rhs();
-
-        load(lhs);
-        load(rhs);
-        method.store(binaryNode.getSymbol());
-
-        return false;
-    }
-
-    @Override
-    public boolean enterCOMMARIGHT(final BinaryNode binaryNode) {
-        return enterComma(binaryNode);
-    }
-
-    @Override
-    public boolean enterCOMMALEFT(final BinaryNode binaryNode) {
-        return enterComma(binaryNode);
-    }
-
-    @Override
-    public boolean enterDIV(final BinaryNode binaryNode) {
-        new BinaryArith() {
-            @Override
-            protected void op() {
-                method.div();
-            }
-        }.evaluate(binaryNode);
-
-        return false;
-    }
-
-    private boolean enterCmp(final Expression lhs, final Expression rhs, final Condition cond, final Type type, final Symbol symbol) {
-        final Type lhsType = lhs.getType();
-        final Type rhsType = rhs.getType();
-
-        final Type widest = Type.widest(lhsType, rhsType);
-        assert widest.isNumeric() || widest.isBoolean() : widest;
-
-        loadBinaryOperands(lhs, rhs, widest);
         final Label trueLabel  = new Label("trueLabel");
         final Label afterLabel = new Label("skip");
 
@@ -2777,177 +4004,94 @@
         method.label(trueLabel);
         method.load(Boolean.TRUE);
         method.label(afterLabel);
-
-        method.convert(type);
-        method.store(symbol);
-
-        return false;
     }
 
-    private boolean enterCmp(final BinaryNode binaryNode, final Condition cond) {
-        return enterCmp(binaryNode.lhs(), binaryNode.rhs(), cond, binaryNode.getType(), binaryNode.getSymbol());
+    private static boolean comparisonOperandsArePrimitive(final BinaryNode binaryNode) {
+        final Type widest = Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType());
+        return widest.isNumeric() || widest.isBoolean();
     }
 
-    @Override
-    public boolean enterEQ(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.EQ);
-    }
-
-    @Override
-    public boolean enterEQ_STRICT(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.EQ);
-    }
-
-    @Override
-    public boolean enterGE(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.GE);
-    }
-
-    @Override
-    public boolean enterGT(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.GT);
-    }
-
-    @Override
-    public boolean enterLE(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.LE);
-    }
-
-    @Override
-    public boolean enterLT(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.LT);
-    }
-
-    @Override
-    public boolean enterMOD(final BinaryNode binaryNode) {
+    private void loadMOD(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         new BinaryArith() {
             @Override
-            protected void op() {
-                method.rem();
+            protected void op(final int programPoint) {
+                method.rem(programPoint);
             }
-        }.evaluate(binaryNode);
-
-        return false;
+        }.evaluate(binaryNode, resultBounds);
     }
 
-    @Override
-    public boolean enterMUL(final BinaryNode binaryNode) {
+    private void loadMUL(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         new BinaryArith() {
             @Override
-            protected void op() {
-                method.mul();
+            protected void op(final int programPoint) {
+                method.mul(programPoint);
             }
-        }.evaluate(binaryNode);
-
-        return false;
+        }.evaluate(binaryNode, resultBounds);
     }
 
-    @Override
-    public boolean enterNE(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.NE);
+    private void loadSAR(final BinaryNode binaryNode) {
+        loadBinaryOperands(binaryNode);
+        method.sar();
     }
 
-    @Override
-    public boolean enterNE_STRICT(final BinaryNode binaryNode) {
-        return enterCmp(binaryNode, Condition.NE);
+    private void loadSHL(final BinaryNode binaryNode) {
+        loadBinaryOperands(binaryNode);
+        method.shl();
     }
 
-    @Override
-    public boolean enterOR(final BinaryNode binaryNode) {
-        return enterAND_OR(binaryNode);
+    private void loadSHR(final BinaryNode binaryNode) {
+        loadBinaryOperands(binaryNode);
+        doSHR();
     }
 
-    @Override
-    public boolean enterSAR(final BinaryNode binaryNode) {
+    private void loadSUB(final BinaryNode binaryNode, final TypeBounds resultBounds) {
         new BinaryArith() {
             @Override
-            protected void op() {
-                method.sar();
+            protected void op(final int programPoint) {
+                method.sub(programPoint);
             }
-        }.evaluate(binaryNode);
-
-        return false;
+        }.evaluate(binaryNode, resultBounds);
     }
 
     @Override
-    public boolean enterSHL(final BinaryNode binaryNode) {
-        new BinaryArith() {
-            @Override
-            protected void op() {
-                method.shl();
-            }
-        }.evaluate(binaryNode);
-
-        return false;
+    public boolean enterLabelNode(final LabelNode labelNode) {
+        labeledBlockBreakLiveLocals.push(lc.getUsedSlotCount());
+        return true;
     }
 
     @Override
-    public boolean enterSHR(final BinaryNode binaryNode) {
-        new BinaryArith() {
-            @Override
-            protected void evaluate(final BinaryNode node) {
-                loadBinaryOperands(node.lhs(), node.rhs(), Type.INT);
-                op();
-                method.store(node.getSymbol());
-            }
-            @Override
-            protected void op() {
-                method.shr();
-                method.convert(Type.LONG).load(JSType.MAX_UINT).and();
-            }
-        }.evaluate(binaryNode);
-
-        return false;
+    protected boolean enterDefault(final Node node) {
+        throw new AssertionError("Code generator entered node of type " + node.getClass().getName());
     }
 
-    @Override
-    public boolean enterSUB(final BinaryNode binaryNode) {
-        new BinaryArith() {
-            @Override
-            protected void op() {
-                method.sub();
-            }
-        }.evaluate(binaryNode);
+    private void loadTernaryNode(final TernaryNode ternaryNode, final TypeBounds resultBounds) {
+        final Expression test = ternaryNode.getTest();
+        final JoinPredecessorExpression trueExpr  = ternaryNode.getTrueExpression();
+        final JoinPredecessorExpression falseExpr = ternaryNode.getFalseExpression();
 
-        return false;
-    }
+        final Label falseLabel = new Label("ternary_false");
+        final Label exitLabel  = new Label("ternary_exit");
 
-    @Override
-    public boolean enterTernaryNode(final TernaryNode ternaryNode) {
-        final Expression test      = ternaryNode.getTest();
-        final Expression trueExpr  = ternaryNode.getTrueExpression();
-        final Expression falseExpr = ternaryNode.getFalseExpression();
+        final Type outNarrowest = Type.narrowest(resultBounds.widest, Type.generic(Type.widestReturnType(trueExpr.getType(), falseExpr.getType())));
+        final TypeBounds outBounds = resultBounds.notNarrowerThan(outNarrowest);
 
-        final Symbol symbol     = ternaryNode.getSymbol();
-        final Label  falseLabel = new Label("ternary_false");
-        final Label  exitLabel  = new Label("ternary_exit");
+        emitBranch(test, falseLabel, false);
 
-        Type widest = Type.widest(ternaryNode.getType(), Type.widest(trueExpr.getType(), falseExpr.getType()));
-        if (trueExpr.getType().isArray() || falseExpr.getType().isArray()) { //loadArray creates a Java array type on the stack, calls global allocate, which creates a native array type
-            widest = Type.OBJECT;
-        }
-
-        load(test, Type.BOOLEAN);
-        // we still keep the conversion here as the AccessSpecializer can have separated the types, e.g. var y = x ? x=55 : 17
-        // will left as (Object)x=55 : (Object)17 by Lower. Then the first term can be {I}x=55 of type int, which breaks the
-        // symmetry for the temporary slot for this TernaryNode. This is evidence that we assign types and explicit conversions
-        // too early, or Apply the AccessSpecializer too late. We are mostly probably looking for a separate type pass to
-        // do this property. Then we never need any conversions in CodeGenerator
-        method.ifeq(falseLabel);
-        load(trueExpr, widest);
+        loadExpression(trueExpr.getExpression(), outBounds);
+        assert Type.generic(method.peekType()) == outBounds.narrowest;
+        method.beforeJoinPoint(trueExpr);
         method._goto(exitLabel);
         method.label(falseLabel);
-        load(falseExpr, widest);
+        loadExpression(falseExpr.getExpression(), outBounds);
+        assert Type.generic(method.peekType()) == outBounds.narrowest;
+        method.beforeJoinPoint(falseExpr);
         method.label(exitLabel);
-        method.store(symbol);
-
-        return false;
     }
 
     /**
      * Generate all shared scope calls generated during codegen.
      */
-    protected void generateScopeCalls() {
+    void generateScopeCalls() {
         for (final SharedScopeCall scopeAccess : lc.getScopeCalls()) {
             scopeAccess.generateScopeCall();
         }
@@ -2957,20 +4101,18 @@
      * Debug code used to print symbols
      *
      * @param block the block we are in
+     * @param function the function we are in
      * @param ident identifier for block or function where applicable
      */
-    @SuppressWarnings("resource")
-    private void printSymbols(final Block block, final String ident) {
-        if (!compiler.getEnv()._print_symbols) {
-            return;
+    private void printSymbols(final Block block, final FunctionNode function, final String ident) {
+        if (compiler.getScriptEnvironment()._print_symbols || function.getFlag(FunctionNode.IS_PRINT_SYMBOLS)) {
+            final PrintWriter out = compiler.getScriptEnvironment().getErr();
+            out.println("[BLOCK in '" + ident + "']");
+            if (!block.printSymbols(out)) {
+                out.println("<no symbols>");
+            }
+            out.println();
         }
-
-        final PrintWriter out = compiler.getEnv().getErr();
-        out.println("[BLOCK in '" + ident + "']");
-        if (!block.printSymbols(out)) {
-            out.println("<no symbols>");
-        }
-        out.println();
     }
 
 
@@ -3015,7 +4157,7 @@
         private int depth;
 
         /** If we have too many arguments, we need temporary storage, this is stored in 'quick' */
-        private Symbol quick;
+        private IdentNode quick;
 
         /**
          * Constructor
@@ -3046,9 +4188,6 @@
         }
 
         private void prologue() {
-            final Symbol targetSymbol = target.getSymbol();
-            final Symbol scopeSymbol  = lc.getCurrentFunction().compilerConstant(SCOPE);
-
             /**
              * This loads the parts of the target, e.g base and index. they are kept
              * on the stack throughout the store and used at the end to execute it
@@ -3057,9 +4196,10 @@
             target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 public boolean enterIdentNode(final IdentNode node) {
-                    if (targetSymbol.isScope()) {
-                        method.load(scopeSymbol);
-                        depth++;
+                    if (node.getSymbol().isScope()) {
+                        method.loadCompilerConstant(SCOPE);
+                        depth += Type.SCOPE.getSlots();
+                        assert depth == 1;
                     }
                     return false;
                 }
@@ -3069,8 +4209,9 @@
                     final BaseNode   baseNode = (BaseNode)target;
                     final Expression base     = baseNode.getBase();
 
-                    load(base, Type.OBJECT);
+                    loadExpressionAsObject(base);
                     depth += Type.OBJECT.getSlots();
+                    assert depth == 1;
 
                     if (isSelfModifying()) {
                         method.dup();
@@ -3090,9 +4231,9 @@
                     final Expression index = node.getIndex();
                     if (!index.getType().isNumeric()) {
                         // could be boolean here as well
-                        load(index, Type.OBJECT);
+                        loadExpressionAsObject(index);
                     } else {
-                        load(index);
+                        loadExpressionUnbounded(index);
                     }
                     depth += index.getType().getSlots();
 
@@ -3107,28 +4248,23 @@
             });
         }
 
-        private Symbol quickSymbol(final Type type) {
-            return quickSymbol(type, QUICK_PREFIX.symbolName());
-        }
-
         /**
-         * Quick symbol generates an extra local variable, always using the same
-         * slot, one that is available after the end of the frame.
+         * Generates an extra local variable, always using the same slot, one that is available after the end of the
+         * frame.
          *
-         * @param type the type of the symbol
-         * @param prefix the prefix for the variable name for the symbol
+         * @param type the type of the variable
          *
-         * @return the quick symbol
+         * @return the quick variable
          */
-        private Symbol quickSymbol(final Type type, final String prefix) {
-            final String name = lc.getCurrentFunction().uniqueName(prefix);
-            final Symbol symbol = new Symbol(name, IS_TEMP | IS_INTERNAL);
+        private IdentNode quickLocalVariable(final Type type) {
+            final String name = lc.getCurrentFunction().uniqueName(QUICK_PREFIX.symbolName());
+            final Symbol symbol = new Symbol(name, IS_INTERNAL | HAS_SLOT);
+            symbol.setHasSlotFor(type);
+            symbol.setFirstSlot(lc.quickSlot(type));
 
-            symbol.setType(type);
+            final IdentNode quickIdent = IdentNode.createInternalIdentifier(symbol).setType(type);
 
-            symbol.setSlot(lc.quickSlot(symbol));
-
-            return symbol;
+            return quickIdent;
         }
 
         // store the result that "lives on" after the op, e.g. "i" in i++ postfix.
@@ -3139,16 +4275,12 @@
                 return;
             }
 
-            final Symbol symbol = assignNode.getSymbol();
-            if (symbol.hasSlot()) {
-                method.dup().store(symbol);
-                return;
-            }
-
             if (method.dup(depth) == null) {
                 method.dup();
-                this.quick = quickSymbol(method.peekType());
-                method.store(quick);
+                final Type quickType = method.peekType();
+                this.quick = quickLocalVariable(quickType);
+                final Symbol quickSymbol = quick.getSymbol();
+                method.storeTemp(quickType, quickSymbol.getFirstSlot());
             }
         }
 
@@ -3163,7 +4295,7 @@
              */
             target.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
-                protected boolean enterDefault(Node node) {
+                protected boolean enterDefault(final Node node) {
                     throw new AssertionError("Unexpected node " + node + " in store epilogue");
                 }
 
@@ -3172,14 +4304,20 @@
                     final Symbol symbol = node.getSymbol();
                     assert symbol != null;
                     if (symbol.isScope()) {
+                        final int flags = CALLSITE_SCOPE | getCallSiteFlags();
                         if (isFastScope(symbol)) {
-                            storeFastScopeVar(symbol, CALLSITE_SCOPE | getCallSiteFlags());
+                            storeFastScopeVar(symbol, flags);
                         } else {
-                            method.dynamicSet(node.getName(), CALLSITE_SCOPE | getCallSiteFlags());
+                            method.dynamicSet(node.getName(), flags);
                         }
                     } else {
-                        method.convert(node.getType());
-                        method.store(symbol);
+                        final Type storeType = assignNode.getType();
+                        if (symbol.hasSlotFor(storeType)) {
+                            // Only emit a convert for a store known to be live; converts for dead stores can
+                            // give us an unnecessary ClassCastException.
+                            method.convert(storeType);
+                        }
+                        storeIdentWithCatchConversion(node, storeType);
                     }
                     return false;
 
@@ -3187,7 +4325,7 @@
 
                 @Override
                 public boolean enterAccessNode(final AccessNode node) {
-                    method.dynamicSet(node.getProperty().getName(), getCallSiteFlags());
+                    method.dynamicSet(node.getProperty(), getCallSiteFlags());
                     return false;
                 }
 
@@ -3215,35 +4353,48 @@
         }
     }
 
-    private void newFunctionObject(final FunctionNode functionNode, final FunctionNode originalFunctionNode) {
+    private void newFunctionObject(final FunctionNode functionNode, final boolean addInitializer) {
         assert lc.peek() == functionNode;
-        // We don't emit a ScriptFunction on stack for:
-        // 1. the outermost compiled function (as there's no code being generated in its outer context that'd need it
-        //    as a callee), and
-        // 2. for functions that are immediately called upon definition and they don't need a callee, e.g. (function(){})().
-        //    Such immediately-called functions are invoked using INVOKESTATIC (see enterFunctionNode() of the embedded
-        //    visitor of enterCallNode() for details), and if they don't need a callee, they don't have it on their
-        //    static method's parameter list.
-        if (lc.getOutermostFunction() == functionNode ||
-                (!functionNode.needsCallee()) && lc.isFunctionDefinedInCurrentCall(originalFunctionNode)) {
+
+        final int fnId = functionNode.getId();
+
+        final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(fnId);
+
+        assert data != null : functionNode.getName() + " has no data";
+
+        if (functionNode.isProgram() && !compiler.isOnDemandCompilation()) {
+            final CompileUnit fnUnit = functionNode.getCompileUnit();
+            final MethodEmitter createFunction = fnUnit.getClassEmitter().method(
+                    EnumSet.of(Flag.PUBLIC, Flag.STATIC), CREATE_PROGRAM_FUNCTION.symbolName(),
+                    ScriptFunction.class, ScriptObject.class);
+            createFunction.begin();
+            createFunction._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
+            loadConstant(data, fnUnit, createFunction);
+            createFunction.load(SCOPE_TYPE, 0);
+            createFunction.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
+            createFunction._return();
+            createFunction.end();
+        }
+
+        if (addInitializer && !compiler.isOnDemandCompilation()) {
+            compiler.addFunctionInitializer(data, functionNode);
+        }
+
+        // We don't emit a ScriptFunction on stack for the outermost compiled function (as there's no code being
+        // generated in its outer context that'd need it as a callee).
+        if (lc.getOutermostFunction() == functionNode) {
             return;
         }
 
-        // Generate the object class and property map in case this function is ever used as constructor
-        final String      className          = SCRIPTFUNCTION_IMPL_OBJECT;
-        final int         fieldCount         = ObjectClassGenerator.getPaddedFieldCount(functionNode.countThisProperties());
-        final String      allocatorClassName = Compiler.binaryName(ObjectClassGenerator.getClassName(fieldCount));
-        final PropertyMap allocatorMap       = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
+        method._new(SCRIPTFUNCTION_IMPL_NAME, SCRIPTFUNCTION_IMPL_TYPE).dup();
+        loadConstant(data);
 
-        method._new(className).dup();
-        loadConstant(new RecompilableScriptFunctionData(functionNode, compiler.getCodeInstaller(), allocatorClassName, allocatorMap));
-
-        if (functionNode.isLazy() || functionNode.needsParentScope()) {
+        if (functionNode.needsParentScope()) {
             method.loadCompilerConstant(SCOPE);
         } else {
             method.loadNull();
         }
-        method.invoke(constructorNoLookup(className, RecompilableScriptFunctionData.class, ScriptObject.class));
+        method.invoke(constructorNoLookup(SCRIPTFUNCTION_IMPL_NAME, RecompilableScriptFunctionData.class, ScriptObject.class));
     }
 
     // calls on Global class.
@@ -3251,10 +4402,6 @@
         return method.invokestatic(GLOBAL_OBJECT, "instance", "()L" + GLOBAL_OBJECT + ';');
     }
 
-    private MethodEmitter globalObjectPrototype() {
-        return method.invokestatic(GLOBAL_OBJECT, "objectPrototype", methodDescriptor(ScriptObject.class));
-    }
-
     private MethodEmitter globalAllocateArguments() {
         return method.invokestatic(GLOBAL_OBJECT, "allocateArguments", methodDescriptor(ScriptObject.class, Object[].class, Object.class, int.class));
     }
@@ -3276,12 +4423,907 @@
         return method.invokestatic(GLOBAL_OBJECT, "isEval", methodDescriptor(boolean.class, Object.class));
     }
 
+    private MethodEmitter globalReplaceLocationPropertyPlaceholder() {
+        return method.invokestatic(GLOBAL_OBJECT, "replaceLocationPropertyPlaceholder", methodDescriptor(Object.class, Object.class, Object.class));
+    }
+
     private MethodEmitter globalCheckObjectCoercible() {
         return method.invokestatic(GLOBAL_OBJECT, "checkObjectCoercible", methodDescriptor(void.class, Object.class));
     }
 
     private MethodEmitter globalDirectEval() {
         return method.invokestatic(GLOBAL_OBJECT, "directEval",
-                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, Object.class));
+                methodDescriptor(Object.class, Object.class, Object.class, Object.class, Object.class, boolean.class));
+    }
+
+    private abstract class OptimisticOperation {
+        private final boolean isOptimistic;
+        // expression and optimistic are the same reference
+        private final Expression expression;
+        private final Optimistic optimistic;
+        private final TypeBounds resultBounds;
+
+        OptimisticOperation(final Optimistic optimistic, final TypeBounds resultBounds) {
+            this.optimistic = optimistic;
+            this.expression = (Expression)optimistic;
+            this.resultBounds = resultBounds;
+            this.isOptimistic = isOptimistic(optimistic) && useOptimisticTypes() &&
+                    // Operation is only effectively optimistic if its type, after being coerced into the result bounds
+                    // is narrower than the upper bound.
+                    resultBounds.within(Type.generic(((Expression)optimistic).getType())).narrowerThan(resultBounds.widest);
+        }
+
+        MethodEmitter emit() {
+            return emit(0);
+        }
+
+        MethodEmitter emit(final int ignoredArgCount) {
+            final int     programPoint                  = optimistic.getProgramPoint();
+            final boolean optimisticOrContinuation      = isOptimistic || isContinuationEntryPoint(programPoint);
+            final boolean currentContinuationEntryPoint = isCurrentContinuationEntryPoint(programPoint);
+            final int     stackSizeOnEntry              = method.getStackSize() - ignoredArgCount;
+
+            // First store the values on the stack opportunistically into local variables. Doing it before loadStack()
+            // allows us to not have to pop/load any arguments that are pushed onto it by loadStack() in the second
+            // storeStack().
+            storeStack(ignoredArgCount, optimisticOrContinuation);
+
+            // Now, load the stack
+            loadStack();
+
+            // Now store the values on the stack ultimately into local variables. In vast majority of cases, this is
+            // (aside from creating the local types map) a no-op, as the first opportunistic stack store will already
+            // store all variables. However, there can be operations in the loadStack() that invalidate some of the
+            // stack stores, e.g. in "x[i] = x[++i]", "++i" will invalidate the already stored value for "i". In such
+            // unfortunate cases this second storeStack() will restore the invariant that everything on the stack is
+            // stored into a local variable, although at the cost of doing a store/load on the loaded arguments as well.
+            final int liveLocalsCount = storeStack(method.getStackSize() - stackSizeOnEntry, optimisticOrContinuation);
+            assert optimisticOrContinuation == (liveLocalsCount != -1);
+
+            final Label beginTry;
+            final Label catchLabel;
+            final Label afterConsumeStack = isOptimistic || currentContinuationEntryPoint ? new Label("after_consume_stack") : null;
+            if(isOptimistic) {
+                beginTry = new Label("try_optimistic");
+                final String catchLabelName = (afterConsumeStack == null ? "" : afterConsumeStack.toString()) + "_handler";
+                catchLabel = new Label(catchLabelName);
+                method.label(beginTry);
+            } else {
+                beginTry = catchLabel = null;
+            }
+
+            consumeStack();
+
+            if(isOptimistic) {
+                method._try(beginTry, afterConsumeStack, catchLabel, UnwarrantedOptimismException.class);
+            }
+
+            if(isOptimistic || currentContinuationEntryPoint) {
+                method.label(afterConsumeStack);
+
+                final int[] localLoads = method.getLocalLoadsOnStack(0, stackSizeOnEntry);
+                assert everyStackValueIsLocalLoad(localLoads) : Arrays.toString(localLoads) + ", " + stackSizeOnEntry + ", " + ignoredArgCount;
+                final List<Type> localTypesList = method.getLocalVariableTypes();
+                final int usedLocals = method.getUsedSlotsWithLiveTemporaries();
+                final List<Type> localTypes = method.getWidestLiveLocals(localTypesList.subList(0, usedLocals));
+                assert everyLocalLoadIsValid(localLoads, usedLocals) : Arrays.toString(localLoads) + " ~ " + localTypes;
+
+                if(isOptimistic) {
+                    addUnwarrantedOptimismHandlerLabel(localTypes, catchLabel);
+                }
+                if(currentContinuationEntryPoint) {
+                    final ContinuationInfo ci = getContinuationInfo();
+                    assert ci != null : "no continuation info found for " + lc.getCurrentFunction();
+                    assert !ci.hasTargetLabel(); // No duplicate program points
+                    ci.setTargetLabel(afterConsumeStack);
+                    ci.getHandlerLabel().markAsOptimisticContinuationHandlerFor(afterConsumeStack);
+                    // Can't rely on targetLabel.stack.localVariableTypes.length, as it can be higher due to effectively
+                    // dead local variables.
+                    ci.lvarCount = localTypes.size();
+                    ci.setStackStoreSpec(localLoads);
+                    ci.setStackTypes(Arrays.copyOf(method.getTypesFromStack(method.getStackSize()), stackSizeOnEntry));
+                    assert ci.getStackStoreSpec().length == ci.getStackTypes().length;
+                    ci.setReturnValueType(method.peekType());
+                    ci.lineNumber = getLastLineNumber();
+                    ci.catchLabel = catchLabels.peek();
+                }
+            }
+            return method;
+        }
+
+        /**
+         * Stores the current contents of the stack into local variables so they are not lost before invoking something that
+         * can result in an {@code UnwarantedOptimizationException}.
+         * @param ignoreArgCount the number of topmost arguments on stack to ignore when deciding on the shape of the catch
+         * block. Those are used in the situations when we could not place the call to {@code storeStack} early enough
+         * (before emitting code for pushing the arguments that the optimistic call will pop). This is admittedly a
+         * deficiency in the design of the code generator when it deals with self-assignments and we should probably look
+         * into fixing it.
+         * @return types of the significant local variables after the stack was stored (types for local variables used
+         * for temporary storage of ignored arguments are not returned).
+         * @param optimisticOrContinuation if false, this method should not execute
+         * a label for a catch block for the {@code UnwarantedOptimizationException}, suitable for capturing the
+         * currently live local variables, tailored to their types.
+         */
+        private int storeStack(final int ignoreArgCount, final boolean optimisticOrContinuation) {
+            if(!optimisticOrContinuation) {
+                return -1; // NOTE: correct value to return is lc.getUsedSlotCount(), but it wouldn't be used anyway
+            }
+
+            final int stackSize = method.getStackSize();
+            final Type[] stackTypes = method.getTypesFromStack(stackSize);
+            final int[] localLoadsOnStack = method.getLocalLoadsOnStack(0, stackSize);
+            final int usedSlots = method.getUsedSlotsWithLiveTemporaries();
+
+            final int firstIgnored = stackSize - ignoreArgCount;
+            // Find the first value on the stack (from the bottom) that is not a load from a local variable.
+            int firstNonLoad = 0;
+            while(firstNonLoad < firstIgnored && localLoadsOnStack[firstNonLoad] != Label.Stack.NON_LOAD) {
+                firstNonLoad++;
+            }
+
+            // Only do the store/load if first non-load is not an ignored argument. Otherwise, do nothing and return
+            // the number of used slots as the number of live local variables.
+            if(firstNonLoad >= firstIgnored) {
+                return usedSlots;
+            }
+
+            // Find the number of new temporary local variables that we need; it's the number of values on the stack that
+            // are not direct loads of existing local variables.
+            int tempSlotsNeeded = 0;
+            for(int i = firstNonLoad; i < stackSize; ++i) {
+                if(localLoadsOnStack[i] == Label.Stack.NON_LOAD) {
+                    tempSlotsNeeded += stackTypes[i].getSlots();
+                }
+            }
+
+            // Ensure all values on the stack that weren't directly loaded from a local variable are stored in a local
+            // variable. We're starting from highest local variable index, so that in case ignoreArgCount > 0 the ignored
+            // ones end up at the end of the local variable table.
+            int lastTempSlot = usedSlots + tempSlotsNeeded;
+            int ignoreSlotCount = 0;
+            for(int i = stackSize; i -- > firstNonLoad;) {
+                final int loadSlot = localLoadsOnStack[i];
+                if(loadSlot == Label.Stack.NON_LOAD) {
+                    final Type type = stackTypes[i];
+                    final int slots = type.getSlots();
+                    lastTempSlot -= slots;
+                    if(i >= firstIgnored) {
+                        ignoreSlotCount += slots;
+                    }
+                    method.storeTemp(type, lastTempSlot);
+                } else {
+                    method.pop();
+                }
+            }
+            assert lastTempSlot == usedSlots; // used all temporary locals
+
+            final List<Type> localTypesList = method.getLocalVariableTypes();
+
+            // Load values back on stack.
+            for(int i = firstNonLoad; i < stackSize; ++i) {
+                final int loadSlot = localLoadsOnStack[i];
+                final Type stackType = stackTypes[i];
+                final boolean isLoad = loadSlot != Label.Stack.NON_LOAD;
+                final int lvarSlot = isLoad ? loadSlot : lastTempSlot;
+                final Type lvarType = localTypesList.get(lvarSlot);
+                method.load(lvarType, lvarSlot);
+                if(isLoad) {
+                    // Conversion operators (I2L etc.) preserve "load"-ness of the value despite the fact that, in the
+                    // strict sense they are creating a derived value from the loaded value. This special behavior of
+                    // on-stack conversion operators is necessary to accommodate for differences in local variable types
+                    // after deoptimization; having a conversion operator throw away "load"-ness would create different
+                    // local variable table shapes between optimism-failed code and its deoptimized rest-of method).
+                    // After we load the value back, we need to redo the conversion to the stack type if stack type is
+                    // different.
+                    // NOTE: this would only strictly be necessary for widening conversions (I2L, L2D, I2D), and not for
+                    // narrowing ones (L2I, D2L, D2I) as only widening conversions are the ones that can get eliminated
+                    // in a deoptimized method, as their original input argument got widened. Maybe experiment with
+                    // throwing away "load"-ness for narrowing conversions in MethodEmitter.convert()?
+                    method.convert(stackType);
+                } else {
+                    // temporary stores never needs a convert, as their type is always the same as the stack type.
+                    assert lvarType == stackType;
+                    lastTempSlot += lvarType.getSlots();
+                }
+            }
+            // used all temporaries
+            assert lastTempSlot == usedSlots + tempSlotsNeeded;
+
+            return lastTempSlot - ignoreSlotCount;
+        }
+
+        private void addUnwarrantedOptimismHandlerLabel(final List<Type> localTypes, final Label label) {
+            final String lvarTypesDescriptor = getLvarTypesDescriptor(localTypes);
+            final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.getUnwarrantedOptimismHandlers();
+            Collection<Label> labels = unwarrantedOptimismHandlers.get(lvarTypesDescriptor);
+            if(labels == null) {
+                labels = new LinkedList<>();
+                unwarrantedOptimismHandlers.put(lvarTypesDescriptor, labels);
+            }
+            method.markLabelAsOptimisticCatchHandler(label, localTypes.size());
+            labels.add(label);
+        }
+
+        abstract void loadStack();
+
+        // Make sure that whatever indy call site you emit from this method uses {@code getCallSiteFlagsOptimistic(node)}
+        // or otherwise ensure optimistic flag is correctly set in the call site, otherwise it doesn't make much sense
+        // to use OptimisticExpression for emitting it.
+        abstract void consumeStack();
+
+        /**
+         * Emits the correct dynamic getter code. Normally just delegates to method emitter, except when the target
+         * expression is optimistic, and the desired type is narrower than the optimistic type. In that case, it'll emit a
+         * dynamic getter with its original optimistic type, and explicitly insert a narrowing conversion. This way we can
+         * preserve the optimism of the values even if they're subsequently immediately coerced into a narrower type. This
+         * is beneficial because in this case we can still presume that since the original getter was optimistic, the
+         * conversion has no side effects.
+         * @param name the name of the property being get
+         * @param flags call site flags
+         * @param isMethod whether we're preferrably retrieving a function
+         * @return the current method emitter
+         */
+        MethodEmitter dynamicGet(final String name, final int flags, final boolean isMethod) {
+            if(isOptimistic) {
+                return method.dynamicGet(getOptimisticCoercedType(), name, getOptimisticFlags(flags), isMethod);
+            }
+            return method.dynamicGet(resultBounds.within(expression.getType()), name, nonOptimisticFlags(flags), isMethod);
+        }
+
+        MethodEmitter dynamicGetIndex(final int flags, final boolean isMethod) {
+            if(isOptimistic) {
+                return method.dynamicGetIndex(getOptimisticCoercedType(), getOptimisticFlags(flags), isMethod);
+            }
+            return method.dynamicGetIndex(resultBounds.within(expression.getType()), nonOptimisticFlags(flags), isMethod);
+        }
+
+        MethodEmitter dynamicCall(final int argCount, final int flags) {
+            if (isOptimistic) {
+                return method.dynamicCall(getOptimisticCoercedType(), argCount, getOptimisticFlags(flags));
+            }
+            return method.dynamicCall(resultBounds.within(expression.getType()), argCount, nonOptimisticFlags(flags));
+        }
+
+        int getOptimisticFlags(final int flags) {
+            return flags | CALLSITE_OPTIMISTIC | (optimistic.getProgramPoint() << CALLSITE_PROGRAM_POINT_SHIFT); //encode program point in high bits
+        }
+
+        int getProgramPoint() {
+            return isOptimistic ? optimistic.getProgramPoint() : INVALID_PROGRAM_POINT;
+        }
+
+        void convertOptimisticReturnValue() {
+            if (isOptimistic) {
+                final Type optimisticType = getOptimisticCoercedType();
+                if(!optimisticType.isObject()) {
+                    method.load(optimistic.getProgramPoint());
+                    if(optimisticType.isInteger()) {
+                        method.invoke(ENSURE_INT);
+                    } else if(optimisticType.isLong()) {
+                        method.invoke(ENSURE_LONG);
+                    } else if(optimisticType.isNumber()) {
+                        method.invoke(ENSURE_NUMBER);
+                    } else {
+                        throw new AssertionError(optimisticType);
+                    }
+                }
+            }
+        }
+
+        void replaceCompileTimeProperty() {
+            final IdentNode identNode = (IdentNode)expression;
+            final String name = identNode.getSymbol().getName();
+            if (CompilerConstants.__FILE__.name().equals(name)) {
+                replaceCompileTimeProperty(getCurrentSource().getName());
+            } else if (CompilerConstants.__DIR__.name().equals(name)) {
+                replaceCompileTimeProperty(getCurrentSource().getBase());
+            } else if (CompilerConstants.__LINE__.name().equals(name)) {
+                replaceCompileTimeProperty(getCurrentSource().getLine(identNode.position()));
+            }
+        }
+
+        /**
+         * When an ident with name __FILE__, __DIR__, or __LINE__ is loaded, we'll try to look it up as any other
+         * identifier. However, if it gets all the way up to the Global object, it will send back a special value that
+         * represents a placeholder for these compile-time location properties. This method will generate code that loads
+         * the value of the compile-time location property and then invokes a method in Global that will replace the
+         * placeholder with the value. Effectively, if the symbol for these properties is defined anywhere in the lexical
+         * scope, they take precedence, but if they aren't, then they resolve to the compile-time location property.
+         * @param propertyValue the actual value of the property
+         */
+        private void replaceCompileTimeProperty(final Object propertyValue) {
+            assert method.peekType().isObject();
+            if(propertyValue instanceof String || propertyValue == null) {
+                method.load((String)propertyValue);
+            } else if(propertyValue instanceof Integer) {
+                method.load(((Integer)propertyValue).intValue());
+                method.convert(Type.OBJECT);
+            } else {
+                throw new AssertionError();
+            }
+            globalReplaceLocationPropertyPlaceholder();
+            convertOptimisticReturnValue();
+        }
+
+        /**
+         * Returns the type that should be used as the return type of the dynamic invocation that is emitted as the code
+         * for the current optimistic operation. If the type bounds is exact boolean or narrower than the expression's
+         * optimistic type, then the optimistic type is returned, otherwise the coercing type. Effectively, this method
+         * allows for moving the coercion into the optimistic type when it won't adversely affect the optimistic
+         * evaluation semantics, and for preserving the optimistic type and doing a separate coercion when it would
+         * affect it.
+         * @return
+         */
+        private Type getOptimisticCoercedType() {
+            final Type optimisticType = expression.getType();
+            assert resultBounds.widest.widerThan(optimisticType);
+            final Type narrowest = resultBounds.narrowest;
+
+            if(narrowest.isBoolean() || narrowest.narrowerThan(optimisticType)) {
+                assert !optimisticType.isObject();
+                return optimisticType;
+            }
+            assert !narrowest.isObject();
+            return narrowest;
+        }
+    }
+
+    private static boolean isOptimistic(final Optimistic optimistic) {
+        if(!optimistic.canBeOptimistic()) {
+            return false;
+        }
+        final Expression expr = (Expression)optimistic;
+        return expr.getType().narrowerThan(expr.getWidestOperationType());
+    }
+
+    private static boolean everyLocalLoadIsValid(final int[] loads, final int localCount) {
+        for (final int load : loads) {
+            if(load < 0 || load >= localCount) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private static boolean everyStackValueIsLocalLoad(final int[] loads) {
+        for (final int load : loads) {
+            if(load == Label.Stack.NON_LOAD) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private String getLvarTypesDescriptor(final List<Type> localVarTypes) {
+        final int count = localVarTypes.size();
+        final StringBuilder desc = new StringBuilder(count);
+        for(int i = 0; i < count;) {
+            i += appendType(desc, localVarTypes.get(i));
+        }
+        return method.markSymbolBoundariesInLvarTypesDescriptor(desc.toString());
+    }
+
+    private static int appendType(final StringBuilder b, final Type t) {
+        b.append(t.getBytecodeStackType());
+        return t.getSlots();
+    }
+
+    private static int countSymbolsInLvarTypeDescriptor(final String lvarTypeDescriptor) {
+        int count = 0;
+        for(int i = 0; i < lvarTypeDescriptor.length(); ++i) {
+            if(Character.isUpperCase(lvarTypeDescriptor.charAt(i))) {
+                ++count;
+            }
+        }
+        return count;
+
+    }
+    /**
+     * Generates all the required {@code UnwarrantedOptimismException} handlers for the current function. The employed
+     * strategy strives to maximize code reuse. Every handler constructs an array to hold the local variables, then
+     * fills in some trailing part of the local variables (those for which it has a unique suffix in the descriptor),
+     * then jumps to a handler for a prefix that's shared with other handlers. A handler that fills up locals up to
+     * position 0 will not jump to a prefix handler (as it has no prefix), but instead end with constructing and
+     * throwing a {@code RewriteException}. Since we lexicographically sort the entries, we only need to check every
+     * entry to its immediately preceding one for longest matching prefix.
+     * @return true if there is at least one exception handler
+     */
+    private boolean generateUnwarrantedOptimismExceptionHandlers(final FunctionNode fn) {
+        if(!useOptimisticTypes()) {
+            return false;
+        }
+
+        // Take the mapping of lvarSpecs -> labels, and turn them into a descending lexicographically sorted list of
+        // handler specifications.
+        final Map<String, Collection<Label>> unwarrantedOptimismHandlers = lc.popUnwarrantedOptimismHandlers();
+        if(unwarrantedOptimismHandlers.isEmpty()) {
+            return false;
+        }
+
+        method.lineNumber(0);
+
+        final List<OptimismExceptionHandlerSpec> handlerSpecs = new ArrayList<>(unwarrantedOptimismHandlers.size() * 4/3);
+        for(final String spec: unwarrantedOptimismHandlers.keySet()) {
+            handlerSpecs.add(new OptimismExceptionHandlerSpec(spec, true));
+        }
+        Collections.sort(handlerSpecs, Collections.reverseOrder());
+
+        // Map of local variable specifications to labels for populating the array for that local variable spec.
+        final Map<String, Label> delegationLabels = new HashMap<>();
+
+        // Do everything in a single pass over the handlerSpecs list. Note that the list can actually grow as we're
+        // passing through it as we might add new prefix handlers into it, so can't hoist size() outside of the loop.
+        for(int handlerIndex = 0; handlerIndex < handlerSpecs.size(); ++handlerIndex) {
+            final OptimismExceptionHandlerSpec spec = handlerSpecs.get(handlerIndex);
+            final String lvarSpec = spec.lvarSpec;
+            if(spec.catchTarget) {
+                assert !method.isReachable();
+                // Start a catch block and assign the labels for this lvarSpec with it.
+                method._catch(unwarrantedOptimismHandlers.get(lvarSpec));
+                // This spec is a catch target, so emit array creation code. The length of the array is the number of
+                // symbols - the number of uppercase characters.
+                method.load(countSymbolsInLvarTypeDescriptor(lvarSpec));
+                method.newarray(Type.OBJECT_ARRAY);
+            }
+            if(spec.delegationTarget) {
+                // If another handler can delegate to this handler as its prefix, then put a jump target here for the
+                // shared code (after the array creation code, which is never shared).
+                method.label(delegationLabels.get(lvarSpec)); // label must exist
+            }
+
+            final boolean lastHandler = handlerIndex == handlerSpecs.size() - 1;
+
+            int lvarIndex;
+            final int firstArrayIndex;
+            final int firstLvarIndex;
+            Label delegationLabel;
+            final String commonLvarSpec;
+            if(lastHandler) {
+                // Last handler block, doesn't delegate to anything.
+                lvarIndex = 0;
+                firstLvarIndex = 0;
+                firstArrayIndex = 0;
+                delegationLabel = null;
+                commonLvarSpec = null;
+            } else {
+                // Not yet the last handler block, will definitely delegate to another handler; let's figure out which
+                // one. It can be an already declared handler further down the list, or it might need to declare a new
+                // prefix handler.
+
+                // Since we're lexicographically ordered, the common prefix handler is defined by the common prefix of
+                // this handler and the next handler on the list.
+                final int nextHandlerIndex = handlerIndex + 1;
+                final String nextLvarSpec = handlerSpecs.get(nextHandlerIndex).lvarSpec;
+                commonLvarSpec = commonPrefix(lvarSpec, nextLvarSpec);
+                // We don't chop symbols in half
+                assert Character.isUpperCase(commonLvarSpec.charAt(commonLvarSpec.length() - 1));
+
+                // Let's find if we already have a declaration for such handler, or we need to insert it.
+                {
+                    boolean addNewHandler = true;
+                    int commonHandlerIndex = nextHandlerIndex;
+                    for(; commonHandlerIndex < handlerSpecs.size(); ++commonHandlerIndex) {
+                        final OptimismExceptionHandlerSpec forwardHandlerSpec = handlerSpecs.get(commonHandlerIndex);
+                        final String forwardLvarSpec = forwardHandlerSpec.lvarSpec;
+                        if(forwardLvarSpec.equals(commonLvarSpec)) {
+                            // We already have a handler for the common prefix.
+                            addNewHandler = false;
+                            // Make sure we mark it as a delegation target.
+                            forwardHandlerSpec.delegationTarget = true;
+                            break;
+                        } else if(!forwardLvarSpec.startsWith(commonLvarSpec)) {
+                            break;
+                        }
+                    }
+                    if(addNewHandler) {
+                        // We need to insert a common prefix handler. Note handlers created with catchTarget == false
+                        // will automatically have delegationTarget == true (because that's the only reason for their
+                        // existence).
+                        handlerSpecs.add(commonHandlerIndex, new OptimismExceptionHandlerSpec(commonLvarSpec, false));
+                    }
+                }
+
+                firstArrayIndex = countSymbolsInLvarTypeDescriptor(commonLvarSpec);
+                lvarIndex = 0;
+                for(int j = 0; j < commonLvarSpec.length(); ++j) {
+                    lvarIndex += CodeGeneratorLexicalContext.getTypeForSlotDescriptor(commonLvarSpec.charAt(j)).getSlots();
+                }
+                firstLvarIndex = lvarIndex;
+
+                // Create a delegation label if not already present
+                delegationLabel = delegationLabels.get(commonLvarSpec);
+                if(delegationLabel == null) {
+                    // uo_pa == "unwarranted optimism, populate array"
+                    delegationLabel = new Label("uo_pa_" + commonLvarSpec);
+                    delegationLabels.put(commonLvarSpec, delegationLabel);
+                }
+            }
+
+            // Load local variables handled by this handler on stack
+            int args = 0;
+            boolean symbolHadValue = false;
+            for(int typeIndex = commonLvarSpec == null ? 0 : commonLvarSpec.length(); typeIndex < lvarSpec.length(); ++typeIndex) {
+                final char typeDesc = lvarSpec.charAt(typeIndex);
+                final Type lvarType = CodeGeneratorLexicalContext.getTypeForSlotDescriptor(typeDesc);
+                if (!lvarType.isUnknown()) {
+                    method.load(lvarType, lvarIndex);
+                    symbolHadValue = true;
+                    args++;
+                } else if(typeDesc == 'U' && !symbolHadValue) {
+                    // Symbol boundary with undefined last value. Check if all previous values for this symbol were also
+                    // undefined; if so, emit one explicit Undefined. This serves to ensure that we're emiting exactly
+                    // one value for every symbol that uses local slots. While we could in theory ignore symbols that
+                    // are undefined (in other words, dead) at the point where this exception was thrown, unfortunately
+                    // we can't do it in practice. The reason for this is that currently our liveness analysis is
+                    // coarse (it can determine whether a symbol has not been read with a particular type anywhere in
+                    // the function being compiled, but that's it), and a symbol being promoted to Object due to a
+                    // deoptimization will suddenly show up as "live for Object type", and previously dead U->O
+                    // conversions on loop entries will suddenly become alive in the deoptimized method which will then
+                    // expect a value for that slot in its continuation handler. If we had precise liveness analysis, we
+                    // could go back to excluding known dead symbols from the payload of the RewriteException.
+                    if(method.peekType() == Type.UNDEFINED) {
+                        method.dup();
+                    } else {
+                        method.loadUndefined(Type.OBJECT);
+                    }
+                    args++;
+                }
+                if(Character.isUpperCase(typeDesc)) {
+                    // Reached symbol boundary; reset flag for the next symbol.
+                    symbolHadValue = false;
+                }
+                lvarIndex += lvarType.getSlots();
+            }
+            assert args > 0;
+            // Delegate actual storing into array to an array populator utility method.
+            //on the stack:
+            // object array to be populated
+            // start index
+            // a lot of types
+            method.dynamicArrayPopulatorCall(args + 1, firstArrayIndex);
+            if(delegationLabel != null) {
+                // We cascade to a prefix handler to fill out the rest of the local variables and throw the
+                // RewriteException.
+                assert !lastHandler;
+                assert commonLvarSpec != null;
+                // Must undefine the local variables that we have already processed for the sake of correct join on the
+                // delegate label
+                method.undefineLocalVariables(firstLvarIndex, true);
+                final OptimismExceptionHandlerSpec nextSpec = handlerSpecs.get(handlerIndex + 1);
+                // If the delegate immediately follows, and it's not a catch target (so it doesn't have array setup
+                // code) don't bother emitting a jump, as we'd just jump to the next instruction.
+                if(!nextSpec.lvarSpec.equals(commonLvarSpec) || nextSpec.catchTarget) {
+                    method._goto(delegationLabel);
+                }
+            } else {
+                assert lastHandler;
+                // Nothing to delegate to, so this handler must create and throw the RewriteException.
+                // At this point we have the UnwarrantedOptimismException and the Object[] with local variables on
+                // stack. We need to create a RewriteException, push two references to it below the constructor
+                // arguments, invoke the constructor, and throw the exception.
+                loadConstant(getByteCodeSymbolNames(fn));
+                if (isRestOf()) {
+                    loadConstant(getContinuationEntryPoints());
+                    method.invoke(CREATE_REWRITE_EXCEPTION_REST_OF);
+                } else {
+                    method.invoke(CREATE_REWRITE_EXCEPTION);
+                }
+                method.athrow();
+            }
+        }
+        return true;
+    }
+
+    private static String[] getByteCodeSymbolNames(final FunctionNode fn) {
+        // Only names of local variables on the function level are captured. This information is used to reduce
+        // deoptimizations, so as much as we can capture will help. We rely on the fact that function wide variables are
+        // all live all the time, so the array passed to rewrite exception contains one element for every slotted symbol
+        // here.
+        final List<String> names = new ArrayList<>();
+        for (final Symbol symbol: fn.getBody().getSymbols()) {
+            if (symbol.hasSlot()) {
+                if (symbol.isScope()) {
+                    // slot + scope can only be true for parameters
+                    assert symbol.isParam();
+                    names.add(null);
+                } else {
+                    names.add(symbol.getName());
+                }
+            }
+        }
+        return names.toArray(new String[names.size()]);
+    }
+
+    private static String commonPrefix(final String s1, final String s2) {
+        final int l1 = s1.length();
+        final int l = Math.min(l1, s2.length());
+        int lms = -1; // last matching symbol
+        for(int i = 0; i < l; ++i) {
+            final char c1 = s1.charAt(i);
+            if(c1 != s2.charAt(i)) {
+                return s1.substring(0, lms + 1);
+            } else if(Character.isUpperCase(c1)) {
+                lms = i;
+            }
+        }
+        return l == l1 ? s1 : s2;
+    }
+
+    private static class OptimismExceptionHandlerSpec implements Comparable<OptimismExceptionHandlerSpec> {
+        private final String lvarSpec;
+        private final boolean catchTarget;
+        private boolean delegationTarget;
+
+        OptimismExceptionHandlerSpec(final String lvarSpec, final boolean catchTarget) {
+            this.lvarSpec = lvarSpec;
+            this.catchTarget = catchTarget;
+            if(!catchTarget) {
+                delegationTarget = true;
+            }
+        }
+
+        @Override
+        public int compareTo(final OptimismExceptionHandlerSpec o) {
+            return lvarSpec.compareTo(o.lvarSpec);
+        }
+
+        @Override
+        public String toString() {
+            final StringBuilder b = new StringBuilder(64).append("[HandlerSpec ").append(lvarSpec);
+            if(catchTarget) {
+                b.append(", catchTarget");
+            }
+            if(delegationTarget) {
+                b.append(", delegationTarget");
+            }
+            return b.append("]").toString();
+        }
+    }
+
+    private static class ContinuationInfo {
+        private final Label handlerLabel;
+        private Label targetLabel; // Label for the target instruction.
+        int lvarCount;
+        // Indices of local variables that need to be loaded on the stack when this node completes
+        private int[] stackStoreSpec;
+        // Types of values loaded on the stack
+        private Type[] stackTypes;
+        // If non-null, this node should perform the requisite type conversion
+        private Type returnValueType;
+        // If we are in the middle of an object literal initialization, we need to update the map
+        private PropertyMap objectLiteralMap;
+        // Object literal stack depth for object literal - not necessarly top if property is a tree
+        private int objectLiteralStackDepth = -1;
+        // The line number at the continuation point
+        private int lineNumber;
+        // The active catch label, in case the continuation point is in a try/catch block
+        private Label catchLabel;
+        // The number of scopes that need to be popped before control is transferred to the catch label.
+        private int exceptionScopePops;
+
+        ContinuationInfo() {
+            this.handlerLabel = new Label("continuation_handler");
+        }
+
+        Label getHandlerLabel() {
+            return handlerLabel;
+        }
+
+        boolean hasTargetLabel() {
+            return targetLabel != null;
+        }
+
+        Label getTargetLabel() {
+            return targetLabel;
+        }
+
+        void setTargetLabel(final Label targetLabel) {
+            this.targetLabel = targetLabel;
+        }
+
+        int[] getStackStoreSpec() {
+            return stackStoreSpec.clone();
+        }
+
+        void setStackStoreSpec(final int[] stackStoreSpec) {
+            this.stackStoreSpec = stackStoreSpec;
+        }
+
+        Type[] getStackTypes() {
+            return stackTypes.clone();
+        }
+
+        void setStackTypes(final Type[] stackTypes) {
+            this.stackTypes = stackTypes;
+        }
+
+        Type getReturnValueType() {
+            return returnValueType;
+        }
+
+        void setReturnValueType(final Type returnValueType) {
+            this.returnValueType = returnValueType;
+        }
+
+        int getObjectLiteralStackDepth() {
+            return objectLiteralStackDepth;
+        }
+
+        void setObjectLiteralStackDepth(final int objectLiteralStackDepth) {
+            this.objectLiteralStackDepth = objectLiteralStackDepth;
+        }
+
+        PropertyMap getObjectLiteralMap() {
+            return objectLiteralMap;
+        }
+
+        void setObjectLiteralMap(final PropertyMap objectLiteralMap) {
+            this.objectLiteralMap = objectLiteralMap;
+        }
+
+        @Override
+        public String toString() {
+             return "[localVariableTypes=" + targetLabel.getStack().getLocalVariableTypesCopy() + ", stackStoreSpec=" +
+                     Arrays.toString(stackStoreSpec) + ", returnValueType=" + returnValueType + "]";
+        }
+    }
+
+    private ContinuationInfo getContinuationInfo() {
+        return fnIdToContinuationInfo.get(lc.getCurrentFunction().getId());
+    }
+
+    private void generateContinuationHandler() {
+        if (!isRestOf()) {
+            return;
+        }
+
+        final ContinuationInfo ci = getContinuationInfo();
+        method.label(ci.getHandlerLabel());
+
+        // There should never be an exception thrown from the continuation handler, but in case there is (meaning,
+        // Nashorn has a bug), then line number 0 will be an indication of where it came from (line numbers are Uint16).
+        method.lineNumber(0);
+
+        final Label.Stack stack = ci.getTargetLabel().getStack();
+        final List<Type> lvarTypes = stack.getLocalVariableTypesCopy();
+        final BitSet symbolBoundary = stack.getSymbolBoundaryCopy();
+        final int lvarCount = ci.lvarCount;
+
+        final Type rewriteExceptionType = Type.typeFor(RewriteException.class);
+        // Store the RewriteException into an unused local variable slot.
+        method.load(rewriteExceptionType, 0);
+        method.storeTemp(rewriteExceptionType, lvarCount);
+        // Get local variable array
+        method.load(rewriteExceptionType, 0);
+        method.invoke(RewriteException.GET_BYTECODE_SLOTS);
+        // Store local variables. Note that deoptimization might introduce new value types for existing local variables,
+        // so we must use both liveLocals and symbolBoundary, as in some cases (when the continuation is inside of a try
+        // block) we need to store the incoming value into multiple slots. The optimism exception handlers will have
+        // exactly one array element for every symbol that uses bytecode storage. If in the originating method the value
+        // was undefined, there will be an explicit Undefined value in the array.
+        int arrayIndex = 0;
+        for(int lvarIndex = 0; lvarIndex < lvarCount;) {
+            final Type lvarType = lvarTypes.get(lvarIndex);
+            if(!lvarType.isUnknown()) {
+                method.dup();
+                method.load(arrayIndex).arrayload();
+                final Class<?> typeClass = lvarType.getTypeClass();
+                // Deoptimization in array initializers can cause arrays to undergo component type widening
+                if(typeClass == long[].class) {
+                    method.load(rewriteExceptionType, lvarCount);
+                    method.invoke(RewriteException.TO_LONG_ARRAY);
+                } else if(typeClass == double[].class) {
+                    method.load(rewriteExceptionType, lvarCount);
+                    method.invoke(RewriteException.TO_DOUBLE_ARRAY);
+                } else if(typeClass == Object[].class) {
+                    method.load(rewriteExceptionType, lvarCount);
+                    method.invoke(RewriteException.TO_OBJECT_ARRAY);
+                } else {
+                    if(!(typeClass.isPrimitive() || typeClass == Object.class)) {
+                        // NOTE: this can only happen with dead stores. E.g. for the program "1; []; f();" in which the
+                        // call to f() will deoptimize the call site, but it'll expect :return to have the type
+                        // NativeArray. However, in the more optimal version, :return's only live type is int, therefore
+                        // "{O}:return = []" is a dead store, and the variable will be sent into the continuation as
+                        // Undefined, however NativeArray can't hold Undefined instance.
+                        method.loadType(Type.getInternalName(typeClass));
+                        method.invoke(RewriteException.INSTANCE_OR_NULL);
+                    }
+                    method.convert(lvarType);
+                }
+                method.storeHidden(lvarType, lvarIndex, false);
+            }
+            final int nextLvarIndex = lvarIndex + lvarType.getSlots();
+            if(symbolBoundary.get(nextLvarIndex - 1)) {
+                ++arrayIndex;
+            }
+            lvarIndex = nextLvarIndex;
+        }
+        if (AssertsEnabled.assertsEnabled()) {
+            method.load(arrayIndex);
+            method.invoke(RewriteException.ASSERT_ARRAY_LENGTH);
+        } else {
+            method.pop();
+        }
+
+        final int[]   stackStoreSpec = ci.getStackStoreSpec();
+        final Type[]  stackTypes     = ci.getStackTypes();
+        final boolean isStackEmpty   = stackStoreSpec.length == 0;
+        boolean replacedObjectLiteralMap = false;
+        if(!isStackEmpty) {
+            // Load arguments on the stack
+            final int objectLiteralStackDepth = ci.getObjectLiteralStackDepth();
+            for(int i = 0; i < stackStoreSpec.length; ++i) {
+                final int slot = stackStoreSpec[i];
+                method.load(lvarTypes.get(slot), slot);
+                method.convert(stackTypes[i]);
+                // stack: s0=object literal being initialized
+                // change map of s0 so that the property we are initilizing when we failed
+                // is now ci.returnValueType
+                if (i == objectLiteralStackDepth) {
+                    method.dup();
+                    assert ci.getObjectLiteralMap() != null;
+                    assert ScriptObject.class.isAssignableFrom(method.peekType().getTypeClass()) : method.peekType().getTypeClass() + " is not a script object";
+                    loadConstant(ci.getObjectLiteralMap());
+                    method.invoke(ScriptObject.SET_MAP);
+                    replacedObjectLiteralMap = true;
+                }
+            }
+        }
+        // Must have emitted the code for replacing the map of an object literal if we have a set object literal stack depth
+        assert ci.getObjectLiteralStackDepth() == -1 || replacedObjectLiteralMap;
+        // Load RewriteException back.
+        method.load(rewriteExceptionType, lvarCount);
+        // Get rid of the stored reference
+        method.loadNull();
+        method.storeHidden(Type.OBJECT, lvarCount);
+        // Mark it dead
+        method.markDeadSlots(lvarCount, Type.OBJECT.getSlots());
+
+        // Load return value on the stack
+        method.invoke(RewriteException.GET_RETURN_VALUE);
+
+        final Type returnValueType = ci.getReturnValueType();
+
+        // Set up an exception handler for primitive type conversion of return value if needed
+        boolean needsCatch = false;
+        final Label targetCatchLabel = ci.catchLabel;
+        Label _try = null;
+        if(returnValueType.isPrimitive()) {
+            // If the conversion throws an exception, we want to report the line number of the continuation point.
+            method.lineNumber(ci.lineNumber);
+
+            if(targetCatchLabel != METHOD_BOUNDARY) {
+                _try = new Label("");
+                method.label(_try);
+                needsCatch = true;
+            }
+        }
+
+        // Convert return value
+        method.convert(returnValueType);
+
+        final int scopePopCount = needsCatch ? ci.exceptionScopePops : 0;
+
+        // Declare a try/catch for the conversion. If no scopes need to be popped until the target catch block, just
+        // jump into it. Otherwise, we'll need to create a scope-popping catch block below.
+        final Label catchLabel = scopePopCount > 0 ? new Label("") : targetCatchLabel;
+        if(needsCatch) {
+            final Label _end_try = new Label("");
+            method.label(_end_try);
+            method._try(_try, _end_try, catchLabel);
+        }
+
+        // Jump to continuation point
+        method._goto(ci.getTargetLabel());
+
+        // Make a scope-popping exception delegate if needed
+        if(catchLabel != targetCatchLabel) {
+            method.lineNumber(0);
+            assert scopePopCount > 0;
+            method._catch(catchLabel);
+            popScopes(scopePopCount);
+            method.uncheckedGoto(targetCatchLabel);
+        }
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
index dcf1b1b..1176dcc 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGeneratorLexicalContext.java
@@ -31,7 +31,7 @@
 import java.util.Deque;
 import java.util.HashMap;
 import java.util.Map;
-
+import jdk.nashorn.internal.IntDeque;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.FunctionNode;
@@ -63,6 +63,10 @@
      *  i.e. should we keep it or throw it away */
     private final Deque<Node> discard = new ArrayDeque<>();
 
+    private final Deque<Map<String, Collection<Label>>> unwarrantedOptimismHandlers = new ArrayDeque<>();
+    private final Deque<StringBuilder> slotTypesDescriptors = new ArrayDeque<>();
+    private final IntDeque splitNodes = new IntDeque();
+
     /** A stack tracking the next free local variable slot in the blocks. There's one entry for every block
      *  currently on the lexical context stack. */
     private int[] nextFreeSlots = new int[16];
@@ -70,46 +74,56 @@
     /** size of next free slot vector */
     private int nextFreeSlotsSize;
 
+    private boolean isWithBoundary(final LexicalContextNode node) {
+        return node instanceof Block && !isEmpty() && peek() instanceof WithNode;
+    }
+
     @Override
     public <T extends LexicalContextNode> T push(final T node) {
-        if (isDynamicScopeBoundary(node)) {
-            ++dynamicScopeCount;
+        if (isWithBoundary(node)) {
+            dynamicScopeCount++;
+        } else if (node instanceof FunctionNode) {
+            if (((FunctionNode)node).inDynamicContext()) {
+                dynamicScopeCount++;
+            }
+            splitNodes.push(0);
         }
         return super.push(node);
     }
 
+    void enterSplitNode() {
+        splitNodes.getAndIncrement();
+        pushFreeSlots(methodEmitters.peek().getUsedSlotsWithLiveTemporaries());
+    }
+
+    void exitSplitNode() {
+        final int count = splitNodes.decrementAndGet();
+        assert count >= 0;
+    }
+
     @Override
     public <T extends LexicalContextNode> T pop(final T node) {
         final T popped = super.pop(node);
-        if (isDynamicScopeBoundary(popped)) {
-            --dynamicScopeCount;
-        }
-        if (node instanceof Block) {
-            --nextFreeSlotsSize;
+        if (isWithBoundary(node)) {
+            dynamicScopeCount--;
+            assert dynamicScopeCount >= 0;
+        } else if (node instanceof FunctionNode) {
+            if (((FunctionNode)node).inDynamicContext()) {
+                dynamicScopeCount--;
+                assert dynamicScopeCount >= 0;
+            }
+            assert splitNodes.peek() == 0;
+            splitNodes.pop();
         }
         return popped;
     }
 
-    private boolean isDynamicScopeBoundary(final LexicalContextNode node) {
-        if (node instanceof Block) {
-            // Block's immediate parent is a with node. Note we aren't testing for a WithNode, as that'd capture
-            // processing of WithNode.expression too, but it should be unaffected.
-            return !isEmpty() && peek() instanceof WithNode;
-        } else if (node instanceof FunctionNode) {
-            // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
-            // variable into the function's scope), and it isn't strict (as evals in strict functions get an
-            // isolated scope).
-            return isFunctionDynamicScope((FunctionNode)node);
-        }
-        return false;
-    }
-
     boolean inDynamicScope() {
         return dynamicScopeCount > 0;
     }
 
-    static boolean isFunctionDynamicScope(FunctionNode fn) {
-        return fn.hasEval() && !fn.isStrict();
+    boolean inSplitNode() {
+        return !splitNodes.isEmpty() && splitNodes.peek() > 0;
     }
 
     MethodEmitter pushMethodEmitter(final MethodEmitter newMethod) {
@@ -123,6 +137,20 @@
         return methodEmitters.isEmpty() ? null : methodEmitters.peek();
     }
 
+    void pushUnwarrantedOptimismHandlers() {
+        unwarrantedOptimismHandlers.push(new HashMap<String, Collection<Label>>());
+        slotTypesDescriptors.push(new StringBuilder());
+    }
+
+    Map<String, Collection<Label>> getUnwarrantedOptimismHandlers() {
+        return unwarrantedOptimismHandlers.peek();
+    }
+
+    Map<String, Collection<Label>> popUnwarrantedOptimismHandlers() {
+        slotTypesDescriptors.pop();
+        return unwarrantedOptimismHandlers.pop();
+    }
+
     CompileUnit pushCompileUnit(final CompileUnit newUnit) {
         compileUnits.push(newUnit);
         return newUnit;
@@ -167,50 +195,77 @@
      * Get a shared static method representing a dynamic scope get access.
      *
      * @param unit current compile unit
-     * @param type the type of the variable
      * @param symbol the symbol
+     * @param valueType the type of the variable
      * @param flags the callsite flags
      * @return an object representing a shared scope call
      */
-    SharedScopeCall getScopeGet(final CompileUnit unit, final Type type, final Symbol symbol, final int flags) {
-        final SharedScopeCall scopeCall = new SharedScopeCall(symbol, type, type, null, flags);
-        if (scopeCalls.containsKey(scopeCall)) {
-            return scopeCalls.get(scopeCall);
-        }
-        scopeCall.setClassAndName(unit, getCurrentFunction().uniqueName(":scopeCall"));
-        scopeCalls.put(scopeCall, scopeCall);
-        return scopeCall;
+    SharedScopeCall getScopeGet(final CompileUnit unit, final Symbol symbol, final Type valueType, final int flags) {
+        return getScopeCall(unit, symbol, valueType, valueType, null, flags);
     }
 
+    void onEnterBlock(final Block block) {
+        pushFreeSlots(assignSlots(block, isFunctionBody() ? 0 : getUsedSlotCount()));
+    }
 
-    void nextFreeSlot(final Block block) {
-        final boolean isFunctionBody = isFunctionBody();
-
-        final int nextFreeSlot;
-        if (isFunctionBody) {
-            // On entry to function, start with slot 0
-            nextFreeSlot = 0;
-        } else {
-            // Otherwise, continue from previous block's first free slot
-            nextFreeSlot = nextFreeSlots[nextFreeSlotsSize - 1];
-        }
+    private void pushFreeSlots(final int freeSlots) {
         if (nextFreeSlotsSize == nextFreeSlots.length) {
             final int[] newNextFreeSlots = new int[nextFreeSlotsSize * 2];
             System.arraycopy(nextFreeSlots, 0, newNextFreeSlots, 0, nextFreeSlotsSize);
             nextFreeSlots = newNextFreeSlots;
         }
-        nextFreeSlots[nextFreeSlotsSize++] = assignSlots(block, nextFreeSlot);
+        nextFreeSlots[nextFreeSlotsSize++] = freeSlots;
     }
 
-    private static int assignSlots(final Block block, final int firstSlot) {
-        int nextSlot = firstSlot;
+    int getUsedSlotCount() {
+        return nextFreeSlots[nextFreeSlotsSize - 1];
+    }
+
+    void releaseSlots() {
+        --nextFreeSlotsSize;
+        final int undefinedFromSlot = nextFreeSlotsSize == 0 ? 0 : nextFreeSlots[nextFreeSlotsSize - 1];
+        if(!slotTypesDescriptors.isEmpty()) {
+            slotTypesDescriptors.peek().setLength(undefinedFromSlot);
+        }
+        methodEmitters.peek().undefineLocalVariables(undefinedFromSlot, false);
+    }
+
+    private int assignSlots(final Block block, final int firstSlot) {
+        int fromSlot = firstSlot;
+        final MethodEmitter method = methodEmitters.peek();
         for (final Symbol symbol : block.getSymbols()) {
             if (symbol.hasSlot()) {
-                symbol.setSlot(nextSlot);
-                nextSlot += symbol.slotCount();
+                symbol.setFirstSlot(fromSlot);
+                final int toSlot = fromSlot + symbol.slotCount();
+                method.defineBlockLocalVariable(fromSlot, toSlot);
+                fromSlot = toSlot;
             }
         }
-        return nextSlot;
+        return fromSlot;
+    }
+
+    static Type getTypeForSlotDescriptor(final char typeDesc) {
+        // Recognizing both lowercase and uppercase as we're using both to signify symbol boundaries; see
+        // MethodEmitter.markSymbolBoundariesInLvarTypesDescriptor().
+        switch(typeDesc) {
+            case 'I':
+            case 'i':
+                return Type.INT;
+            case 'J':
+            case 'j':
+                return Type.LONG;
+            case 'D':
+            case 'd':
+                return Type.NUMBER;
+            case 'A':
+            case 'a':
+                return Type.OBJECT;
+            case 'U':
+            case 'u':
+                return Type.UNKNOWN;
+            default:
+                throw new AssertionError();
+        }
     }
 
     void pushDiscard(final Node node) {
@@ -225,11 +280,8 @@
         return discard.peek();
     }
 
-    int quickSlot(final Symbol symbol) {
-        final int quickSlot = nextFreeSlots[nextFreeSlotsSize - 1];
-        nextFreeSlots[nextFreeSlotsSize - 1] = quickSlot + symbol.slotCount();
-        return quickSlot;
+    int quickSlot(final Type type) {
+        return methodEmitters.peek().defineTemporaryLocalVariable(type.getSlots());
     }
-
 }
 
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
index 6c0a673..8bf7727 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilationPhase.java
@@ -1,392 +1,454 @@
+/*
+ * 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.  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.
+ */
+
 package jdk.nashorn.internal.codegen;
 
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.ATTR;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BUILTINS_TRANSFORMED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_GENERATED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.BYTECODE_INSTALLED;
 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.CONSTANT_FOLDED;
-import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.FINALIZED;
 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.INITIALIZED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED;
 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.LOWERED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.OPTIMISTIC_TYPES_ASSIGNED;
 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.PARSED;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SCOPE_DEPTHS_COMPUTED;
 import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SPLIT;
+import static jdk.nashorn.internal.ir.FunctionNode.CompilationState.SYMBOLS_ASSIGNED;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.ArrayDeque;
+import java.io.PrintWriter;
 import java.util.ArrayList;
-import java.util.Deque;
 import java.util.EnumSet;
-import java.util.HashSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
-import jdk.nashorn.internal.codegen.types.Range;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.CallNode;
-import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.AssertsEnabled;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
 import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
+import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode.ArrayUnit;
 import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.ReturnNode;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.TemporarySymbols;
+import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.CodeInstaller;
+import jdk.nashorn.internal.runtime.FunctionInitializer;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
-import jdk.nashorn.internal.runtime.Timing;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
 
 /**
  * A compilation phase is a step in the processes of turning a JavaScript
  * FunctionNode into bytecode. It has an optional return value.
  */
 enum CompilationPhase {
-
-    /*
-     * Lazy initialization - tag all function nodes not the script as lazy as
-     * default policy. The will get trampolines and only be generated when
-     * called
-     */
-    LAZY_INITIALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED)) {
-        @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-
-            /*
-             * For lazy compilation, we might be given a node previously marked
-             * as lazy to compile as the outermost function node in the
-             * compiler. Unmark it so it can be compiled and not cause
-             * recursion. Make sure the return type is unknown so it can be
-             * correctly deduced. Return types are always Objects in Lazy nodes
-             * as we haven't got a change to generate code for them and decude
-             * its parameter specialization
-             *
-             * TODO: in the future specializations from a callsite will be
-             * passed here so we can generate a better non-lazy version of a
-             * function from a trampoline
-             */
-
-            final FunctionNode outermostFunctionNode = fn;
-
-            final Set<FunctionNode> neverLazy = new HashSet<>();
-            final Set<FunctionNode> lazy      = new HashSet<>();
-
-            FunctionNode newFunctionNode = outermostFunctionNode;
-
-            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                // self references are done with invokestatic and thus cannot
-                // have trampolines - never lazy
-                @Override
-                public boolean enterCallNode(final CallNode node) {
-                    final Node callee = node.getFunction();
-                    if (callee instanceof FunctionNode) {
-                        neverLazy.add(((FunctionNode)callee));
-                        return false;
-                    }
-                    return true;
-                }
-
-                //any function that isn't the outermost one must be marked as lazy
-                @Override
-                public boolean enterFunctionNode(final FunctionNode node) {
-                    assert compiler.isLazy();
-                    lazy.add(node);
-                    return true;
-                }
-            });
-
-            //at least one method is non lazy - the outermost one
-            neverLazy.add(newFunctionNode);
-
-            for (final FunctionNode node : neverLazy) {
-                Compiler.LOG.fine(
-                        "Marking ",
-                        node.getName(),
-                        " as non lazy, as it's a self reference");
-                lazy.remove(node);
-            }
-
-            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                @Override
-                public Node leaveFunctionNode(final FunctionNode functionNode) {
-                    if (lazy.contains(functionNode)) {
-                        Compiler.LOG.fine(
-                                "Marking ",
-                                functionNode.getName(),
-                                " as lazy");
-                        final FunctionNode parent = lc.getParentFunction(functionNode);
-                        assert parent != null;
-                        lc.setFlag(parent, FunctionNode.HAS_LAZY_CHILDREN);
-                        lc.setBlockNeedsScope(parent.getBody());
-                        lc.setFlag(functionNode, FunctionNode.IS_LAZY);
-                        return functionNode;
-                    }
-
-                    return functionNode.
-                        clearFlag(lc, FunctionNode.IS_LAZY).
-                        setReturnType(lc, Type.UNKNOWN);
-                }
-            });
-
-            return newFunctionNode;
-        }
-
-        @Override
-        public String toString() {
-            return "[Lazy JIT Initialization]";
-        }
-    },
-
-    /*
+    /**
      * Constant folding pass Simple constant folding that will make elementary
      * constructs go away
      */
-    CONSTANT_FOLDING_PHASE(EnumSet.of(INITIALIZED, PARSED)) {
+    CONSTANT_FOLDING_PHASE(
+            EnumSet.of(
+                INITIALIZED,
+                PARSED)) {
         @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            return (FunctionNode)fn.accept(new FoldConstants());
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            return (FunctionNode)fn.accept(new FoldConstants(compiler));
         }
 
         @Override
         public String toString() {
-            return "[Constant Folding]";
+            return "'Constant Folding'";
         }
     },
 
-    /*
+    /**
      * Lower (Control flow pass) Finalizes the control flow. Clones blocks for
      * finally constructs and similar things. Establishes termination criteria
      * for nodes Guarantee return instructions to method making sure control
      * flow cannot fall off the end. Replacing high level nodes with lower such
      * as runtime nodes where applicable.
      */
-    LOWERING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED)) {
+    LOWERING_PHASE(
+            EnumSet.of(
+                INITIALIZED,
+                PARSED,
+                CONSTANT_FOLDED)) {
         @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            return (FunctionNode)fn.accept(new Lower(compiler.getCodeInstaller()));
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            return (FunctionNode)fn.accept(new Lower(compiler));
         }
 
         @Override
         public String toString() {
-            return "[Control Flow Lowering]";
+            return "'Control Flow Lowering'";
         }
     },
 
-    /*
-     * Attribution Assign symbols and types to all nodes.
+    /**
+     * Phase used only when doing optimistic code generation. It assigns all potentially
+     * optimistic ops a program point so that an UnwarrantedException knows from where
+     * a guess went wrong when creating the continuation to roll back this execution
      */
-    ATTRIBUTION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED)) {
+    PROGRAM_POINT_PHASE(
+            EnumSet.of(
+                INITIALIZED,
+                PARSED,
+                CONSTANT_FOLDED,
+                LOWERED)) {
         @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            final TemporarySymbols ts = compiler.getTemporarySymbols();
-            final FunctionNode newFunctionNode = (FunctionNode)enterAttr(fn, ts).accept(new Attr(ts));
-            if (compiler.getEnv()._print_mem_usage) {
-                Compiler.LOG.info("Attr temporary symbol count: " + ts.getTotalSymbolCount());
-            }
-            return newFunctionNode;
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            return (FunctionNode)fn.accept(new ProgramPoints());
         }
 
-        /**
-         * Pessimistically set all lazy functions' return types to Object
-         * and the function symbols to object
-         * @param functionNode node where to start iterating
-         */
-        private FunctionNode enterAttr(final FunctionNode functionNode, final TemporarySymbols ts) {
-            return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+        @Override
+        public String toString() {
+            return "'Program Point Calculation'";
+        }
+    },
+
+    TRANSFORM_BUILTINS_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED)) {
+        //we only do this if we have a param type map, otherwise this is not a specialized recompile
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new ApplySpecialization(compiler));
+            return (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
                 public Node leaveFunctionNode(final FunctionNode node) {
-                    if (node.isLazy()) {
-                        FunctionNode newNode = node.setReturnType(lc, Type.OBJECT);
-                        return ts.ensureSymbol(lc, Type.OBJECT, newNode);
-                    }
-                    //node may have a reference here that needs to be nulled if it was referred to by
-                    //its outer context, if it is lazy and not attributed
-                    return node.setReturnType(lc, Type.UNKNOWN).setSymbol(lc, null);
+                    return node.setState(lc, BUILTINS_TRANSFORMED);
                 }
             });
         }
 
         @Override
         public String toString() {
-            return "[Type Attribution]";
+            return "'Builtin Replacement'";
         }
     },
 
-    /*
-     * Range analysis
-     *    Conservatively prove that certain variables can be narrower than
-     *    the most generic number type
+    /**
+     * Splitter Split the AST into several compile units based on a heuristic size calculation.
+     * Split IR can lead to scope information being changed.
      */
-    RANGE_ANALYSIS_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
+    SPLITTING_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED)) {
         @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            if (!compiler.getEnv()._range_analysis) {
-                return fn;
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            final CompileUnit  outermostCompileUnit = compiler.addCompileUnit(0L);
+
+            FunctionNode newFunctionNode;
+
+            //ensure elementTypes, postsets and presets exist for splitter and arraynodes
+            newFunctionNode = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+                @Override
+                public LiteralNode<?> leaveLiteralNode(final LiteralNode<?> literalNode) {
+                    return literalNode.initialize(lc);
+                }
+            });
+
+            newFunctionNode = new Splitter(compiler, newFunctionNode, outermostCompileUnit).split(newFunctionNode, true);
+
+            assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn=" + fn.getName() + ", fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
+            assert newFunctionNode.isStrict() == compiler.isStrict() : "functionNode.isStrict() != compiler.isStrict() for " + quote(newFunctionNode.getName());
+
+            return newFunctionNode;
+        }
+
+        @Override
+        public String toString() {
+            return "'Code Splitting'";
+        }
+    },
+
+    SYMBOL_ASSIGNMENT_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT)) {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            return (FunctionNode)fn.accept(new AssignSymbols(compiler));
+        }
+
+        @Override
+        public String toString() {
+            return "'Symbol Assignment'";
+        }
+    },
+
+    SCOPE_DEPTH_COMPUTATION_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT,
+                    SYMBOLS_ASSIGNED)) {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            return (FunctionNode)fn.accept(new FindScopeDepths(compiler));
+        }
+
+        @Override
+        public String toString() {
+            return "'Scope Depth Computation'";
+        }
+    },
+
+    OPTIMISTIC_TYPE_ASSIGNMENT_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT,
+                    SYMBOLS_ASSIGNED,
+                    SCOPE_DEPTHS_COMPUTED)) {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            if (compiler.useOptimisticTypes()) {
+                return (FunctionNode)fn.accept(new OptimisticTypesCalculator(compiler));
+            }
+            return setStates(fn, OPTIMISTIC_TYPES_ASSIGNED);
+        }
+
+        @Override
+        public String toString() {
+            return "'Optimistic Type Assignment'";
+        }
+    },
+
+    LOCAL_VARIABLE_TYPE_CALCULATION_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT,
+                    SYMBOLS_ASSIGNED,
+                    SCOPE_DEPTHS_COMPUTED,
+                    OPTIMISTIC_TYPES_ASSIGNED)) {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new LocalVariableTypesCalculator(compiler));
+
+            final ScriptEnvironment senv = compiler.getScriptEnvironment();
+            final PrintWriter       err  = senv.getErr();
+
+            //TODO separate phase for the debug printouts for abstraction and clarity
+            if (senv._print_lower_ast || fn.getFlag(FunctionNode.IS_PRINT_LOWER_AST)) {
+                err.println("Lower AST for: " + quote(newFunctionNode.getName()));
+                err.println(new ASTWriter(newFunctionNode));
             }
 
-            FunctionNode newFunctionNode = (FunctionNode)fn.accept(new RangeAnalyzer());
-            final List<ReturnNode> returns = new ArrayList<>();
+            if (senv._print_lower_parse || fn.getFlag(FunctionNode.IS_PRINT_LOWER_PARSE)) {
+                err.println("Lower AST for: " + quote(newFunctionNode.getName()));
+                err.println(new PrintVisitor(newFunctionNode));
+            }
 
-            newFunctionNode = (FunctionNode)newFunctionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-                private final Deque<ArrayList<ReturnNode>> returnStack = new ArrayDeque<>();
+            return newFunctionNode;
+        }
 
+        @Override
+        public String toString() {
+            return "'Local Variable Type Calculation'";
+        }
+    },
+
+    /**
+     * Reuse compile units, if they are already present. We are using the same compiler
+     * to recompile stuff
+     */
+    REUSE_COMPILE_UNITS_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT,
+                    SYMBOLS_ASSIGNED,
+                    SCOPE_DEPTHS_COMPUTED,
+                    OPTIMISTIC_TYPES_ASSIGNED,
+                    LOCAL_VARIABLE_TYPES_CALCULATED)) {
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            assert phases.isRestOfCompilation() : "reuse compile units currently only used for Rest-Of methods";
+
+            final Map<CompileUnit, CompileUnit> map = new HashMap<>();
+            final Set<CompileUnit> newUnits = CompileUnit.createCompileUnitSet();
+
+            final DebugLogger log = compiler.getLogger();
+
+            log.fine("Clearing bytecode cache");
+            compiler.clearBytecode();
+
+            for (final CompileUnit oldUnit : compiler.getCompileUnits()) {
+                assert map.get(oldUnit) == null;
+                final StringBuilder sb = new StringBuilder(compiler.nextCompileUnitName());
+                if (phases.isRestOfCompilation()) {
+                    sb.append("$restOf");
+                }
+                final CompileUnit newUnit = compiler.createCompileUnit(sb.toString(), oldUnit.getWeight());
+                log.fine("Creating new compile unit ", oldUnit, " => ", newUnit);
+                map.put(oldUnit, newUnit);
+                assert newUnit != null;
+                newUnits.add(newUnit);
+            }
+
+            log.fine("Replacing compile units in Compiler...");
+            compiler.replaceCompileUnits(newUnits);
+            log.fine("Done");
+
+            //replace old compile units in function nodes, if any are assigned,
+            //for example by running the splitter on this function node in a previous
+            //partial code generation
+            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
                 @Override
-                public boolean enterFunctionNode(final FunctionNode functionNode) {
-                    returnStack.push(new ArrayList<ReturnNode>());
-                    return true;
+                public Node leaveFunctionNode(final FunctionNode node) {
+                    final CompileUnit oldUnit = node.getCompileUnit();
+                    assert oldUnit != null : "no compile unit in function node";
+
+                    final CompileUnit newUnit = map.get(oldUnit);
+                    assert newUnit != null : "old unit has no mapping to new unit " + oldUnit;
+
+                    log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName()));
+                    return node.setCompileUnit(lc, newUnit).setState(lc, CompilationState.COMPILE_UNITS_REUSED);
                 }
 
                 @Override
-                public Node leaveFunctionNode(final FunctionNode functionNode) {
-                    Type returnType = Type.UNKNOWN;
-                    for (final ReturnNode ret : returnStack.pop()) {
-                        if (ret.getExpression() == null) {
-                            returnType = Type.OBJECT;
-                            break;
+                public Node leaveSplitNode(final SplitNode node) {
+                    final CompileUnit oldUnit = node.getCompileUnit();
+                    assert oldUnit != null : "no compile unit in function node";
+
+                    final CompileUnit newUnit = map.get(oldUnit);
+                    assert newUnit != null : "old unit has no mapping to new unit " + oldUnit;
+
+                    log.fine("Replacing compile unit: ", oldUnit, " => ", newUnit, " in ", quote(node.getName()));
+                    return node.setCompileUnit(lc, newUnit);
+                }
+
+                @Override
+                public Node leaveLiteralNode(final LiteralNode<?> node) {
+                    if (node instanceof ArrayLiteralNode) {
+                        final ArrayLiteralNode aln = (ArrayLiteralNode)node;
+                        if (aln.getUnits() == null) {
+                            return node;
                         }
-                        returnType = Type.widest(returnType, ret.getExpression().getType());
+                        final List<ArrayUnit> newArrayUnits = new ArrayList<>();
+                        for (final ArrayUnit au : aln.getUnits()) {
+                            final CompileUnit newUnit = map.get(au.getCompileUnit());
+                            assert newUnit != null;
+                            newArrayUnits.add(new ArrayUnit(newUnit, au.getLo(), au.getHi()));
+                        }
+                        return aln.setUnits(lc, newArrayUnits);
                     }
-                    return functionNode.setReturnType(lc, returnType);
-                }
-
-                @Override
-                public Node leaveReturnNode(final ReturnNode returnNode) {
-                    final ReturnNode result = (ReturnNode)leaveDefault(returnNode);
-                    returns.add(result);
-                    return result;
+                    return node;
                 }
 
                 @Override
                 public Node leaveDefault(final Node node) {
-                    if(node instanceof Expression) {
-                        final Expression expr = (Expression)node;
-                        final Symbol symbol = expr.getSymbol();
-                        if (symbol != null) {
-                            final Range range  = symbol.getRange();
-                            final Type  symbolType = symbol.getSymbolType();
-                            if (!symbolType.isNumeric()) {
-                                return expr;
-                            }
-                            final Type  rangeType  = range.getType();
-                            if (!Type.areEquivalent(symbolType, rangeType) && Type.widest(symbolType, rangeType) == symbolType) { //we can narrow range
-                                RangeAnalyzer.LOG.info("[", lc.getCurrentFunction().getName(), "] ", symbol, " can be ", range.getType(), " ", symbol.getRange());
-                                return expr.setSymbol(lc, symbol.setTypeOverrideShared(range.getType(), compiler.getTemporarySymbols()));
-                            }
-                        }
-                    }
-                    return node;
+                    return node.ensureUniqueLabels(lc);
                 }
             });
 
-            Type returnType = Type.UNKNOWN;
-            for (final ReturnNode node : returns) {
-                if (node.getExpression() != null) {
-                    returnType = Type.widest(returnType, node.getExpression().getType());
-                } else {
-                    returnType = Type.OBJECT;
-                    break;
-                }
-            }
-
-            return newFunctionNode.setReturnType(null, returnType);
-        }
-
-        @Override
-        public String toString() {
-            return "[Range Analysis]";
-        }
-    },
-
-
-    /*
-     * Splitter Split the AST into several compile units based on a size
-     * heuristic Splitter needs attributed AST for weight calculations (e.g. is
-     * a + b a ScriptRuntime.ADD with call overhead or a dadd with much less).
-     * Split IR can lead to scope information being changed.
-     */
-    SPLITTING_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR)) {
-        @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            final CompileUnit outermostCompileUnit = compiler.addCompileUnit(compiler.firstCompileUnitName());
-
-            final FunctionNode newFunctionNode = new Splitter(compiler, fn, outermostCompileUnit).split(fn);
-
-            assert newFunctionNode.getCompileUnit() == outermostCompileUnit : "fn.compileUnit (" + newFunctionNode.getCompileUnit() + ") != " + outermostCompileUnit;
-
-            if (newFunctionNode.isStrict()) {
-                assert compiler.getStrictMode();
-                compiler.setStrictMode(true);
-            }
-
             return newFunctionNode;
         }
 
         @Override
         public String toString() {
-            return "[Code Splitting]";
+            return "'Reuse Compile Units'";
         }
     },
 
-    /*
-     * FinalizeTypes
-     *
-     * This pass finalizes the types for nodes. If Attr created wider types than
-     * known during the first pass, convert nodes are inserted or access nodes
-     * are specialized where scope accesses.
-     *
-     * Runtime nodes may be removed and primitivized or reintroduced depending
-     * on information that was established in Attr.
-     *
-     * Contract: all variables must have slot assignments and scope assignments
-     * before type finalization.
-     */
-    TYPE_FINALIZATION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT)) {
-        @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            final ScriptEnvironment env = compiler.getEnv();
-
-            final FunctionNode newFunctionNode = (FunctionNode)fn.accept(new FinalizeTypes(compiler.getTemporarySymbols()));
-
-            if (env._print_lower_ast) {
-                env.getErr().println(new ASTWriter(newFunctionNode));
-            }
-
-            if (env._print_lower_parse) {
-                env.getErr().println(new PrintVisitor(newFunctionNode));
-            }
-
-            return newFunctionNode;
-        }
-
-        @Override
-        public String toString() {
-            return "[Type Finalization]";
-        }
-    },
-
-    /*
+     /**
      * Bytecode generation:
      *
      * Generate the byte code class(es) resulting from the compiled FunctionNode
      */
-    BYTECODE_GENERATION_PHASE(EnumSet.of(INITIALIZED, PARSED, CONSTANT_FOLDED, LOWERED, ATTR, SPLIT, FINALIZED)) {
+    BYTECODE_GENERATION_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT,
+                    SYMBOLS_ASSIGNED,
+                    SCOPE_DEPTHS_COMPUTED,
+                    OPTIMISTIC_TYPES_ASSIGNED,
+                    LOCAL_VARIABLE_TYPES_CALCULATED)) {
+
         @Override
-        FunctionNode transform(final Compiler compiler, final FunctionNode fn) {
-            final ScriptEnvironment env = compiler.getEnv();
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            final ScriptEnvironment senv = compiler.getScriptEnvironment();
+
             FunctionNode newFunctionNode = fn;
 
+            compiler.getLogger().fine("Starting bytecode generation for ", quote(fn.getName()), " - restOf=", phases.isRestOfCompilation());
+            final CodeGenerator codegen = new CodeGenerator(compiler, phases.isRestOfCompilation() ? compiler.getContinuationEntryPoints() : null);
             try {
-                final CodeGenerator codegen = new CodeGenerator(compiler);
-                newFunctionNode = (FunctionNode)newFunctionNode.accept(codegen);
+                // Explicitly set BYTECODE_GENERATED here; it can not be set in case of skipping codegen for :program
+                // in the lazy + optimistic world. See CodeGenerator.skipFunction().
+                newFunctionNode = ((FunctionNode)newFunctionNode.accept(codegen)).setState(null, BYTECODE_GENERATED);
                 codegen.generateScopeCalls();
             } catch (final VerifyError e) {
-                if (env._verify_code || env._print_code) {
-                    env.getErr().println(e.getClass().getSimpleName() + ": "  + e.getMessage());
-                    if (env._dump_on_error) {
-                        e.printStackTrace(env.getErr());
+                if (senv._verify_code || senv._print_code) {
+                    senv.getErr().println(e.getClass().getSimpleName() + ": "  + e.getMessage());
+                    if (senv._dump_on_error) {
+                        e.printStackTrace(senv.getErr());
                     }
                 } else {
                     throw e;
                 }
+            } catch (final Throwable e) {
+                // Provide source file and line number being compiled when the assertion occurred
+                throw new AssertionError("Failed generating bytecode for " + fn.getSourceName() + ":" + codegen.getLastLineNumber(), e);
             }
 
             for (final CompileUnit compileUnit : compiler.getCompileUnits()) {
@@ -400,50 +462,12 @@
 
                 compiler.addClass(className, bytecode);
 
-                // should could be printed to stderr for generate class?
-                if (env._print_code) {
-                    final StringBuilder sb = new StringBuilder();
-                    sb.append("class: " + className).append('\n')
-                            .append(ClassEmitter.disassemble(bytecode))
-                            .append("=====");
-                    env.getErr().println(sb);
-                }
-
                 // should we verify the generated code?
-                if (env._verify_code) {
+                if (senv._verify_code) {
                     compiler.getCodeInstaller().verify(bytecode);
                 }
 
-                // should code be dumped to disk - only valid in compile_only mode?
-                if (env._dest_dir != null && env._compile_only) {
-                    final String fileName = className.replace('.', File.separatorChar) + ".class";
-                    final int    index    = fileName.lastIndexOf(File.separatorChar);
-
-                    final File dir;
-                    if (index != -1) {
-                        dir = new File(env._dest_dir, fileName.substring(0, index));
-                    } else {
-                        dir = new File(env._dest_dir);
-                    }
-
-                    try {
-                        if (!dir.exists() && !dir.mkdirs()) {
-                            throw new IOException(dir.toString());
-                        }
-                        final File file = new File(env._dest_dir, fileName);
-                        try (final FileOutputStream fos = new FileOutputStream(file)) {
-                            fos.write(bytecode);
-                        }
-                        Compiler.LOG.info("Wrote class to '" + file.getAbsolutePath() + '\'');
-                    } catch (final IOException e) {
-                        Compiler.LOG.warning("Skipping class dump for ",
-                                className,
-                                ": ",
-                                ECMAErrors.getMessage(
-                                    "io.error.cant.write",
-                                    dir.toString()));
-                    }
-                }
+                DumpBytecode.dumpBytecode(senv, compiler.getLogger(), bytecode, className);
             }
 
             return newFunctionNode;
@@ -451,42 +475,176 @@
 
         @Override
         public String toString() {
-            return "[Bytecode Generation]";
+            return "'Bytecode Generation'";
         }
-    };
+    },
 
+     INSTALL_PHASE(
+            EnumSet.of(
+                    INITIALIZED,
+                    PARSED,
+                    CONSTANT_FOLDED,
+                    LOWERED,
+                    BUILTINS_TRANSFORMED,
+                    SPLIT,
+                    SYMBOLS_ASSIGNED,
+                    SCOPE_DEPTHS_COMPUTED,
+                    OPTIMISTIC_TYPES_ASSIGNED,
+                    LOCAL_VARIABLE_TYPES_CALCULATED,
+                    BYTECODE_GENERATED)) {
+
+        @Override
+        FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode fn) {
+            final DebugLogger log = compiler.getLogger();
+
+            final Map<String, Class<?>> installedClasses = new LinkedHashMap<>();
+
+            boolean first = true;
+            Class<?> rootClass = null;
+            long length = 0L;
+
+            final CodeInstaller<ScriptEnvironment> codeInstaller = compiler.getCodeInstaller();
+            final Map<String, byte[]>              bytecode      = compiler.getBytecode();
+
+            for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
+                final String className = entry.getKey();
+                //assert !first || className.equals(compiler.getFirstCompileUnit().getUnitClassName()) : "first=" + first + " className=" + className + " != " + compiler.getFirstCompileUnit().getUnitClassName();
+                final byte[] code = entry.getValue();
+                length += code.length;
+
+                final Class<?> clazz = codeInstaller.install(className, code);
+                if (first) {
+                    rootClass = clazz;
+                    first = false;
+                }
+                installedClasses.put(className, clazz);
+            }
+
+            if (rootClass == null) {
+                throw new CompilationException("Internal compiler error: root class not found!");
+            }
+
+            final Object[] constants = compiler.getConstantData().toArray();
+            codeInstaller.initialize(installedClasses.values(), compiler.getSource(), constants);
+
+            // initialize transient fields on recompilable script function data
+            for (final Object constant: constants) {
+                if (constant instanceof RecompilableScriptFunctionData) {
+                    ((RecompilableScriptFunctionData)constant).initTransients(compiler.getSource(), codeInstaller);
+                }
+            }
+
+            // initialize function in the compile units
+            for (final CompileUnit unit : compiler.getCompileUnits()) {
+                unit.setCode(installedClasses.get(unit.getUnitClassName()));
+            }
+
+            if (!compiler.isOnDemandCompilation()) {
+                // Initialize functions
+                final Map<Integer, FunctionInitializer> initializers = compiler.getFunctionInitializers();
+                if (initializers != null) {
+                    for (final Entry<Integer, FunctionInitializer> entry : initializers.entrySet()) {
+                        final FunctionInitializer initializer = entry.getValue();
+                        initializer.setCode(installedClasses.get(initializer.getClassName()));
+                        compiler.getScriptFunctionData(entry.getKey()).initializeCode(initializer);
+                    }
+                }
+            }
+
+            if (log.isEnabled()) {
+                final StringBuilder sb = new StringBuilder();
+
+                sb.append("Installed class '").
+                    append(rootClass.getSimpleName()).
+                    append('\'').
+                    append(" [").
+                    append(rootClass.getName()).
+                    append(", size=").
+                    append(length).
+                    append(" bytes, ").
+                    append(compiler.getCompileUnits().size()).
+                    append(" compile unit(s)]");
+
+                log.fine(sb.toString());
+            }
+
+            return setStates(fn.setRootClass(null, rootClass), BYTECODE_INSTALLED);
+        }
+
+        @Override
+        public String toString() {
+            return "'Class Installation'";
+        }
+
+     };
+
+    /** pre conditions required for function node to which this transform is to be applied */
     private final EnumSet<CompilationState> pre;
+
+    /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */
     private long startTime;
+
+    /** start time of transform - used for timing, see {@link jdk.nashorn.internal.runtime.Timing} */
     private long endTime;
+
+    /** boolean that is true upon transform completion */
     private boolean isFinished;
 
     private CompilationPhase(final EnumSet<CompilationState> pre) {
         this.pre = pre;
     }
 
-    boolean isApplicable(final FunctionNode functionNode) {
-        return functionNode.hasState(pre);
-    }
-
-    protected FunctionNode begin(final FunctionNode functionNode) {
-        if (pre != null) {
-            // check that everything in pre is present
-            for (final CompilationState state : pre) {
-                assert functionNode.hasState(state);
-            }
-            // check that nothing else is present
-            for (final CompilationState state : CompilationState.values()) {
-                assert !(functionNode.hasState(state) && !pre.contains(state));
-            }
+    private static FunctionNode setStates(final FunctionNode functionNode, final CompilationState state) {
+        if (!AssertsEnabled.assertsEnabled()) {
+            return functionNode;
         }
-
-        startTime = System.currentTimeMillis();
-        return functionNode;
+        return (FunctionNode)functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public Node leaveFunctionNode(final FunctionNode fn) {
+                return fn.setState(lc, state);
+           }
+        });
     }
 
-    protected FunctionNode end(final FunctionNode functionNode) {
-        endTime = System.currentTimeMillis();
-        Timing.accumulateTime(toString(), endTime - startTime);
+    /**
+     * Start a compilation phase
+     * @param compiler
+     * @param functionNode function to compile
+     * @return function node
+     */
+    protected FunctionNode begin(final Compiler compiler, final FunctionNode functionNode) {
+        compiler.getLogger().indent();
+
+        assert pre != null;
+
+        if (!functionNode.hasState(pre)) {
+            final StringBuilder sb = new StringBuilder("Compilation phase ");
+            sb.append(this).
+                append(" is not applicable to ").
+                append(quote(functionNode.getName())).
+                append("\n\tFunctionNode state = ").
+                append(functionNode.getState()).
+                append("\n\tRequired state     = ").
+                append(this.pre);
+
+            throw new CompilationException(sb.toString());
+         }
+
+         startTime = System.nanoTime();
+
+         return functionNode;
+     }
+
+    /**
+     * End a compilation phase
+     * @param compiler the compiler
+     * @param functionNode function node to compile
+     * @return function node
+     */
+    protected FunctionNode end(final Compiler compiler, final FunctionNode functionNode) {
+        compiler.getLogger().unindent();
+        endTime = System.nanoTime();
+        compiler.getScriptEnvironment()._timing.accumulateTime(toString(), endTime - startTime);
 
         isFinished = true;
         return functionNode;
@@ -504,13 +662,26 @@
         return endTime;
     }
 
-    abstract FunctionNode transform(final Compiler compiler, final FunctionNode functionNode) throws CompilationException;
+    abstract FunctionNode transform(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException;
 
-    final FunctionNode apply(final Compiler compiler, final FunctionNode functionNode) throws CompilationException {
-        if (!isApplicable(functionNode)) {
-            throw new CompilationException("compile phase not applicable: " + this + " to " + functionNode.getName() + " state=" + functionNode.getState());
-        }
-        return end(transform(compiler, begin(functionNode)));
+    /**
+     * Apply a transform to a function node, returning the transfored function node. If the transform is not
+     * applicable, an exception is thrown. Every transform requires the function to have a certain number of
+     * states to operate. It can have more states set, but not fewer. The state list, i.e. the constructor
+     * arguments to any of the CompilationPhase enum entries, is a set of REQUIRED states.
+     *
+     * @param compiler     compiler
+     * @param phases       current complete pipeline of which this phase is one
+     * @param functionNode function node to transform
+     *
+     * @return transformed function node
+     *
+     * @throws CompilationException if function node lacks the state required to run the transform on it
+     */
+    final FunctionNode apply(final Compiler compiler, final CompilationPhases phases, final FunctionNode functionNode) throws CompilationException {
+        assert phases.contains(this);
+
+        return end(compiler, transform(compiler, phases, begin(compiler, functionNode)));
     }
 
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CompileUnit.java b/nashorn/src/jdk/nashorn/internal/codegen/CompileUnit.java
index 7312725..2859bf4 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompileUnit.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompileUnit.java
@@ -25,10 +25,13 @@
 
 package jdk.nashorn.internal.codegen;
 
+import java.util.Set;
+import java.util.TreeSet;
+
 /**
  * Used to track split class compilation.
  */
-public class CompileUnit implements Comparable<CompileUnit> {
+public final class CompileUnit implements Comparable<CompileUnit> {
     /** Current class name */
     private final String className;
 
@@ -39,14 +42,14 @@
 
     private Class<?> clazz;
 
-    CompileUnit(final String className, final ClassEmitter classEmitter) {
-        this(className, classEmitter, 0L);
-    }
-
     CompileUnit(final String className, final ClassEmitter classEmitter, final long initialWeight) {
         this.className    = className;
-        this.classEmitter = classEmitter;
         this.weight       = initialWeight;
+        this.classEmitter = classEmitter;
+    }
+
+    static Set<CompileUnit> createCompileUnitSet() {
+        return new TreeSet<>();
     }
 
     /**
@@ -112,13 +115,17 @@
         return className;
     }
 
-    @Override
-    public String toString() {
-        return "[classname=" + className + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']';
+    private static String shortName(final String name) {
+        return name.lastIndexOf('/') == -1 ? name : name.substring(name.lastIndexOf('/') + 1);
     }
 
     @Override
-    public int compareTo(CompileUnit o) {
+    public String toString() {
+        return "[CompileUnit className=" + shortName(className) + " weight=" + weight + '/' + Splitter.SPLIT_THRESHOLD + ']';
+    }
+
+    @Override
+    public int compareTo(final CompileUnit o) {
         return className.compareTo(o.className);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
index e4af587..aa60fdd 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Compiler.java
@@ -27,47 +27,46 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.DEFAULT_SCRIPT_NAME;
-import static jdk.nashorn.internal.codegen.CompilerConstants.LAZY;
 import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.VARARGS;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
 
 import java.io.File;
-import java.lang.reflect.Field;
-import java.security.AccessController;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
+import java.lang.invoke.MethodType;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.EnumSet;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
-import java.util.TreeSet;
+import java.util.TreeMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
 import java.util.logging.Level;
 import jdk.internal.dynalink.support.NameCodec;
 import jdk.nashorn.internal.codegen.ClassEmitter.Flag;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.TemporarySymbols;
+import jdk.nashorn.internal.ir.Optimistic;
 import jdk.nashorn.internal.ir.debug.ClassHistogramElement;
 import jdk.nashorn.internal.ir.debug.ObjectSizeCalculator;
 import jdk.nashorn.internal.runtime.CodeInstaller;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.FunctionInitializer;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.Source;
-import jdk.nashorn.internal.runtime.Timing;
-import jdk.nashorn.internal.runtime.options.Options;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * Responsible for converting JavaScripts to java byte code. Main entry
@@ -75,7 +74,8 @@
  * predefined Code installation policy, given to it at construction time.
  * @see CodeInstaller
  */
-public final class Compiler {
+@Logger(name="compiler")
+public final class Compiler implements Loggable {
 
     /** Name of the scripts package */
     public static final String SCRIPTS_PACKAGE = "jdk/nashorn/internal/scripts";
@@ -83,9 +83,13 @@
     /** Name of the objects package */
     public static final String OBJECTS_PACKAGE = "jdk/nashorn/internal/objects";
 
-    private Source source;
+    private final ScriptEnvironment env;
 
-    private String sourceName;
+    private final Source source;
+
+    private final String sourceName;
+
+    private final boolean optimistic;
 
     private final Map<String, byte[]> bytecode;
 
@@ -93,21 +97,189 @@
 
     private final ConstantData constantData;
 
-    private final CompilationSequence sequence;
-
-    private final ScriptEnvironment env;
-
-    private String scriptName;
-
-    private boolean strict;
-
     private final CodeInstaller<ScriptEnvironment> installer;
 
-    private final TemporarySymbols temporarySymbols = new TemporarySymbols();
-
     /** logger for compiler, trampolines, splits and related code generation events
      *  that affect classes */
-    public static final DebugLogger LOG = new DebugLogger("compiler");
+    private final DebugLogger log;
+
+    private final Context context;
+
+    private final TypeMap types;
+
+    // Runtime scope in effect at the time of the compilation. Used to evaluate types of expressions and prevent overly
+    // optimistic assumptions (which will lead to unnecessary deoptimizing recompilations).
+    private final TypeEvaluator typeEvaluator;
+
+    private final boolean strict;
+
+    private final boolean onDemand;
+
+    /**
+     * If this is a recompilation, this is how we pass in the invalidations, e.g. programPoint=17, Type == int means
+     * that using whatever was at program point 17 as an int failed.
+     */
+    private final Map<Integer, Type> invalidatedProgramPoints;
+
+    /**
+     * Descriptor of the location where we write the type information after compilation.
+     */
+    private final Object typeInformationFile;
+
+    /**
+     * Compile unit name of first compile unit - this prefix will be used for all
+     * classes that a compilation generates.
+     */
+    private final String firstCompileUnitName;
+
+    /**
+     * Contains the program point that should be used as the continuation entry point, as well as all previous
+     * continuation entry points executed as part of a single logical invocation of the function. In practical terms, if
+     * we execute a rest-of method from the program point 17, but then we hit deoptimization again during it at program
+     * point 42, and execute a rest-of method from the program point 42, and then we hit deoptimization again at program
+     * point 57 and are compiling a rest-of method for it, the values in the array will be [57, 42, 17]. This is only
+     * set when compiling a rest-of method. If this method is a rest-of for a non-rest-of method, the array will have
+     * one element. If it is a rest-of for a rest-of, the array will have two elements, and so on.
+     */
+    private final int[] continuationEntryPoints;
+
+    /**
+     * ScriptFunction data for what is being compile, where applicable.
+     * TODO: make this immutable, propagate it through the CompilationPhases
+     */
+    private RecompilableScriptFunctionData compiledFunction;
+
+    /**
+     * Compilation phases that a compilation goes through
+     */
+    public static class CompilationPhases implements Iterable<CompilationPhase> {
+
+        /** Singleton that describes a standard eager compilation - this includes code installation */
+        public final static CompilationPhases COMPILE_ALL = new CompilationPhases(
+                "Compile all",
+                new CompilationPhase[] {
+                        CompilationPhase.CONSTANT_FOLDING_PHASE,
+                        CompilationPhase.LOWERING_PHASE,
+                        CompilationPhase.PROGRAM_POINT_PHASE,
+                        CompilationPhase.TRANSFORM_BUILTINS_PHASE,
+                        CompilationPhase.SPLITTING_PHASE,
+                        CompilationPhase.SYMBOL_ASSIGNMENT_PHASE,
+                        CompilationPhase.SCOPE_DEPTH_COMPUTATION_PHASE,
+                        CompilationPhase.OPTIMISTIC_TYPE_ASSIGNMENT_PHASE,
+                        CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE,
+                        CompilationPhase.BYTECODE_GENERATION_PHASE,
+                        CompilationPhase.INSTALL_PHASE
+                });
+
+        /** Compile all for a rest of method */
+        public final static CompilationPhases COMPILE_ALL_RESTOF =
+                COMPILE_ALL.setDescription("Compile all, rest of").addAfter(CompilationPhase.LOCAL_VARIABLE_TYPE_CALCULATION_PHASE, CompilationPhase.REUSE_COMPILE_UNITS_PHASE);
+
+        /** Singleton that describes a standard eager compilation, but no installation, for example used by --compile-only */
+        public final static CompilationPhases COMPILE_ALL_NO_INSTALL =
+                COMPILE_ALL.
+                removeLast().
+                setDescription("Compile without install");
+
+        /** Singleton that describes compilation up to the CodeGenerator, but not actually generating code */
+        public final static CompilationPhases COMPILE_UPTO_BYTECODE =
+                COMPILE_ALL.
+                removeLast().
+                removeLast().
+                setDescription("Compile upto bytecode");
+
+        /**
+         * Singleton that describes back end of method generation, given that we have generated the normal
+         * method up to CodeGenerator as in {@link CompilationPhases#COMPILE_UPTO_BYTECODE}
+         */
+        public final static CompilationPhases COMPILE_FROM_BYTECODE = new CompilationPhases(
+                "Generate bytecode and install",
+                new CompilationPhase[] {
+                        CompilationPhase.BYTECODE_GENERATION_PHASE,
+                        CompilationPhase.INSTALL_PHASE
+                });
+
+        /**
+         * Singleton that describes restOf method generation, given that we have generated the normal
+         * method up to CodeGenerator as in {@link CompilationPhases#COMPILE_UPTO_BYTECODE}
+         */
+        public final static CompilationPhases COMPILE_FROM_BYTECODE_RESTOF =
+                COMPILE_FROM_BYTECODE.
+                addFirst(CompilationPhase.REUSE_COMPILE_UNITS_PHASE).
+                setDescription("Generate bytecode and install - RestOf method");
+
+        private final List<CompilationPhase> phases;
+
+        private final String desc;
+
+        private CompilationPhases(final String desc, final CompilationPhase... phases) {
+            this.desc = desc;
+
+            final List<CompilationPhase> newPhases = new LinkedList<>();
+            newPhases.addAll(Arrays.asList(phases));
+            this.phases = Collections.unmodifiableList(newPhases);
+        }
+
+        @Override
+        public String toString() {
+            return "'" + desc + "' " + phases.toString();
+        }
+
+        private CompilationPhases setDescription(final String desc) {
+            return new CompilationPhases(desc, phases.toArray(new CompilationPhase[phases.size()]));
+        }
+
+        private CompilationPhases removeLast() {
+            final LinkedList<CompilationPhase> list = new LinkedList<>(phases);
+            list.removeLast();
+            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
+        }
+
+        private CompilationPhases addFirst(final CompilationPhase phase) {
+            if (phases.contains(phase)) {
+                return this;
+            }
+            final LinkedList<CompilationPhase> list = new LinkedList<>(phases);
+            list.addFirst(phase);
+            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
+        }
+
+        private CompilationPhases addAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
+            final LinkedList<CompilationPhase> list = new LinkedList<>();
+            for (final CompilationPhase p : phases) {
+                list.add(p);
+                if (p == phase) {
+                    list.add(newPhase);
+                }
+            }
+            return new CompilationPhases(desc, list.toArray(new CompilationPhase[list.size()]));
+        }
+
+        boolean contains(final CompilationPhase phase) {
+            return phases.contains(phase);
+        }
+
+        @Override
+        public Iterator<CompilationPhase> iterator() {
+            return phases.iterator();
+        }
+
+        boolean isRestOfCompilation() {
+            return this == COMPILE_ALL_RESTOF || this == COMPILE_FROM_BYTECODE_RESTOF;
+        }
+
+        String getDesc() {
+            return desc;
+        }
+
+        String toString(final String prefix) {
+            final StringBuilder sb = new StringBuilder();
+            for (final CompilationPhase phase : phases) {
+                sb.append(prefix).append(phase).append('\n');
+            }
+            return sb.toString();
+        }
+    }
 
     /**
      * This array contains names that need to be reserved at the start
@@ -124,374 +296,287 @@
         ARGUMENTS.symbolName()
     };
 
-    /**
-     * This class makes it possible to do your own compilation sequence
-     * from the code generation package. There are predefined compilation
-     * sequences already
-     */
-    @SuppressWarnings("serial")
-    static class CompilationSequence extends LinkedList<CompilationPhase> {
+    // per instance
+    private final int compilationId = COMPILATION_ID.getAndIncrement();
 
-        CompilationSequence(final CompilationPhase... phases) {
-            super(Arrays.asList(phases));
-        }
+    // per instance
+    private final AtomicInteger nextCompileUnitId = new AtomicInteger(0);
 
-        CompilationSequence(final CompilationSequence sequence) {
-            this(sequence.toArray(new CompilationPhase[sequence.size()]));
-        }
-
-        CompilationSequence insertAfter(final CompilationPhase phase, final CompilationPhase newPhase) {
-            final CompilationSequence newSeq = new CompilationSequence();
-            for (final CompilationPhase elem : this) {
-                newSeq.add(phase);
-                if (elem.equals(phase)) {
-                    newSeq.add(newPhase);
-                }
-            }
-            assert newSeq.contains(newPhase);
-            return newSeq;
-        }
-
-        CompilationSequence insertBefore(final CompilationPhase phase, final CompilationPhase newPhase) {
-            final CompilationSequence newSeq = new CompilationSequence();
-            for (final CompilationPhase elem : this) {
-                if (elem.equals(phase)) {
-                    newSeq.add(newPhase);
-                }
-                newSeq.add(phase);
-            }
-            assert newSeq.contains(newPhase);
-            return newSeq;
-        }
-
-        CompilationSequence insertFirst(final CompilationPhase phase) {
-            final CompilationSequence newSeq = new CompilationSequence(this);
-            newSeq.addFirst(phase);
-            return newSeq;
-        }
-
-        CompilationSequence insertLast(final CompilationPhase phase) {
-            final CompilationSequence newSeq = new CompilationSequence(this);
-            newSeq.addLast(phase);
-            return newSeq;
-        }
-    }
+    private static final AtomicInteger COMPILATION_ID = new AtomicInteger(0);
 
     /**
-     * Environment information known to the compile, e.g. params
+     * Constructor
+     *
+     * @param context   context
+     * @param env       script environment
+     * @param installer code installer
+     * @param source    source to compile
+     * @param isStrict  is this a strict compilation
      */
-    public static class Hints {
-        private final Type[] paramTypes;
-
-        /** singleton empty hints */
-        public static final Hints EMPTY = new Hints();
-
-        private Hints() {
-            this.paramTypes = null;
-        }
-
-        /**
-         * Constructor
-         * @param paramTypes known parameter types for this callsite
-         */
-        public Hints(final Type[] paramTypes) {
-            this.paramTypes = paramTypes;
-        }
-
-        /**
-         * Get the parameter type for this parameter position, or
-         * null if now known
-         * @param pos position
-         * @return parameter type for this callsite if known
-         */
-        public Type getParameterType(final int pos) {
-            if (paramTypes != null && pos < paramTypes.length) {
-                return paramTypes[pos];
-            }
-            return null;
-        }
-    }
-
-    /**
-     * Standard (non-lazy) compilation, that basically will take an entire script
-     * and JIT it at once. This can lead to long startup time and fewer type
-     * specializations
-     */
-    final static CompilationSequence SEQUENCE_EAGER = new CompilationSequence(
-        CompilationPhase.CONSTANT_FOLDING_PHASE,
-        CompilationPhase.LOWERING_PHASE,
-        CompilationPhase.ATTRIBUTION_PHASE,
-        CompilationPhase.RANGE_ANALYSIS_PHASE,
-        CompilationPhase.SPLITTING_PHASE,
-        CompilationPhase.TYPE_FINALIZATION_PHASE,
-        CompilationPhase.BYTECODE_GENERATION_PHASE);
-
-    final static CompilationSequence SEQUENCE_LAZY =
-        SEQUENCE_EAGER.insertFirst(CompilationPhase.LAZY_INITIALIZATION_PHASE);
-
-    private static CompilationSequence sequence(final boolean lazy) {
-        return lazy ? SEQUENCE_LAZY : SEQUENCE_EAGER;
-    }
-
-    boolean isLazy() {
-        return sequence == SEQUENCE_LAZY;
-    }
-
-    private static String lazyTag(final FunctionNode functionNode) {
-        if (functionNode.isLazy()) {
-            return '$' + LAZY.symbolName() + '$' + functionNode.getName();
-        }
-        return "";
+    public Compiler(
+            final Context context,
+            final ScriptEnvironment env,
+            final CodeInstaller<ScriptEnvironment> installer,
+            final Source source,
+            final boolean isStrict) {
+        this(context, env, installer, source, isStrict, false, null, null, null, null, null, null);
     }
 
     /**
      * Constructor
      *
-     * @param env          script environment
-     * @param installer    code installer
-     * @param sequence     {@link Compiler.CompilationSequence} of {@link CompilationPhase}s to apply as this compilation
-     * @param strict       should this compilation use strict mode semantics
+     * @param context                  context
+     * @param env                      script environment
+     * @param installer                code installer
+     * @param source                   source to compile
+     * @param isStrict                 is this a strict compilation
+     * @param isOnDemand               is this an on demand compilation
+     * @param compiledFunction         compiled function, if any
+     * @param types                    parameter and return value type information, if any is known
+     * @param invalidatedProgramPoints invalidated program points for recompilation
+     * @param typeInformationFile      descriptor of the location where type information is persisted
+     * @param continuationEntryPoints  continuation entry points for restof method
+     * @param runtimeScope             runtime scope for recompilation type lookup in {@code TypeEvaluator}
      */
-    //TODO support an array of FunctionNodes for batch lazy compilation
-    Compiler(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final CompilationSequence sequence, final boolean strict) {
-        this.env           = env;
-        this.sequence      = sequence;
-        this.installer     = installer;
-        this.constantData  = new ConstantData();
-        this.compileUnits  = new TreeSet<>();
-        this.bytecode      = new LinkedHashMap<>();
+    public Compiler(
+            final Context context,
+            final ScriptEnvironment env,
+            final CodeInstaller<ScriptEnvironment> installer,
+            final Source source,
+            final boolean isStrict,
+            final boolean isOnDemand,
+            final RecompilableScriptFunctionData compiledFunction,
+            final TypeMap types,
+            final Map<Integer, Type> invalidatedProgramPoints,
+            final Object typeInformationFile,
+            final int[] continuationEntryPoints,
+            final ScriptObject runtimeScope) {
+        this.context                  = context;
+        this.env                      = env;
+        this.installer                = installer;
+        this.constantData             = new ConstantData();
+        this.compileUnits             = CompileUnit.createCompileUnitSet();
+        this.bytecode                 = new LinkedHashMap<>();
+        this.log                      = initLogger(context);
+        this.source                   = source;
+        this.sourceName               = FunctionNode.getSourceName(source);
+        this.onDemand                 = isOnDemand;
+        this.compiledFunction         = compiledFunction;
+        this.types                    = types;
+        this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new HashMap<Integer, Type>() : invalidatedProgramPoints;
+        this.typeInformationFile      = typeInformationFile;
+        this.continuationEntryPoints  = continuationEntryPoints == null ? null: continuationEntryPoints.clone();
+        this.typeEvaluator            = new TypeEvaluator(this, runtimeScope);
+        this.firstCompileUnitName     = firstCompileUnitName();
+        this.strict                   = isStrict;
+
+        this.optimistic = env._optimistic_types;
     }
 
-    private void initCompiler(final FunctionNode functionNode) {
-        this.strict        = strict || functionNode.isStrict();
-        final StringBuilder sb = new StringBuilder();
-        sb.append(functionNode.uniqueName(DEFAULT_SCRIPT_NAME.symbolName() + lazyTag(functionNode))).
-                append('$').
-                append(safeSourceName(functionNode.getSource()));
-        this.source = functionNode.getSource();
-        this.sourceName = functionNode.getSourceName();
-        this.scriptName = sb.toString();
+    private static String safeSourceName(final ScriptEnvironment env, final CodeInstaller<ScriptEnvironment> installer, final Source source) {
+        String baseName = new File(source.getName()).getName();
+
+        final int index = baseName.lastIndexOf(".js");
+        if (index != -1) {
+            baseName = baseName.substring(0, index);
+        }
+
+        baseName = baseName.replace('.', '_').replace('-', '_');
+        if (!env._loader_per_compile) {
+            baseName = baseName + installer.getUniqueScriptId();
+        }
+
+        final String mangled = NameCodec.encode(baseName);
+        return mangled != null ? mangled : baseName;
     }
 
-    /**
-     * Constructor
-     *
-     * @param installer    code installer
-     * @param strict       should this compilation use strict mode semantics
-     */
-    public Compiler(final CodeInstaller<ScriptEnvironment> installer, final boolean strict) {
-        this(installer.getOwner(), installer, sequence(installer.getOwner()._lazy_compilation), strict);
+    private String firstCompileUnitName() {
+        final StringBuilder sb = new StringBuilder(SCRIPTS_PACKAGE).
+                append('/').
+                append(CompilerConstants.DEFAULT_SCRIPT_NAME.symbolName()).
+                append('$');
+
+        if (isOnDemandCompilation()) {
+            sb.append(RecompilableScriptFunctionData.RECOMPILATION_PREFIX);
+        }
+
+        if (compilationId > 0) {
+            sb.append(compilationId).append('$');
+        }
+
+        if (types != null && compiledFunction.getFunctionNodeId() > 0) {
+            sb.append(compiledFunction.getFunctionNodeId());
+            final Type[] paramTypes = types.getParameterTypes(compiledFunction.getFunctionNodeId());
+            for (final Type t : paramTypes) {
+                sb.append(Type.getShortSignatureDescriptor(t));
+            }
+            sb.append('$');
+        }
+
+        sb.append(Compiler.safeSourceName(env, installer, source));
+
+        return sb.toString();
     }
 
-    /**
-     * Constructor - compilation will use the same strict semantics as in script environment
-     *
-     * @param installer    code installer
-     */
-    public Compiler(final CodeInstaller<ScriptEnvironment> installer) {
-        this(installer.getOwner(), installer, sequence(installer.getOwner()._lazy_compilation), installer.getOwner()._strict);
+    void declareLocalSymbol(final String symbolName) {
+        typeEvaluator.declareLocalSymbol(symbolName);
     }
 
-    /**
-     * Constructor - compilation needs no installer, but uses a script environment
-     * Used in "compile only" scenarios
-     * @param env a script environment
-     */
-    public Compiler(final ScriptEnvironment env) {
-        this(env, null, sequence(env._lazy_compilation), env._strict);
+    void setData(final RecompilableScriptFunctionData data) {
+        assert this.compiledFunction == null : data;
+        this.compiledFunction = data;
     }
 
-    private static void printMemoryUsage(final String phaseName, final FunctionNode functionNode) {
-        LOG.info(phaseName + " finished. Doing IR size calculation...");
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
 
-        final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
-        osc.calculateObjectSize(functionNode);
-
-        final List<ClassHistogramElement> list = osc.getClassHistogram();
-
-        final StringBuilder sb = new StringBuilder();
-        final long totalSize = osc.calculateObjectSize(functionNode);
-        sb.append(phaseName).append(" Total size = ").append(totalSize / 1024 / 1024).append("MB");
-        LOG.info(sb);
-
-        Collections.sort(list, new Comparator<ClassHistogramElement>() {
+    @Override
+    public DebugLogger initLogger(final Context ctxt) {
+        return ctxt.getLogger(this.getClass(), new Consumer<DebugLogger>() {
             @Override
-            public int compare(ClassHistogramElement o1, ClassHistogramElement o2) {
-                final long diff = o1.getBytes() - o2.getBytes();
-                if (diff < 0) {
-                    return 1;
-                } else if (diff > 0) {
-                    return -1;
-                } else {
-                    return 0;
+            public void accept(final DebugLogger newLogger) {
+                if (!Compiler.this.getScriptEnvironment()._lazy_compilation) {
+                    newLogger.warning("WARNING: Running with lazy compilation switched off. This is not a default setting.");
                 }
             }
         });
-        for (final ClassHistogramElement e : list) {
-            final String line = String.format("    %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
-            LOG.info(line);
-            if (e.getBytes() < totalSize / 200) {
-                LOG.info("    ...");
-                break; // never mind, so little memory anyway
-            }
+    }
+
+    ScriptEnvironment getScriptEnvironment() {
+        return env;
+    }
+
+    boolean isOnDemandCompilation() {
+        return onDemand;
+    }
+
+    boolean useOptimisticTypes() {
+        return optimistic;
+    }
+
+    Context getContext() {
+        return context;
+    }
+
+    Type getOptimisticType(final Optimistic node) {
+        return typeEvaluator.getOptimisticType(node);
+    }
+
+    void addInvalidatedProgramPoint(final int programPoint, final Type type) {
+        invalidatedProgramPoints.put(programPoint, type);
+    }
+
+
+    /**
+     * Returns a copy of this compiler's current mapping of invalidated optimistic program points to their types. The
+     * copy is not live with regard to changes in state in this compiler instance, and is mutable.
+     * @return a copy of this compiler's current mapping of invalidated optimistic program points to their types.
+     */
+    public Map<Integer, Type> getInvalidatedProgramPoints() {
+        return invalidatedProgramPoints == null ? null : new TreeMap<>(invalidatedProgramPoints);
+    }
+
+    TypeMap getTypeMap() {
+        return types;
+    }
+
+    MethodType getCallSiteType(final FunctionNode fn) {
+        if (types == null || !isOnDemandCompilation()) {
+            return null;
         }
+        return types.getCallSiteType(fn);
+    }
+
+    Type getParamType(final FunctionNode fn, final int pos) {
+        return types == null ? null : types.get(fn, pos);
     }
 
     /**
-     * Execute the compilation this Compiler was created with
-     * @param functionNode function node to compile from its current state
-     * @throws CompilationException if something goes wrong
-     * @return function node that results from code transforms
-     */
-    public FunctionNode compile(final FunctionNode functionNode) throws CompilationException {
-        FunctionNode newFunctionNode = functionNode;
+     * Do a compilation job
+     *
+     * @param functionNode function node to compile
+     * @param phases phases of compilation transforms to apply to function
 
-        initCompiler(newFunctionNode); //TODO move this state into functionnode?
+     * @return transformed function
+     *
+     * @throws CompilationException if error occurs during compilation
+     */
+    public FunctionNode compile(final FunctionNode functionNode, final CompilationPhases phases) throws CompilationException {
+
+        log.finest("Starting compile job for ", DebugLogger.quote(functionNode.getName()), " phases=", quote(phases.getDesc()));
+        log.indent();
+
+        final String name = DebugLogger.quote(functionNode.getName());
+
+        FunctionNode newFunctionNode = functionNode;
 
         for (final String reservedName : RESERVED_NAMES) {
             newFunctionNode.uniqueName(reservedName);
         }
 
-        final boolean fine = !LOG.levelAbove(Level.FINE);
-        final boolean info = !LOG.levelAbove(Level.INFO);
+        final boolean info = log.levelFinerThanOrEqual(Level.INFO);
+
+        final DebugLogger timeLogger = env.isTimingEnabled() ? env._timing.getLogger() : null;
 
         long time = 0L;
 
-        for (final CompilationPhase phase : sequence) {
-            newFunctionNode = phase.apply(this, newFunctionNode);
+        for (final CompilationPhase phase : phases) {
+            log.fine(phase, " starting for ", quote(name));
+            newFunctionNode = phase.apply(this, phases, newFunctionNode);
+            log.fine(phase, " done for function ", quote(name));
 
             if (env._print_mem_usage) {
-                printMemoryUsage(phase.toString(), newFunctionNode);
+                printMemoryUsage(functionNode, phase.toString());
             }
 
-            final long duration = Timing.isEnabled() ? (phase.getEndTime() - phase.getStartTime()) : 0L;
-            time += duration;
-
-            if (fine) {
-                final StringBuilder sb = new StringBuilder();
-
-                sb.append(phase.toString()).
-                    append(" done for function '").
-                    append(newFunctionNode.getName()).
-                    append('\'');
-
-                if (duration > 0L) {
-                    sb.append(" in ").
-                        append(duration).
-                        append(" ms ");
-                }
-
-                LOG.fine(sb);
-            }
+            time += (env.isTimingEnabled() ? phase.getEndTime() - phase.getStartTime() : 0L);
         }
 
+        if (typeInformationFile != null && !phases.isRestOfCompilation()) {
+            OptimisticTypesPersistence.store(typeInformationFile, invalidatedProgramPoints);
+        }
+
+        log.unindent();
+
         if (info) {
             final StringBuilder sb = new StringBuilder();
-            sb.append("Compile job for '").
-                append(newFunctionNode.getSource()).
-                append(':').
-                append(newFunctionNode.getName()).
-                append("' finished");
-
-            if (time > 0L) {
-                sb.append(" in ").
-                    append(time).
-                    append(" ms");
+            sb.append("Compile job for ").append(newFunctionNode.getSource()).append(':').append(quote(newFunctionNode.getName())).append(" finished");
+            if (time > 0L && timeLogger != null) {
+                assert env.isTimingEnabled();
+                sb.append(" in ").append(time).append(" ms");
             }
-
-            LOG.info(sb);
+            log.info(sb);
         }
 
         return newFunctionNode;
     }
 
-    private Class<?> install(final String className, final byte[] code, final Object[] constants) {
-        return installer.install(className, code, source, constants);
+    Source getSource() {
+        return source;
+    }
+
+    Map<String, byte[]> getBytecode() {
+        return Collections.unmodifiableMap(bytecode);
     }
 
     /**
-     * Install compiled classes into a given loader
-     * @param functionNode function node to install - must be in {@link CompilationState#EMITTED} state
-     * @return root script class - if there are several compile units they will also be installed
+     * Reset bytecode cache for compiler reuse.
      */
-    public Class<?> install(final FunctionNode functionNode) {
-        final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
+    void clearBytecode() {
+        bytecode.clear();
+    }
 
-        assert functionNode.hasState(CompilationState.EMITTED) : functionNode.getName() + " has no bytecode and cannot be installed";
-
-        final Map<String, Class<?>> installedClasses = new HashMap<>();
-        final Object[] constants = getConstantData().toArray();
-
-        final String   rootClassName = firstCompileUnitName();
-        final byte[]   rootByteCode  = bytecode.get(rootClassName);
-        final Class<?> rootClass     = install(rootClassName, rootByteCode, constants);
-
-        if (!isLazy()) {
-            installer.storeCompiledScript(source, rootClassName, bytecode, constants);
-        }
-
-        int length = rootByteCode.length;
-
-        installedClasses.put(rootClassName, rootClass);
-
-        for (final Entry<String, byte[]> entry : bytecode.entrySet()) {
-            final String className = entry.getKey();
-            if (className.equals(rootClassName)) {
-                continue;
-            }
-            final byte[] code = entry.getValue();
-            length += code.length;
-
-            installedClasses.put(className, install(className, code, constants));
-        }
-
-        for (final CompileUnit unit : compileUnits) {
-            unit.setCode(installedClasses.get(unit.getUnitClassName()));
-        }
-
-        final StringBuilder sb;
-        if (LOG.isEnabled()) {
-            sb = new StringBuilder();
-            sb.append("Installed class '").
-                append(rootClass.getSimpleName()).
-                append('\'').
-                append(" bytes=").
-                append(length).
-                append('.');
-            if (bytecode.size() > 1) {
-                sb.append(' ').append(bytecode.size()).append(" compile units.");
-            }
-        } else {
-            sb = null;
-        }
-
-        if (Timing.isEnabled()) {
-            final long duration = System.currentTimeMillis() - t0;
-            Timing.accumulateTime("[Code Installation]", duration);
-            if (sb != null) {
-                sb.append(" Install time: ").append(duration).append(" ms");
-            }
-        }
-
-        if (sb != null) {
-            LOG.fine(sb);
-        }
-
-        return rootClass;
+    CompileUnit getFirstCompileUnit() {
+        assert !compileUnits.isEmpty();
+        return compileUnits.iterator().next();
     }
 
     Set<CompileUnit> getCompileUnits() {
         return compileUnits;
     }
 
-    boolean getStrictMode() {
-        return strict;
-    }
-
-    void setStrictMode(final boolean strict) {
-        this.strict = strict;
-    }
-
     ConstantData getConstantData() {
         return constantData;
     }
@@ -500,64 +585,76 @@
         return installer;
     }
 
-    TemporarySymbols getTemporarySymbols() {
-        return temporarySymbols;
-    }
-
     void addClass(final String name, final byte[] code) {
         bytecode.put(name, code);
     }
 
-    ScriptEnvironment getEnv() {
-        return this.env;
-    }
-
-    private String safeSourceName(final Source src) {
-        String baseName = new File(src.getName()).getName();
-
-        final int index = baseName.lastIndexOf(".js");
-        if (index != -1) {
-            baseName = baseName.substring(0, index);
+    String nextCompileUnitName() {
+        final StringBuilder sb = new StringBuilder(firstCompileUnitName);
+        final int cuid = nextCompileUnitId.getAndIncrement();
+        if (cuid > 0) {
+            sb.append("$cu").append(cuid);
         }
 
-        baseName = baseName.replace('.', '_').replace('-', '_');
-        if (! env._loader_per_compile) {
-            baseName = baseName + installer.getUniqueScriptId();
+        return sb.toString();
+    }
+
+    Map<Integer, FunctionInitializer> functionInitializers;
+
+    void addFunctionInitializer(final RecompilableScriptFunctionData functionData, final FunctionNode functionNode) {
+        if (functionInitializers == null) {
+            functionInitializers = new HashMap<>();
         }
-        final String mangled = NameCodec.encode(baseName);
-
-        return mangled != null ? mangled : baseName;
+        if (!functionInitializers.containsKey(functionData)) {
+            functionInitializers.put(functionData.getFunctionNodeId(), new FunctionInitializer(functionNode));
+        }
     }
 
-    private int nextCompileUnitIndex() {
-        return compileUnits.size() + 1;
+    Map<Integer, FunctionInitializer> getFunctionInitializers() {
+        return functionInitializers;
     }
 
-    String firstCompileUnitName() {
-        return SCRIPTS_PACKAGE + '/' + scriptName;
+    /**
+     * Persist current compilation with the given {@code cacheKey}.
+     * @param cacheKey cache key
+     * @param functionNode function node
+     */
+    public void persistClassInfo(final String cacheKey, final FunctionNode functionNode) {
+        if (cacheKey != null && env._persistent_cache) {
+            Map<Integer, FunctionInitializer> initializers;
+            // If this is an on-demand compilation create a function initializer for the function being compiled.
+            // Otherwise use function initializer map generated by codegen.
+            if (functionInitializers == null) {
+                initializers = new HashMap<>();
+                final FunctionInitializer initializer = new FunctionInitializer(functionNode, getInvalidatedProgramPoints());
+                initializers.put(functionNode.getId(), initializer);
+            } else {
+                initializers = functionInitializers;
+            }
+            final String mainClassName = getFirstCompileUnit().getUnitClassName();
+            installer.storeScript(cacheKey, source, mainClassName, bytecode, initializers, constantData.toArray(), compilationId);
+        }
     }
 
-    private String nextCompileUnitName() {
-        return firstCompileUnitName() + '$' + nextCompileUnitIndex();
+    /**
+     * Make sure the next compilation id is greater than {@code value}.
+     * @param value compilation id value
+     */
+    public static void updateCompilationId(final int value) {
+        if (value >= COMPILATION_ID.get()) {
+            COMPILATION_ID.set(value + 1);
+        }
     }
 
     CompileUnit addCompileUnit(final long initialWeight) {
-        return addCompileUnit(nextCompileUnitName(), initialWeight);
-    }
-
-    CompileUnit addCompileUnit(final String unitClassName) {
-        return addCompileUnit(unitClassName, 0L);
-    }
-
-    private CompileUnit addCompileUnit(final String unitClassName, final long initialWeight) {
-        final CompileUnit compileUnit = initCompileUnit(unitClassName, initialWeight);
+        final CompileUnit compileUnit = createCompileUnit(initialWeight);
         compileUnits.add(compileUnit);
-        LOG.fine("Added compile unit ", compileUnit);
+        log.fine("Added compile unit ", compileUnit);
         return compileUnit;
     }
 
-    private CompileUnit initCompileUnit(final String unitClassName, final long initialWeight) {
-        final ClassEmitter classEmitter = new ClassEmitter(env, sourceName, unitClassName, strict);
+    CompileUnit createCompileUnit(final String unitClassName, final long initialWeight) {
+        final ClassEmitter classEmitter = new ClassEmitter(context, sourceName, unitClassName, isStrict());
         final CompileUnit  compileUnit  = new CompileUnit(unitClassName, classEmitter, initialWeight);
 
         classEmitter.begin();
@@ -572,6 +669,19 @@
         return compileUnit;
     }
 
+    private CompileUnit createCompileUnit(final long initialWeight) {
+        return createCompileUnit(nextCompileUnitName(), initialWeight);
+    }
+
+    boolean isStrict() {
+        return strict;
+    }
+
+    void replaceCompileUnits(final Set<CompileUnit> newUnits) {
+        compileUnits.clear();
+        compileUnits.addAll(newUnits);
+    }
+
     CompileUnit findUnit(final long weight) {
         for (final CompileUnit unit : compileUnits) {
             if (unit.canHold(weight)) {
@@ -593,22 +703,69 @@
         return name.replace('/', '.');
     }
 
-    /**
-     * Should we use integers for arithmetic operations as well?
-     * TODO: We currently generate no overflow checks so this is
-     * disabled
-     *
-     * @return true if arithmetic operations should not widen integer
-     *   operands by default.
-     */
-    static boolean shouldUseIntegerArithmetic() {
-        return USE_INT_ARITH;
+    RecompilableScriptFunctionData getProgram() {
+        if (compiledFunction == null) {
+            return null;
+        }
+        return compiledFunction.getProgram();
     }
 
-    private static final boolean USE_INT_ARITH;
+    RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
+        return compiledFunction == null ? null : compiledFunction.getScriptFunctionData(functionId);
+    }
 
-    static {
-        USE_INT_ARITH  =  Options.getBooleanProperty("nashorn.compiler.intarithmetic");
-        assert !USE_INT_ARITH : "Integer arithmetic is not enabled";
+    boolean isGlobalSymbol(final FunctionNode fn, final String name) {
+        return getScriptFunctionData(fn.getId()).isGlobalSymbol(fn, name);
+    }
+
+    int[] getContinuationEntryPoints() {
+        return continuationEntryPoints;
+    }
+
+    Type getInvalidatedProgramPointType(final int programPoint) {
+        return invalidatedProgramPoints.get(programPoint);
+    }
+
+    private void printMemoryUsage(final FunctionNode functionNode, final String phaseName) {
+        if (!log.isEnabled()) {
+            return;
+        }
+
+        log.info(phaseName, "finished. Doing IR size calculation...");
+
+        final ObjectSizeCalculator osc = new ObjectSizeCalculator(ObjectSizeCalculator.getEffectiveMemoryLayoutSpecification());
+        osc.calculateObjectSize(functionNode);
+
+        final List<ClassHistogramElement> list      = osc.getClassHistogram();
+        final StringBuilder               sb        = new StringBuilder();
+        final long                        totalSize = osc.calculateObjectSize(functionNode);
+
+        sb.append(phaseName).
+            append(" Total size = ").
+            append(totalSize / 1024 / 1024).
+            append("MB");
+        log.info(sb);
+
+        Collections.sort(list, new Comparator<ClassHistogramElement>() {
+            @Override
+            public int compare(final ClassHistogramElement o1, final ClassHistogramElement o2) {
+                final long diff = o1.getBytes() - o2.getBytes();
+                if (diff < 0) {
+                    return 1;
+                } else if (diff > 0) {
+                    return -1;
+                } else {
+                    return 0;
+                }
+            }
+        });
+        for (final ClassHistogramElement e : list) {
+            final String line = String.format("    %-48s %10d bytes (%8d instances)", e.getClazz(), e.getBytes(), e.getInstances());
+            log.info(line);
+            if (e.getBytes() < totalSize / 200) {
+                log.info("    ...");
+                break; // never mind, so little memory anyway
+            }
+        }
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
index 16f08b8..e84c9f0 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/CompilerConstants.java
@@ -29,7 +29,11 @@
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.MethodVisitor;
+import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -41,7 +45,6 @@
  */
 
 public enum CompilerConstants {
-
     /** the __FILE__ variable */
     __FILE__,
 
@@ -51,9 +54,6 @@
     /** the __LINE__ variable */
     __LINE__,
 
-    /** lazy prefix for classes of jitted methods */
-    LAZY("Lazy"),
-
     /** constructor name */
     INIT("<init>"),
 
@@ -78,15 +78,18 @@
     /** function prefix for anonymous functions */
     ANON_FUNCTION_PREFIX("L:"),
 
-    /** method name for Java method that is script entry point */
-    RUN_SCRIPT("runScript"),
+    /** method name for Java method that is the program entry point */
+    PROGRAM(":program"),
+
+    /** method name for Java method that creates the script function for the program */
+    CREATE_PROGRAM_FUNCTION(":createProgramFunction"),
 
     /**
      * "this" name symbol for a parameter representing ECMAScript "this" in static methods that are compiled
      * representations of ECMAScript functions. It is not assigned a slot, as its position in the method signature is
      * dependent on other factors (most notably, callee can precede it).
      */
-    THIS("this"),
+    THIS("this", Object.class),
 
     /** this debugger symbol */
     THIS_DEBUGGER(":this"),
@@ -110,13 +113,16 @@
     /** the internal arguments object, when necessary (not visible to scripts, can't be reassigned). */
     ARGUMENTS(":arguments", ScriptObject.class),
 
+    /** prefix for apply-to-call exploded arguments */
+    EXPLODED_ARGUMENT_PREFIX(":xarg"),
+
     /** prefix for iterators for for (x in ...) */
     ITERATOR_PREFIX(":i", Iterator.class),
 
     /** prefix for tag variable used for switch evaluation */
     SWITCH_TAG_PREFIX(":s"),
 
-    /** prefix for all exceptions */
+    /** prefix for JVM exceptions */
     EXCEPTION_PREFIX(":e", Throwable.class),
 
     /** prefix for quick slots generated in Store */
@@ -161,7 +167,7 @@
     /** get map */
     GET_MAP(":getMap"),
 
-    /** get map */
+    /** set map */
     SET_MAP(":setMap"),
 
     /** get array prefix */
@@ -170,10 +176,22 @@
     /** get array suffix */
     GET_ARRAY_SUFFIX("$array");
 
+    /** To save memory - intern the compiler constant symbol names, as they are frequently reused */
+    static {
+        for (final CompilerConstants c : values()) {
+            final String symbolName = c.symbolName();
+            if (symbolName != null) {
+                symbolName.intern();
+            }
+        }
+    }
+
+    private static Set<String> symbolNames;
+
     /**
      * Prefix used for internal methods generated in script clases.
      */
-    public static final String INTERNAL_METHOD_PREFIX = ":";
+    private static final String INTERNAL_METHOD_PREFIX = ":";
 
     private final String symbolName;
     private final Class<?> type;
@@ -198,9 +216,28 @@
     }
 
     private CompilerConstants(final String symbolName, final Class<?> type, final int slot) {
-        this.symbolName  = symbolName;
-        this.type = type;
-        this.slot = slot;
+        this.symbolName = symbolName;
+        this.type       = type;
+        this.slot       = slot;
+    }
+
+    /**
+     * Check whether a name is that of a reserved compiler constnat
+     * @param name name
+     * @return true if compiler constant name
+     */
+    public static boolean isCompilerConstant(final String name) {
+        ensureSymbolNames();
+        return symbolNames.contains(name);
+    }
+
+    private static void ensureSymbolNames() {
+        if(symbolNames == null) {
+            symbolNames = new HashSet<>();
+            for(final CompilerConstants cc: CompilerConstants.values()) {
+                symbolNames.add(cc.symbolName);
+            }
+        }
     }
 
     /**
@@ -327,9 +364,14 @@
     public static Call specialCallNoLookup(final String className, final String name, final String desc) {
         return new Call(null, className, name, desc) {
             @Override
-            public MethodEmitter invoke(final MethodEmitter method) {
+            MethodEmitter invoke(final MethodEmitter method) {
                 return method.invokespecial(className, name, descriptor);
             }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, desc, false);
+            }
         };
     }
 
@@ -361,9 +403,14 @@
     public static Call staticCallNoLookup(final String className, final String name, final String desc) {
         return new Call(null, className, name, desc) {
             @Override
-            public MethodEmitter invoke(final MethodEmitter method) {
+            MethodEmitter invoke(final MethodEmitter method) {
                 return method.invokestatic(className, name, descriptor);
             }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, desc, false);
+            }
         };
     }
 
@@ -396,9 +443,14 @@
     public static Call virtualCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
             @Override
-            public MethodEmitter invoke(final MethodEmitter method) {
+            MethodEmitter invoke(final MethodEmitter method) {
                 return method.invokevirtual(className, name, descriptor);
             }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false);
+            }
         };
     }
 
@@ -416,9 +468,14 @@
     public static Call interfaceCallNoLookup(final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return new Call(null, className(clazz), name, methodDescriptor(rtype, ptypes)) {
             @Override
-            public MethodEmitter invoke(final MethodEmitter method) {
+            MethodEmitter invoke(final MethodEmitter method) {
                 return method.invokeinterface(className, name, descriptor);
             }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKEINTERFACE, className, name, descriptor, true);
+            }
         };
     }
 
@@ -512,9 +569,14 @@
     public static Call staticCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return new Call(MH.findStatic(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
             @Override
-            public MethodEmitter invoke(final MethodEmitter method) {
+            MethodEmitter invoke(final MethodEmitter method) {
                 return method.invokestatic(className, name, descriptor);
             }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKESTATIC, className, name, descriptor, false);
+            }
         };
     }
 
@@ -532,13 +594,56 @@
     public static Call virtualCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
         return new Call(MH.findVirtual(lookup, clazz, name, MH.type(rtype, ptypes)), className(clazz), name, methodDescriptor(rtype, ptypes)) {
             @Override
-            public MethodEmitter invoke(final MethodEmitter method) {
+            MethodEmitter invoke(final MethodEmitter method) {
                 return method.invokevirtual(className, name, descriptor);
             }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, className, name, descriptor, false);
+            }
         };
     }
 
     /**
+     * Create a special call, given an explicit lookup, looking up the method handle for it at the same time.
+     * clazz is used as this class
+     *
+     * @param lookup    the lookup
+     * @param clazz     the class
+     * @param name      the name of the method
+     * @param rtype     the return type
+     * @param ptypes    the parameter types
+     *
+     * @return the call object representing the virtual call
+     */
+    public static Call specialCall(final MethodHandles.Lookup lookup, final Class<?> clazz, final String name, final Class<?> rtype, final Class<?>... ptypes) {
+        return new Call(MH.findSpecial(lookup, clazz, name, MH.type(rtype, ptypes), clazz), className(clazz), name, methodDescriptor(rtype, ptypes)) {
+            @Override
+            MethodEmitter invoke(final MethodEmitter method) {
+                return method.invokespecial(className, name, descriptor);
+            }
+
+            @Override
+            public void invoke(final MethodVisitor mv) {
+                mv.visitMethodInsn(Opcodes.INVOKESPECIAL, className, name, descriptor, false);
+            }
+        };
+    }
+
+    /**
+     * Returns true if the passed string looks like a method name of an internally generated Nashorn method. Basically,
+     * if it starts with a colon character {@code :} but is not the name of the program method {@code :program}.
+     * Program function is not considered internal as we want it to show up in exception stack traces.
+     * @param methodName the name of a method
+     * @return true if it looks like an internal Nashorn method name.
+     * @throws NullPointerException if passed null
+     */
+    public static boolean isInternalMethodName(final String methodName) {
+        return methodName.startsWith(INTERNAL_METHOD_PREFIX) && !methodName.equals(PROGRAM.symbolName);
+     }
+
+    /**
      * Private class representing an access. This can generate code into a method code or
      * a field access.
      */
@@ -668,7 +773,14 @@
          *
          * @return the method emitter
          */
-        protected abstract MethodEmitter invoke(final MethodEmitter emitter);
+        abstract MethodEmitter invoke(final MethodEmitter emitter);
+
+        /**
+         * Generate invocation code for the method
+         *
+         * @param mv a method visitor
+         */
+        public abstract void invoke(final MethodVisitor mv);
     }
 
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Condition.java b/nashorn/src/jdk/nashorn/internal/codegen/Condition.java
index 80ed029..27402ed 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Condition.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Condition.java
@@ -66,8 +66,7 @@
         case GT:
             return IFGT;
         default:
-            assert false;
-            return -1;
+            throw new UnsupportedOperationException("toUnary:" + c.toString());
         }
     }
 
@@ -86,8 +85,7 @@
         case GT:
             return IF_ICMPGT;
         default:
-            assert false;
-            return -1;
+            throw new UnsupportedOperationException("toBinary:" + c.toString());
         }
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java b/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
index 292f167..cd87f0f 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ConstantData.java
@@ -25,20 +25,18 @@
 
 package jdk.nashorn.internal.codegen;
 
-import jdk.nashorn.internal.runtime.Property;
-import jdk.nashorn.internal.runtime.PropertyMap;
-
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import jdk.nashorn.internal.runtime.PropertyMap;
 
 /**
  * Manages constants needed by code generation.  Objects are maintained in an
  * interning maps to remove duplicates.
  */
-class ConstantData {
+final class ConstantData {
     /** Constant table. */
     final List<Object> constants;
 
@@ -64,7 +62,7 @@
         private int calcHashCode() {
             final Class<?> cls = array.getClass();
 
-            if (cls == Object[].class) {
+            if (!cls.getComponentType().isPrimitive()) {
                 return Arrays.hashCode((Object[])array);
             } else if (cls == double[].class) {
                 return Arrays.hashCode((double[])array);
@@ -92,7 +90,7 @@
             final Class<?> cls = array.getClass();
 
             if (cls == otherArray.getClass()) {
-                if (cls == Object[].class) {
+                if (!cls.getComponentType().isPrimitive()) {
                     return Arrays.equals((Object[])array, (Object[])otherArray);
                 } else if (cls == double[].class) {
                     return Arrays.equals((double[])array, (double[])otherArray);
@@ -122,12 +120,7 @@
         private final int hashCode;
 
         public PropertyMapWrapper(final PropertyMap map) {
-            int hash = 0;
-            for (final Property property : map.getProperties()) {
-                hash = hash << 7 ^ hash >> 7;
-                hash ^= property.hashCode();
-            }
-            this.hashCode = hash;
+            this.hashCode = Arrays.hashCode(map.getProperties());
             this.propertyMap = map;
         }
 
@@ -138,14 +131,8 @@
 
         @Override
         public boolean equals(final Object other) {
-            if (!(other instanceof PropertyMapWrapper)) {
-                return false;
-            }
-
-            final Property[] ownProperties = propertyMap.getProperties();
-            final Property[] otherProperties = ((PropertyMapWrapper) other).propertyMap.getProperties();
-
-            return Arrays.equals(ownProperties, otherProperties);
+            return other instanceof PropertyMapWrapper &&
+                    Arrays.equals(propertyMap.getProperties(), ((PropertyMapWrapper) other).propertyMap.getProperties());
         }
     }
 
@@ -185,6 +172,7 @@
      * @return the index in the constant pool that the object was given
      */
     public int add(final Object object) {
+        assert object != null;
         final Object  entry;
         if (object.getClass().isArray()) {
             entry = new ArrayWrapper(object);
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java b/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java
new file mode 100644
index 0000000..1fdbab8
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/DumpBytecode.java
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintWriter;
+import jdk.nashorn.internal.runtime.ECMAErrors;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+
+/**
+ * Class that facilitates printing bytecode and dumping it to disk.
+ */
+public final class DumpBytecode {
+    /**
+     * Dump bytecode to console and potentially disk.
+     * @param env the script environment defining options for printing bytecode
+     * @param logger a logger used to write diagnostics about bytecode dumping
+     * @param bytecode the actual code to dump
+     * @param className the name of the class being dumped
+     */
+    public static void dumpBytecode(final ScriptEnvironment env, final DebugLogger logger, final byte[] bytecode, final String className) {
+        File dir = null;
+        try {
+            // should could be printed to stderr for generate class?
+            if (env._print_code) {
+
+                final StringBuilder sb = new StringBuilder();
+                sb.append("class: " + className).
+                    append('\n').
+                    append(ClassEmitter.disassemble(bytecode)).
+                    append("=====");
+
+                if (env._print_code_dir != null) {
+
+                    String name = className;
+                    final int dollar = name.lastIndexOf('$');
+                    if (dollar != -1) {
+                        name = name.substring(dollar + 1);
+                    }
+
+                    dir = new File(env._print_code_dir);
+                    if (!dir.exists() && !dir.mkdirs()) {
+                        throw new IOException(dir.toString());
+                    }
+
+                    File file;
+                    String fileName;
+                    int uniqueId = 0;
+                    do {
+                        fileName = name + (uniqueId == 0 ? "" : "_" + uniqueId) + ".bytecode";
+                        file = new File(env._print_code_dir, fileName);
+                        uniqueId++;
+                    } while (file.exists());
+
+                    try (final PrintWriter pw = new PrintWriter(new FileOutputStream(file))) {
+                        pw.print(sb.toString());
+                        pw.flush();
+                    }
+                } else {
+                    env.getErr().println(sb);
+                }
+            }
+
+
+            // should code be dumped to disk - only valid in compile_only mode?
+            if (env._dest_dir != null && env._compile_only) {
+                final String fileName = className.replace('.', File.separatorChar) + ".class";
+                final int    index    = fileName.lastIndexOf(File.separatorChar);
+
+                if (index != -1) {
+                    dir = new File(env._dest_dir, fileName.substring(0, index));
+                } else {
+                    dir = new File(env._dest_dir);
+                }
+
+                if (!dir.exists() && !dir.mkdirs()) {
+                    throw new IOException(dir.toString());
+                }
+                final File file = new File(env._dest_dir, fileName);
+                try (final FileOutputStream fos = new FileOutputStream(file)) {
+                    fos.write(bytecode);
+                }
+                logger.info("Wrote class to '" + file.getAbsolutePath() + '\'');
+            }
+        } catch (final IOException e) {
+            logger.warning("Skipping class dump for ",
+                    className,
+                    ": ",
+                    ECMAErrors.getMessage(
+                        "io.error.cant.write",
+                        dir.toString()));
+        }
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java b/nashorn/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
index 438103e..86dcd77 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FieldObjectCreator.java
@@ -28,8 +28,9 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS;
 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.typeDescriptor;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName;
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount;
-import static jdk.nashorn.internal.codegen.types.Type.OBJECT;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
@@ -51,19 +52,18 @@
  * @param <T> the value type for the fields being written on object creation, e.g. Node
  * @see jdk.nashorn.internal.ir.Node
  */
-public abstract class FieldObjectCreator<T> extends ObjectCreator {
+public abstract class FieldObjectCreator<T> extends ObjectCreator<T> {
 
-    private         String        fieldObjectClassName;
-    private         Class<?>      fieldObjectClass;
-    private         int           fieldCount;
-    private         int           paddedFieldCount;
-    private         int           paramCount;
-
-    /** array of corresponding values to symbols (null for no values) */
-    private final List<T> values;
+    private String                        fieldObjectClassName;
+    private Class<? extends ScriptObject> fieldObjectClass;
+    private int                           fieldCount;
+    private int                           paddedFieldCount;
+    private int                           paramCount;
 
     /** call site flags to be used for invocations */
-    private final int     callSiteFlags;
+    private final int callSiteFlags;
+    /** are we creating this field object from 'eval' code? */
+    private final boolean evalCode;
 
     /**
      * Constructor
@@ -73,8 +73,8 @@
      * @param symbols  symbols for fields in object
      * @param values   list of values corresponding to keys
      */
-    FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values) {
-        this(codegen, keys, symbols, values, false, false);
+    FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples) {
+        this(codegen, tuples, false, false);
     }
 
     /**
@@ -87,11 +87,10 @@
      * @param isScope      is this a scope object
      * @param hasArguments does the created object have an "arguments" property
      */
-    FieldObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<T> values, final boolean isScope, final boolean hasArguments) {
-        super(codegen, keys, symbols, isScope, hasArguments);
-        this.values        = values;
+    FieldObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples, final boolean isScope, final boolean hasArguments) {
+        super(codegen, tuples, isScope, hasArguments);
         this.callSiteFlags = codegen.getCallSiteFlags();
-
+        this.evalCode = codegen.isEvalCode();
         countFields();
         findClass();
     }
@@ -104,8 +103,19 @@
     @Override
     protected void makeObject(final MethodEmitter method) {
         makeMap();
-
-        method._new(getClassName()).dup(); // create instance
+        final String className = getClassName();
+        try {
+            // NOTE: we must load the actual structure class here, because the API operates with Nashorn Type objects,
+            // and Type objects need a loaded class, for better or worse. We also have to be specific and use the type
+            // of the actual structure class, we can't generalize it to e.g. Type.typeFor(ScriptObject.class) as the
+            // exact type information is needed for generating continuations in rest-of methods. If we didn't do this,
+            // object initializers like { x: arr[i] } would fail during deoptimizing compilation on arr[i], as the
+            // values restored from the RewriteException would be cast to "ScriptObject" instead of to e.g. "JO4", and
+            // subsequently the "PUTFIELD J04.L0" instruction in the continuation code would fail bytecode verification.
+            method._new(Context.forStructureClass(className.replace('/', '.'))).dup();
+        } catch (final ClassNotFoundException e) {
+            throw new AssertionError(e);
+        }
         loadMap(method); //load the map
 
         if (isScope()) {
@@ -113,32 +123,31 @@
 
             if (hasArguments()) {
                 method.loadCompilerConstant(ARGUMENTS);
-                method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class, ARGUMENTS.type()));
+                method.invoke(constructorNoLookup(className, PropertyMap.class, ScriptObject.class, ARGUMENTS.type()));
             } else {
-                method.invoke(constructorNoLookup(getClassName(), PropertyMap.class, ScriptObject.class));
+                method.invoke(constructorNoLookup(className, PropertyMap.class, ScriptObject.class));
             }
         } else {
-            method.invoke(constructorNoLookup(getClassName(), PropertyMap.class));
+            method.invoke(constructorNoLookup(className, PropertyMap.class));
         }
 
         // Set values.
-        final Iterator<Symbol> symbolIter = symbols.iterator();
-        final Iterator<String> keyIter    = keys.iterator();
-        final Iterator<T>      valueIter  = values.iterator();
+        final Iterator<MapTuple<T>> iter = tuples.iterator();
 
-        while (symbolIter.hasNext()) {
-            final Symbol symbol = symbolIter.next();
-            final String key    = keyIter.next();
-            final T      value  = valueIter.next();
-
-            if (symbol != null && value != null) {
-                final int index = getArrayIndex(key);
-
+        while (iter.hasNext()) {
+            final MapTuple<T> tuple = iter.next();
+            //we only load when we have both symbols and values (which can be == the symbol)
+            //if we didn't load, we need an array property
+            if (tuple.symbol != null && tuple.value != null) {
+                final int index = getArrayIndex(tuple.key);
                 if (!isValidArrayIndex(index)) {
-                    putField(method, key, symbol.getFieldIndex(), value);
+                    putField(method, tuple.key, tuple.symbol.getFieldIndex(), tuple);
                 } else {
-                    putSlot(method, ArrayIndex.toLongIndex(index), value);
+                    putSlot(method, ArrayIndex.toLongIndex(index), tuple);
                 }
+
+                //this is a nop of tuple.key isn't e.g. "apply" or another special name
+                method.invalidateSpecialName(tuple.key);
             }
         }
     }
@@ -146,18 +155,11 @@
     @Override
     protected PropertyMap makeMap() {
         assert propertyMap == null : "property map already initialized";
-        propertyMap = newMapCreator(fieldObjectClass).makeFieldMap(hasArguments(), fieldCount, paddedFieldCount);
+        propertyMap = newMapCreator(fieldObjectClass).makeFieldMap(hasArguments(), fieldCount, paddedFieldCount, evalCode);
         return propertyMap;
     }
 
     /**
-     * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
-     *
-     * @param value Value to load.
-     */
-    protected abstract void loadValue(T value);
-
-    /**
      * Store a value in a field of the generated class object.
      *
      * @param method      Script method.
@@ -165,12 +167,20 @@
      * @param fieldIndex  Field number.
      * @param value       Value to store.
      */
-    private void putField(final MethodEmitter method, final String key, final int fieldIndex, final T value) {
+    private void putField(final MethodEmitter method, final String key, final int fieldIndex, final MapTuple<T> tuple) {
         method.dup();
 
-        loadValue(value);
-        method.convert(OBJECT);
-        method.putField(getClassName(), ObjectClassGenerator.getFieldName(fieldIndex, Type.OBJECT), typeDescriptor(Object.class));
+        final Type    fieldType   = tuple.isPrimitive() ? PRIMITIVE_FIELD_TYPE : Type.OBJECT;
+        final String  fieldClass  = getClassName();
+        final String  fieldName   = getFieldName(fieldIndex, fieldType);
+        final String  fieldDesc   = typeDescriptor(fieldType.getTypeClass());
+
+        assert fieldName.equals(getFieldName(fieldIndex, PRIMITIVE_FIELD_TYPE)) || fieldType.isObject() :    key + " object keys must store to L*-fields";
+        assert fieldName.equals(getFieldName(fieldIndex, Type.OBJECT))          || fieldType.isPrimitive() : key + " primitive keys must store to J*-fields";
+
+        loadTuple(method, tuple);
+
+        method.putField(fieldClass, fieldName, fieldDesc);
     }
 
     /**
@@ -180,14 +190,14 @@
      * @param index  Slot index.
      * @param value  Value to store.
      */
-    private void putSlot(final MethodEmitter method, final long index, final T value) {
+    private void putSlot(final MethodEmitter method, final long index, final MapTuple<T> tuple) {
         method.dup();
         if (JSType.isRepresentableAsInt(index)) {
-            method.load((int) index);
+            method.load((int)index);
         } else {
             method.load(index);
         }
-        loadValue(value);
+        loadTuple(method, tuple, false); //we don't pack array like objects
         method.dynamicSetIndex(callSiteFlags);
     }
 
@@ -220,7 +230,8 @@
      * Tally the number of fields and parameters.
      */
     private void countFields() {
-        for (final Symbol symbol : this.symbols) {
+        for (final MapTuple<T> tuple : tuples) {
+            final Symbol symbol = tuple.symbol;
             if (symbol != null) {
                 if (hasArguments() && symbol.isParam()) {
                     symbol.setFieldIndex(paramCount++);
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java b/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java
deleted file mode 100644
index 1534148..0000000
--- a/nashorn/src/jdk/nashorn/internal/codegen/FinalizeTypes.java
+++ /dev/null
@@ -1,199 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE;
-import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
-
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Block;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ExpressionStatement;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.TemporarySymbols;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.parser.Token;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.DebugLogger;
-
-/**
- * Lower to more primitive operations. After lowering, an AST has symbols and
- * types. Lowering may also add specialized versions of methods to the script if
- * the optimizer is turned on.
- *
- * Any expression that requires temporary storage as part of computation will
- * also be detected here and give a temporary symbol
- *
- * For any op that we process in FinalizeTypes it is an absolute guarantee
- * that scope and slot information is correct. This enables e.g. AccessSpecialization
- * and frame optimizations
- */
-
-final class FinalizeTypes extends NodeOperatorVisitor<LexicalContext> {
-
-    private static final DebugLogger LOG = new DebugLogger("finalize");
-
-    private final TemporarySymbols temporarySymbols;
-
-    FinalizeTypes(final TemporarySymbols temporarySymbols) {
-        super(new LexicalContext());
-        this.temporarySymbols = temporarySymbols;
-    }
-
-    @Override
-    public Node leaveForNode(final ForNode forNode) {
-        if (forNode.isForIn()) {
-            return forNode;
-        }
-
-        final Expression init   = forNode.getInit();
-        final Expression test   = forNode.getTest();
-        final Expression modify = forNode.getModify();
-
-        assert test != null || forNode.hasGoto() : "forNode " + forNode + " needs goto and is missing it in " + lc.getCurrentFunction();
-
-        return forNode.
-            setInit(lc, init == null ? null : discard(init)).
-            setModify(lc, modify == null ? null : discard(modify));
-    }
-
-    @Override
-    public Node leaveCOMMALEFT(final BinaryNode binaryNode) {
-        assert binaryNode.getSymbol() != null;
-        return binaryNode.setRHS(discard(binaryNode.rhs()));
-    }
-
-    @Override
-    public Node leaveCOMMARIGHT(final BinaryNode binaryNode) {
-        assert binaryNode.getSymbol() != null;
-        return binaryNode.setLHS(discard(binaryNode.lhs()));
-    }
-
-    @Override
-    public boolean enterBlock(final Block block) {
-        updateSymbols(block);
-        return true;
-    }
-
-    @Override
-    public Node leaveExpressionStatement(final ExpressionStatement expressionStatement) {
-        temporarySymbols.reuse();
-        return expressionStatement.setExpression(discard(expressionStatement.getExpression()));
-    }
-
-    @Override
-    public boolean enterFunctionNode(final FunctionNode functionNode) {
-        if (functionNode.isLazy()) {
-            return false;
-        }
-
-        // If the function doesn't need a callee, we ensure its __callee__ symbol doesn't get a slot. We can't do
-        // this earlier, as access to scoped variables, self symbol, etc. in previous phases can all trigger the
-        // need for the callee.
-        if (!functionNode.needsCallee()) {
-            functionNode.compilerConstant(CALLEE).setNeedsSlot(false);
-        }
-        // Similar reasoning applies to __scope__ symbol: if the function doesn't need either parent scope and none of
-        // its blocks create a scope, we ensure it doesn't get a slot, but we can't determine whether it needs a scope
-        // earlier than this phase.
-        if (!(functionNode.hasScopeBlock() || functionNode.needsParentScope())) {
-            functionNode.compilerConstant(SCOPE).setNeedsSlot(false);
-        }
-
-        return true;
-    }
-
-    @Override
-    public Node leaveFunctionNode(final FunctionNode functionNode) {
-        return functionNode.setState(lc, CompilationState.FINALIZED);
-    }
-
-    private static void updateSymbolsLog(final FunctionNode functionNode, final Symbol symbol, final boolean loseSlot) {
-        if (LOG.isEnabled()) {
-            if (!symbol.isScope()) {
-                LOG.finest("updateSymbols: ", symbol, " => scope, because all vars in ", functionNode.getName(), " are in scope");
-            }
-            if (loseSlot && symbol.hasSlot()) {
-                LOG.finest("updateSymbols: ", symbol, " => no slot, because all vars in ", functionNode.getName(), " are in scope");
-            }
-        }
-    }
-
-    /**
-     * Called after a block or function node (subclass of block) is finished. Guarantees
-     * that scope and slot information is correct for every symbol
-     * @param block block for which to to finalize type info.
-     */
-    private void updateSymbols(final Block block) {
-        if (!block.needsScope()) {
-            return; // nothing to do
-        }
-
-        final FunctionNode   functionNode   = lc.getFunction(block);
-        final boolean        allVarsInScope = functionNode.allVarsInScope();
-        final boolean        isVarArg       = functionNode.isVarArg();
-
-        for (final Symbol symbol : block.getSymbols()) {
-            if (symbol.isInternal() || symbol.isThis() || symbol.isTemp()) {
-                continue;
-            }
-
-            if (symbol.isVar()) {
-                if (allVarsInScope || symbol.isScope()) {
-                    updateSymbolsLog(functionNode, symbol, true);
-                    Symbol.setSymbolIsScope(lc, symbol);
-                    symbol.setNeedsSlot(false);
-                } else {
-                    assert symbol.hasSlot() : symbol + " should have a slot only, no scope";
-                }
-            } else if (symbol.isParam() && (allVarsInScope || isVarArg || symbol.isScope())) {
-                updateSymbolsLog(functionNode, symbol, isVarArg);
-                Symbol.setSymbolIsScope(lc, symbol);
-                symbol.setNeedsSlot(!isVarArg);
-            }
-        }
-    }
-
-    private static Expression discard(final Expression node) {
-        if (node.getSymbol() != null) {
-            final UnaryNode discard = new UnaryNode(Token.recast(node.getToken(), TokenType.DISCARD), node);
-            //discard never has a symbol in the discard node - then it would be a nop
-            assert !node.isTerminal();
-            return discard;
-        }
-
-        // node has no result (symbol) so we can keep it the way it is
-        return node;
-    }
-
-
-}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java b/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
new file mode 100644
index 0000000..0f8ea77
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FindScopeDepths.java
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 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.  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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getClassName;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getPaddedFieldCount;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.WithNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * Establishes depth of scope for non local symbols at the start of method.
+ * If this is a recompilation, the previous data from eager compilation is
+ * stored in the RecompilableScriptFunctionData and is transferred to the
+ * FunctionNode being compiled
+ */
+@Logger(name="scopedepths")
+final class FindScopeDepths extends NodeVisitor<LexicalContext> implements Loggable {
+
+    private final Compiler compiler;
+    private final Map<Integer, Map<Integer, RecompilableScriptFunctionData>> fnIdToNestedFunctions = new HashMap<>();
+    private final Map<Integer, Map<String, Integer>> externalSymbolDepths = new HashMap<>();
+    private final Map<Integer, Set<String>> internalSymbols = new HashMap<>();
+    private final Set<Block> withBodies = new HashSet<>();
+
+    private final DebugLogger log;
+
+    private int dynamicScopeCount;
+
+    FindScopeDepths(final Compiler compiler) {
+        super(new LexicalContext());
+        this.compiler = compiler;
+        this.log      = initLogger(compiler.getContext());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    static int findScopesToStart(final LexicalContext lc, final FunctionNode fn, final Block block) {
+        final Block bodyBlock = findBodyBlock(lc, fn, block);
+        final Iterator<Block> iter = lc.getBlocks(block);
+        Block b = iter.next();
+        int scopesToStart = 0;
+        while (true) {
+            if (b.needsScope()) {
+                scopesToStart++;
+            }
+            if (b == bodyBlock) {
+                break;
+            }
+            b = iter.next();
+        }
+        return scopesToStart;
+    }
+
+    static int findInternalDepth(final LexicalContext lc, final FunctionNode fn, final Block block, final Symbol symbol) {
+        final Block bodyBlock = findBodyBlock(lc, fn, block);
+        final Iterator<Block> iter = lc.getBlocks(block);
+        Block b = iter.next();
+        int scopesToStart = 0;
+        while (true) {
+            if (definedInBlock(b, symbol)) {
+                return scopesToStart;
+            }
+            if (b.needsScope()) {
+                scopesToStart++;
+            }
+            if (b == bodyBlock) {
+                break; //don't go past body block, but process it
+            }
+            b = iter.next();
+        }
+        return -1;
+    }
+
+    private static boolean definedInBlock(final Block block, final Symbol symbol) {
+        if (symbol.isGlobal()) {
+            if (block.isGlobalScope()) {
+                return true;
+            }
+            //globals cannot be defined anywhere else
+            return false;
+        }
+        return block.getExistingSymbol(symbol.getName()) == symbol;
+    }
+
+    static Block findBodyBlock(final LexicalContext lc, final FunctionNode fn, final Block block) {
+        final Iterator<Block> iter = lc.getBlocks(block);
+        while (iter.hasNext()) {
+            final Block next = iter.next();
+            if (fn.getBody() == next) {
+                return next;
+            }
+        }
+        return null;
+    }
+
+    private static Block findGlobalBlock(final LexicalContext lc, final Block block) {
+        final Iterator<Block> iter = lc.getBlocks(block);
+        Block globalBlock = null;
+        while (iter.hasNext()) {
+            globalBlock = iter.next();
+        }
+        return globalBlock;
+    }
+
+    private static boolean isDynamicScopeBoundary(final FunctionNode fn) {
+        return fn.needsDynamicScope();
+    }
+
+    private boolean isDynamicScopeBoundary(final Block block) {
+        return withBodies.contains(block);
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        if (compiler.isOnDemandCompilation()) {
+            return true;
+        }
+
+        if (isDynamicScopeBoundary(functionNode)) {
+            increaseDynamicScopeCount(functionNode);
+        }
+
+        final int fnId = functionNode.getId();
+        Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.get(fnId);
+        if (nestedFunctions == null) {
+            nestedFunctions = new HashMap<>();
+            fnIdToNestedFunctions.put(fnId, nestedFunctions);
+        }
+
+        return true;
+    }
+
+    //external symbols hold the scope depth of sc11 from global at the start of the method
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+        final String name = functionNode.getName();
+        FunctionNode newFunctionNode = functionNode.setState(lc, CompilationState.SCOPE_DEPTHS_COMPUTED);
+
+        if (compiler.isOnDemandCompilation()) {
+            final RecompilableScriptFunctionData data = compiler.getScriptFunctionData(newFunctionNode.getId());
+            assert data != null : newFunctionNode.getName() + " lacks data";
+            if (data.inDynamicContext()) {
+                log.fine("Reviving scriptfunction ", quote(name), " as defined in previous (now lost) dynamic scope.");
+                newFunctionNode = newFunctionNode.setInDynamicContext(lc);
+            }
+            return newFunctionNode;
+        }
+
+        if (inDynamicScope()) {
+            log.fine("Tagging ", quote(name), " as defined in dynamic scope");
+            newFunctionNode = newFunctionNode.setInDynamicContext(lc);
+        }
+
+        //create recompilable scriptfunctiondata
+        final int fnId = newFunctionNode.getId();
+        final Map<Integer, RecompilableScriptFunctionData> nestedFunctions = fnIdToNestedFunctions.get(fnId);
+
+        assert nestedFunctions != null;
+        // Generate the object class and property map in case this function is ever used as constructor
+        final int         fieldCount         = getPaddedFieldCount(newFunctionNode.getThisProperties());
+        final String      allocatorClassName = Compiler.binaryName(getClassName(fieldCount));
+        final PropertyMap allocatorMap       = PropertyMap.newMap(null, allocatorClassName, 0, fieldCount, 0);
+        final RecompilableScriptFunctionData data = new RecompilableScriptFunctionData(
+                newFunctionNode,
+                compiler.getCodeInstaller(),
+                allocatorClassName,
+                allocatorMap,
+                nestedFunctions,
+                externalSymbolDepths.get(fnId),
+                internalSymbols.get(fnId)
+                );
+
+        if (lc.getOutermostFunction() != newFunctionNode) {
+            final FunctionNode parentFn = lc.getParentFunction(newFunctionNode);
+            if (parentFn != null) {
+                fnIdToNestedFunctions.get(parentFn.getId()).put(fnId, data);
+            }
+        } else {
+            compiler.setData(data);
+        }
+
+        if (isDynamicScopeBoundary(functionNode)) {
+            decreaseDynamicScopeCount(functionNode);
+        }
+
+        return newFunctionNode;
+    }
+
+    private boolean inDynamicScope() {
+        return dynamicScopeCount > 0;
+    }
+
+    private void increaseDynamicScopeCount(final Node node) {
+        assert dynamicScopeCount >= 0;
+        ++dynamicScopeCount;
+        if (log.isEnabled()) {
+            log.finest(quote(lc.getCurrentFunction().getName()), " ++dynamicScopeCount = ", dynamicScopeCount, " at: ", node, node.getClass());
+        }
+    }
+
+    private void decreaseDynamicScopeCount(final Node node) {
+        --dynamicScopeCount;
+        assert dynamicScopeCount >= 0;
+        if (log.isEnabled()) {
+            log.finest(quote(lc.getCurrentFunction().getName()), " --dynamicScopeCount = ", dynamicScopeCount, " at: ", node, node.getClass());
+        }
+    }
+
+    @Override
+    public boolean enterWithNode(final WithNode node) {
+        withBodies.add(node.getBody());
+        return true;
+    }
+
+    @Override
+    public boolean enterBlock(final Block block) {
+        if (compiler.isOnDemandCompilation()) {
+            return true;
+        }
+
+        if (isDynamicScopeBoundary(block)) {
+            increaseDynamicScopeCount(block);
+        }
+
+        if (!lc.isFunctionBody()) {
+            return true;
+        }
+
+        //the below part only happens on eager compilation when we have the entire hierarchy
+        //block is a function body
+        final FunctionNode fn = lc.getCurrentFunction();
+
+        //get all symbols that are referenced inside this function body
+        final Set<Symbol> symbols = new HashSet<>();
+        block.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public final boolean enterDefault(final Node node) {
+                if (!compiler.isOnDemandCompilation()) {
+                    if (node instanceof IdentNode) {
+                        final Symbol symbol = ((IdentNode)node).getSymbol();
+                        if (symbol != null && symbol.isScope()) {
+                            //if this is an internal symbol, skip it.
+                            symbols.add(symbol);
+                        }
+                    }
+                }
+                return true;
+            }
+        });
+
+        final Map<String, Integer> internals = new HashMap<>();
+
+        final Block globalBlock = findGlobalBlock(lc, block);
+        final Block bodyBlock   = findBodyBlock(lc, fn, block);
+
+        assert globalBlock != null;
+        assert bodyBlock   != null;
+
+        for (final Symbol symbol : symbols) {
+            Iterator<Block> iter;
+
+            final int internalDepth = findInternalDepth(lc, fn, block, symbol);
+            final boolean internal = internalDepth >= 0;
+            if (internal) {
+                internals.put(symbol.getName(), internalDepth);
+            }
+
+            // if not internal, we have to continue walking until we reach the top. We
+            // start outside the body and each new scope adds a depth count. When we
+            // find the symbol, we store its depth count
+            if (!internal) {
+                int depthAtStart = 0;
+                //not internal - keep looking.
+                iter = lc.getAncestorBlocks(bodyBlock);
+                while (iter.hasNext()) {
+                    final Block b2 = iter.next();
+                    if (definedInBlock(b2, symbol)) {
+                        addExternalSymbol(fn, symbol, depthAtStart);
+                        break;
+                    }
+                    if (b2.needsScope()) {
+                        depthAtStart++;
+                    }
+                }
+            }
+        }
+
+        addInternalSymbols(fn, internals.keySet());
+
+        if (log.isEnabled()) {
+            log.info(fn.getName() + " internals=" + internals + " externals=" + externalSymbolDepths.get(fn.getId()));
+        }
+
+        return true;
+    }
+
+    @Override
+    public Node leaveBlock(final Block block) {
+        if (compiler.isOnDemandCompilation()) {
+            return block;
+        }
+        if (isDynamicScopeBoundary(block)) {
+            decreaseDynamicScopeCount(block);
+        }
+        return block;
+    }
+
+    private void addInternalSymbols(final FunctionNode functionNode, final Set<String> symbols) {
+        final int fnId = functionNode.getId();
+        assert internalSymbols.get(fnId) == null || internalSymbols.get(fnId).equals(symbols); //e.g. cloned finally block
+        internalSymbols.put(fnId, symbols);
+    }
+
+    private void addExternalSymbol(final FunctionNode functionNode, final Symbol symbol, final int depthAtStart) {
+        final int fnId = functionNode.getId();
+        Map<String, Integer> depths = externalSymbolDepths.get(fnId);
+        if (depths == null) {
+            depths = new HashMap<>();
+            externalSymbolDepths.put(fnId, depths);
+        }
+        depths.put(symbol.getName(), depthAtStart);
+    }
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
index 59362fa..fe81b2b 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FoldConstants.java
@@ -44,26 +44,41 @@
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * Simple constant folding pass, executed before IR is starting to be lowered.
  */
-final class FoldConstants extends NodeVisitor<LexicalContext> {
+@Logger(name="fold")
+final class FoldConstants extends NodeVisitor<LexicalContext> implements Loggable {
 
-    private static final DebugLogger LOG = new DebugLogger("fold");
+    private final DebugLogger log;
 
-    FoldConstants() {
+    FoldConstants(final Compiler compiler) {
         super(new LexicalContext());
+        this.log = initLogger(compiler.getContext());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
     public Node leaveUnaryNode(final UnaryNode unaryNode) {
         final LiteralNode<?> literalNode = new UnaryNodeConstantEvaluator(unaryNode).eval();
         if (literalNode != null) {
-            LOG.info("Unary constant folded ", unaryNode, " to ", literalNode);
+            log.info("Unary constant folded ", unaryNode, " to ", literalNode);
             return literalNode;
         }
         return unaryNode;
@@ -73,18 +88,13 @@
     public Node leaveBinaryNode(final BinaryNode binaryNode) {
         final LiteralNode<?> literalNode = new BinaryNodeConstantEvaluator(binaryNode).eval();
         if (literalNode != null) {
-            LOG.info("Binary constant folded ", binaryNode, " to ", literalNode);
+            log.info("Binary constant folded ", binaryNode, " to ", literalNode);
             return literalNode;
         }
         return binaryNode;
     }
 
     @Override
-    public boolean enterFunctionNode(final FunctionNode functionNode) {
-        return !functionNode.isLazy();
-    }
-
-    @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
         return functionNode.setState(lc, CompilationState.CONSTANT_FOLDED);
     }
@@ -149,7 +159,7 @@
         final LexicalContext lc = new LexicalContext();
         block.accept(lc, new NodeVisitor<LexicalContext>(lc) {
             @Override
-            public boolean enterVarNode(VarNode varNode) {
+            public boolean enterVarNode(final VarNode varNode) {
                 statements.add(varNode.setInit(null));
                 return false;
             }
@@ -163,7 +173,7 @@
 
         @Override
         protected LiteralNode<?> eval() {
-            final Node rhsNode = parent.rhs();
+            final Node rhsNode = parent.getExpression();
 
             if (!(rhsNode instanceof LiteralNode)) {
                 return null;
@@ -174,7 +184,8 @@
             }
 
             final LiteralNode<?> rhs = (LiteralNode<?>)rhsNode;
-            final boolean rhsInteger = rhs.getType().isInteger();
+            final Type rhsType = rhs.getType();
+            final boolean rhsInteger = rhsType.isInteger() || rhsType.isBoolean();
 
             LiteralNode<?> literalNode;
 
@@ -261,7 +272,7 @@
                 break;
             case ADD:
                 if ((lhs.isString() || rhs.isNumeric()) && (rhs.isString() || rhs.isNumeric())) {
-                    Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject());
+                    final Object res = ScriptRuntime.ADD(lhs.getObject(), rhs.getObject());
                     if (res instanceof Number) {
                         value = ((Number)res).doubleValue();
                         break;
@@ -311,8 +322,8 @@
                 return null;
             }
 
-            isInteger &= value != 0.0 && JSType.isRepresentableAsInt(value);
-            isLong    &= value != 0.0 && JSType.isRepresentableAsLong(value);
+            isInteger &= JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value);
+            isLong    &= JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value);
 
             if (isInteger) {
                 return LiteralNode.newInstance(token, finish, (int)value);
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java b/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java
index 1c1b5f7..5e06794 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/FunctionSignature.java
@@ -141,7 +141,7 @@
             paramTypeList.add(paramType.getTypeClass());
         }
 
-        this.methodType = MH.type(returnType.getTypeClass(), paramTypeList.toArray(new Class[paramTypes.length]));
+        this.methodType = MH.type(returnType.getTypeClass(), paramTypeList.toArray(new Class<?>[paramTypes.length]));
     }
 
     /**
@@ -195,6 +195,14 @@
     }
 
     /**
+     * Get the param types for this function signature
+     * @return cloned vector of param types
+     */
+    public Type[] getParamTypes() {
+        return paramTypes.clone();
+    }
+
+    /**
      * Return the {@link MethodType} for this function signature
      * @return the method type
      */
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Label.java b/nashorn/src/jdk/nashorn/internal/codegen/Label.java
index 21939db..8630469 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Label.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Label.java
@@ -24,8 +24,13 @@
  */
 package jdk.nashorn.internal.codegen;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
 import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.runtime.Debug;
 
 /**
  * Abstraction for labels, separating a label from the underlying
@@ -38,20 +43,23 @@
     //byte code generation evaluation type stack for consistency check
     //and correct opcode selection. one per label as a label may be a
     //join point
-    static final class Stack {
-        Type[] data = new Type[8];
-        int sp = 0;
+    static final class Stack implements Cloneable {
+        static final int NON_LOAD = -1;
+
+        Type[] data;
+        int[]  localLoads;
+        int    sp;
+
+        List<Type> localVariableTypes;
+        int firstTemp; // index of the first temporary local variable
+        // Bitmap marking last slot belonging to a single symbol.
+        BitSet symbolBoundary;
 
         Stack() {
-        }
-
-        private Stack(final Type[] type, final int sp) {
-            this();
-            this.data = new Type[type.length];
-            this.sp   = sp;
-            for (int i = 0; i < sp; i++) {
-                data[i] = type[i];
-            }
+            data = new Type[8];
+            localLoads = new int[8];
+            localVariableTypes = new ArrayList<>(8);
+            symbolBoundary = new BitSet();
         }
 
         boolean isEmpty() {
@@ -62,7 +70,147 @@
             return sp;
         }
 
-        boolean isEquivalentTo(final Stack other) {
+        void clear() {
+            sp = 0;
+        }
+
+        void push(final Type type) {
+            if (data.length == sp) {
+                final Type[] newData = new Type[sp * 2];
+                final int[]  newLocalLoad = new int[sp * 2];
+                System.arraycopy(data, 0, newData, 0, sp);
+                System.arraycopy(localLoads, 0, newLocalLoad, 0, sp);
+                data = newData;
+                localLoads = newLocalLoad;
+            }
+            data[sp] = type;
+            localLoads[sp] = NON_LOAD;
+            sp++;
+        }
+
+        Type peek() {
+            return peek(0);
+        }
+
+        Type peek(final int n) {
+            final int pos = sp - 1 - n;
+            return pos < 0 ? null : data[pos];
+        }
+
+        /**
+         * Retrieve the top <tt>count</tt> types on the stack without modifying it.
+         *
+         * @param count number of types to return
+         * @return array of Types
+         */
+        Type[] getTopTypes(final int count) {
+            final Type[] topTypes = new Type[count];
+            System.arraycopy(data, sp - count, topTypes, 0, count);
+            return topTypes;
+        }
+
+        int[] getLocalLoads(final int from, final int to) {
+            final int count = to - from;
+            final int[] topLocalLoads = new int[count];
+            System.arraycopy(localLoads, from, topLocalLoads, 0, count);
+            return topLocalLoads;
+        }
+
+        /**
+         * Returns the number of used local variable slots, including all live stack-store temporaries.
+         * @return the number of used local variable slots, including all live stack-store temporaries.
+         */
+        int getUsedSlotsWithLiveTemporaries() {
+            // There are at least as many as are declared by the current blocks.
+            int usedSlots = firstTemp;
+            // Look at every load on the stack, and bump the number of used slots up by the temporaries seen there.
+            for(int i = sp; i-->0;) {
+                final int slot = localLoads[i];
+                if(slot != Label.Stack.NON_LOAD) {
+                    final int afterSlot = slot + localVariableTypes.get(slot).getSlots();
+                    if(afterSlot > usedSlots) {
+                        usedSlots = afterSlot;
+                    }
+                }
+            }
+            return usedSlots;
+        }
+
+        /**
+         *
+         * @param joinOrigin the stack from the other branch.
+         */
+        void joinFrom(final Stack joinOrigin, final boolean breakTarget) {
+            assert isStackCompatible(joinOrigin);
+            if(breakTarget) {
+                // As we're joining labels that can jump across block boundaries, the number of local variables can
+                // differ, and we should always respect the one having less variables.
+                firstTemp = Math.min(firstTemp, joinOrigin.firstTemp);
+            } else {
+                assert firstTemp == joinOrigin.firstTemp;
+            }
+            final int[] otherLoads = joinOrigin.localLoads;
+            int firstDeadTemp = firstTemp;
+            for(int i = 0; i < sp; ++i) {
+                final int localLoad = localLoads[i];
+                if(localLoad != otherLoads[i]) {
+                    localLoads[i] = NON_LOAD;
+                } else if(localLoad >= firstDeadTemp) {
+                    firstDeadTemp = localLoad + localVariableTypes.get(localLoad).getSlots();
+                }
+            }
+            // Eliminate dead temporaries
+            undefineLocalVariables(firstDeadTemp, false);
+            assert isVariablePartitioningEqual(joinOrigin, firstDeadTemp);
+            mergeVariableTypes(joinOrigin, firstDeadTemp);
+        }
+
+        private void mergeVariableTypes(final Stack joinOrigin, final int toSlot) {
+            final ListIterator<Type> it1 = localVariableTypes.listIterator();
+            final Iterator<Type> it2 = joinOrigin.localVariableTypes.iterator();
+
+            for(int i = 0; i < toSlot; ++i) {
+                final Type thisType = it1.next();
+                final Type otherType = it2.next();
+                if(otherType == Type.UNKNOWN) {
+                    // Variables that are <unknown> on the other branch will become <unknown> here too.
+                    it1.set(Type.UNKNOWN);
+                } else if (thisType != otherType) {
+                    if(thisType.isObject() && otherType.isObject()) {
+                        // different object types are merged into Object.
+                        // TODO: maybe find most common superclass?
+                        it1.set(Type.OBJECT);
+                    } else {
+                        assert thisType == Type.UNKNOWN;
+                    }
+                }
+            }
+        }
+
+        void joinFromTry(final Stack joinOrigin) {
+            // As we're joining labels that can jump across block boundaries, the number of local variables can
+            // differ, and we should always respect the one having less variables.
+            firstTemp = Math.min(firstTemp, joinOrigin.firstTemp);
+            assert isVariablePartitioningEqual(joinOrigin, firstTemp);
+            mergeVariableTypes(joinOrigin, firstTemp);
+        }
+
+        private int getFirstDeadLocal(final List<Type> types) {
+            int i = types.size();
+            for(final ListIterator<Type> it = types.listIterator(i);
+                it.hasPrevious() && it.previous() == Type.UNKNOWN;
+                --i) {
+                // no body
+            }
+
+            // Respect symbol boundaries; we never chop off half a symbol's storage
+            while(!symbolBoundary.get(i - 1)) {
+                ++i;
+            }
+            return i;
+        }
+
+        private boolean isStackCompatible(final Stack other) {
             if (sp != other.sp) {
                 return false;
             }
@@ -74,51 +222,271 @@
             return true;
         }
 
-        void clear() {
-            sp = 0;
+        private boolean isVariablePartitioningEqual(final Stack other, final int toSlot) {
+            // No difference in the symbol boundaries before the toSlot
+            final BitSet diff = other.getSymbolBoundaryCopy();
+            diff.xor(symbolBoundary);
+            return diff.previousSetBit(toSlot - 1) == -1;
         }
 
-        void push(final Type type) {
-            if (data.length == sp) {
-                final Type[] newData = new Type[sp * 2];
-                for (int i = 0; i < sp; i++) {
-                    newData[i] = data[i];
-                }
-                data = newData;
+        void markDeadLocalVariables(final int fromSlot, final int slotCount) {
+            final int localCount = localVariableTypes.size();
+            if(fromSlot >= localCount) {
+                return;
             }
-            data[sp++] = type;
+            final int toSlot = Math.min(fromSlot + slotCount, localCount);
+            invalidateLocalLoadsOnStack(fromSlot, toSlot);
+            for(int i = fromSlot; i < toSlot; ++i) {
+                localVariableTypes.set(i, Type.UNKNOWN);
+            }
         }
 
-        Type peek() {
-            return peek(0);
+        @SuppressWarnings("unchecked")
+        List<Type> getLocalVariableTypesCopy() {
+            return (List<Type>)((ArrayList<Type>)localVariableTypes).clone();
         }
 
-        Type peek(final int n) {
-            int pos = sp - 1 - n;
-            return pos < 0 ? null : data[pos];
+        BitSet getSymbolBoundaryCopy() {
+            return (BitSet)symbolBoundary.clone();
+        }
+
+        /**
+         * Returns a list of local variable slot types, but for those symbols that have multiple values, only the slot
+         * holding the widest type is marked as live.
+         * @return a list of widest local variable slot types.
+         */
+        List<Type> getWidestLiveLocals(final List<Type> lvarTypes) {
+            final List<Type> widestLiveLocals = new ArrayList<>(lvarTypes);
+            boolean keepNextValue = true;
+            final int size = widestLiveLocals.size();
+            for(int i = size - 1; i-- > 0;) {
+                if(symbolBoundary.get(i)) {
+                    keepNextValue = true;
+                }
+                final Type t = widestLiveLocals.get(i);
+                if(t != Type.UNKNOWN) {
+                    if(keepNextValue) {
+                        if(t != Type.SLOT_2) {
+                            keepNextValue = false;
+                        }
+                    } else {
+                        widestLiveLocals.set(i, Type.UNKNOWN);
+                    }
+                }
+            }
+            widestLiveLocals.subList(Math.max(getFirstDeadLocal(widestLiveLocals), firstTemp), widestLiveLocals.size()).clear();
+            return widestLiveLocals;
+        }
+
+        String markSymbolBoundariesInLvarTypesDescriptor(final String lvarDescriptor) {
+            final char[] chars = lvarDescriptor.toCharArray();
+            int j = 0;
+            for(int i = 0; i < chars.length; ++i) {
+                final char c = chars[i];
+                final int nextj = j + CodeGeneratorLexicalContext.getTypeForSlotDescriptor(c).getSlots();
+                if(!symbolBoundary.get(nextj - 1)) {
+                    chars[i] = Character.toLowerCase(c);
+                }
+                j = nextj;
+            }
+            return new String(chars);
         }
 
         Type pop() {
+            assert sp > 0;
             return data[--sp];
         }
 
-        Stack copy() {
-            return new Stack(data, sp);
+        @Override
+        public Stack clone() {
+            try {
+                final Stack clone = (Stack)super.clone();
+                clone.data = data.clone();
+                clone.localLoads = localLoads.clone();
+                clone.symbolBoundary = getSymbolBoundaryCopy();
+                clone.localVariableTypes = getLocalVariableTypesCopy();
+                return clone;
+            } catch(final CloneNotSupportedException e) {
+                throw new AssertionError("", e);
+            }
+        }
+
+        private Stack cloneWithEmptyStack() {
+            final Stack stack = clone();
+            stack.sp = 0;
+            return stack;
+        }
+
+        int getTopLocalLoad() {
+            return localLoads[sp - 1];
+        }
+
+        void markLocalLoad(final int slot) {
+            localLoads[sp - 1] = slot;
+        }
+
+        /**
+         * Performs various bookeeping when a value is stored in a local variable slot.
+         * @param slot the slot written to
+         * @param onlySymbolLiveValue if true, this is the symbol's only live value, and other values of the symbol
+         * should be marked dead
+         * @param Type the type written to the slot
+         */
+        void onLocalStore(final Type type, final int slot, final boolean onlySymbolLiveValue) {
+            if(onlySymbolLiveValue) {
+                final int fromSlot = slot == 0 ? 0 : (symbolBoundary.previousSetBit(slot - 1) + 1);
+                final int toSlot = symbolBoundary.nextSetBit(slot) + 1;
+                for(int i = fromSlot; i < toSlot; ++i) {
+                    localVariableTypes.set(i, Type.UNKNOWN);
+                }
+                invalidateLocalLoadsOnStack(fromSlot, toSlot);
+            } else {
+                invalidateLocalLoadsOnStack(slot, slot + type.getSlots());
+            }
+
+            localVariableTypes.set(slot, type);
+            if(type.isCategory2()) {
+                localVariableTypes.set(slot + 1, Type.SLOT_2);
+            }
+        }
+
+        /**
+         * Given a slot range, invalidate knowledge about local loads on stack from these slots (because they're being
+         * killed).
+         * @param fromSlot first slot, inclusive.
+         * @param toSlot last slot, exclusive.
+         */
+        private void invalidateLocalLoadsOnStack(final int fromSlot, final int toSlot) {
+            for(int i = 0; i < sp; ++i) {
+                final int localLoad = localLoads[i];
+                if(localLoad >= fromSlot && localLoad < toSlot) {
+                    localLoads[i] = NON_LOAD;
+                }
+            }
+        }
+
+        /**
+         * Marks a range of slots as belonging to a defined local variable. The slots will start out with no live value
+         * in them.
+         * @param fromSlot first slot, inclusive.
+         * @param toSlot last slot, exclusive.
+         */
+        void defineBlockLocalVariable(final int fromSlot, final int toSlot) {
+            defineLocalVariable(fromSlot, toSlot);
+            assert firstTemp < toSlot;
+            firstTemp = toSlot;
+        }
+
+        /**
+         * Defines a new temporary local variable and returns its allocated index.
+         * @param width the required width (in slots) for the new variable.
+         * @return the bytecode slot index where the newly allocated local begins.
+         */
+        int defineTemporaryLocalVariable(final int width) {
+            final int fromSlot = getUsedSlotsWithLiveTemporaries();
+            defineLocalVariable(fromSlot, fromSlot + width);
+            return fromSlot;
+        }
+
+        /**
+         * Marks a range of slots as belonging to a defined temporary local variable. The slots will start out with no
+         * live value in them.
+         * @param fromSlot first slot, inclusive.
+         * @param toSlot last slot, exclusive.
+         */
+        void defineTemporaryLocalVariable(final int fromSlot, final int toSlot) {
+            defineLocalVariable(fromSlot, toSlot);
+        }
+
+        private void defineLocalVariable(final int fromSlot, final int toSlot) {
+            assert !hasLoadsOnStack(fromSlot, toSlot);
+            assert fromSlot < toSlot;
+            symbolBoundary.clear(fromSlot, toSlot - 1);
+            symbolBoundary.set(toSlot - 1);
+            final int lastExisting = Math.min(toSlot, localVariableTypes.size());
+            for(int i = fromSlot; i < lastExisting; ++i) {
+                localVariableTypes.set(i, Type.UNKNOWN);
+            }
+            for(int i = lastExisting; i < toSlot; ++i) {
+                localVariableTypes.add(i, Type.UNKNOWN);
+            }
+        }
+
+        /**
+         * Undefines all local variables past the specified slot.
+         * @param fromSlot the first slot to be undefined
+         * @param canTruncateSymbol if false, the fromSlot must be either the first slot of a symbol, or the first slot
+         * after the last symbol. If true, the fromSlot can be in the middle of the storage area for a symbol. This
+         * should be used with care - it is only meant for use in optimism exception handlers.
+         */
+        void undefineLocalVariables(final int fromSlot, final boolean canTruncateSymbol) {
+            final int lvarCount = localVariableTypes.size();
+            assert lvarCount == symbolBoundary.length();
+            assert !hasLoadsOnStack(fromSlot, lvarCount);
+            if(canTruncateSymbol) {
+                if(fromSlot > 0) {
+                    symbolBoundary.set(fromSlot - 1);
+                }
+            } else {
+                assert fromSlot == 0 || symbolBoundary.get(fromSlot - 1);
+            }
+            if(fromSlot < lvarCount) {
+                symbolBoundary.clear(fromSlot, lvarCount);
+                localVariableTypes.subList(fromSlot, lvarCount).clear();
+            }
+            firstTemp = Math.min(fromSlot, firstTemp);
+            assert symbolBoundary.length() == localVariableTypes.size();
+            assert symbolBoundary.length() == fromSlot;
+        }
+
+        private void markAsOptimisticCatchHandler(final int liveLocalCount) {
+            // Live temporaries that are no longer on stack are undefined
+            undefineLocalVariables(liveLocalCount, true);
+            // Temporaries are promoted
+            firstTemp = liveLocalCount;
+            // No trailing undefineds
+            localVariableTypes.subList(firstTemp, localVariableTypes.size()).clear();
+            assert symbolBoundary.length() == firstTemp;
+            // Generalize all reference types to Object, and promote boolean to int
+            for(final ListIterator<Type> it = localVariableTypes.listIterator(); it.hasNext();) {
+                final Type type = it.next();
+                if(type == Type.BOOLEAN) {
+                    it.set(Type.INT);
+                } else if(type.isObject() && type != Type.OBJECT) {
+                    it.set(Type.OBJECT);
+                }
+            }
+        }
+
+        /**
+         * Returns true if any loads on the stack come from the specified slot range.
+         * @param fromSlot start of the range (inclusive)
+         * @param toSlot end of the range (exclusive)
+         * @return true if any loads on the stack come from the specified slot range.
+         */
+        boolean hasLoadsOnStack(final int fromSlot, final int toSlot) {
+            for(int i = 0; i < sp; ++i) {
+                final int load = localLoads[i];
+                if(load >= fromSlot && load < toSlot) {
+                    return true;
+                }
+            }
+            return false;
         }
 
         @Override
         public String toString() {
-            final StringBuilder builder = new StringBuilder("[");
-            for (int i = 0; i < sp; i++) {
-                builder.append(data[i]);
-                if (i < sp - 1) {
-                    builder.append(", ");
-                }
-            }
-            return builder.append("]").toString();
+            return "stack=" + Arrays.toString(Arrays.copyOf(data, sp))
+                 + ", symbolBoundaries=" + String.valueOf(symbolBoundary)
+                 + ", firstTemp=" + firstTemp
+                 + ", localTypes=" + String.valueOf(localVariableTypes)
+                 ;
         }
     }
 
+    /** Next id for debugging purposes, remove if footprint becomes unmanageable */
+    private static int nextId = 0;
+
     /** Name of this label */
     private final String name;
 
@@ -128,6 +496,14 @@
     /** ASM representation of this label */
     private jdk.internal.org.objectweb.asm.Label label;
 
+    /** Id for debugging purposes, remove if footprint becomes unmanageable */
+    private final int id;
+
+    /** Is this label reachable (anything ever jumped to it)? */
+    private boolean reachable;
+
+    private boolean breakTarget;
+
     /**
      * Constructor
      *
@@ -136,6 +512,7 @@
     public Label(final String name) {
         super();
         this.name = name;
+        this.id   = nextId++;
     }
 
     /**
@@ -146,9 +523,9 @@
     public Label(final Label label) {
         super();
         this.name = label.name;
+        this.id   = label.id;
     }
 
-
     jdk.internal.org.objectweb.asm.Label getLabel() {
         if (this.label == null) {
             this.label = new jdk.internal.org.objectweb.asm.Label();
@@ -160,12 +537,61 @@
         return stack;
     }
 
-    void setStack(final Label.Stack stack) {
-        this.stack = stack;
+    void joinFrom(final Label.Stack joinOrigin) {
+        this.reachable = true;
+        if(stack == null) {
+            stack = joinOrigin.clone();
+        } else {
+            stack.joinFrom(joinOrigin, breakTarget);
+        }
+    }
+
+    void joinFromTry(final Label.Stack joinOrigin, final boolean isOptimismHandler) {
+        this.reachable = true;
+        if (stack == null) {
+            if(!isOptimismHandler) {
+                stack = joinOrigin.cloneWithEmptyStack();
+                // Optimism handler needs temporaries to remain live, others don't.
+                stack.undefineLocalVariables(stack.firstTemp, false);
+            }
+        } else {
+            assert !isOptimismHandler;
+            stack.joinFromTry(joinOrigin);
+        }
+    }
+
+    void markAsBreakTarget() {
+        breakTarget = true;
+    }
+
+    boolean isBreakTarget() {
+        return breakTarget;
+    }
+
+    void onCatch() {
+        if(stack != null) {
+            stack = stack.cloneWithEmptyStack();
+        }
+    }
+    void markAsOptimisticCatchHandler(final Label.Stack currentStack, final int liveLocalCount) {
+        stack = currentStack.cloneWithEmptyStack();
+        stack.markAsOptimisticCatchHandler(liveLocalCount);
+    }
+
+    void markAsOptimisticContinuationHandlerFor(final Label afterConsumeStackLabel) {
+        stack = afterConsumeStackLabel.stack.cloneWithEmptyStack();
+    }
+
+    boolean isReachable() {
+        return reachable;
+    }
+
+    boolean isAfter(final Label other) {
+        return label.getOffset() > other.label.getOffset();
     }
 
     @Override
     public String toString() {
-        return name + '_' + Debug.id(this);
+        return name + '_' + id;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java b/nashorn/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java
new file mode 100644
index 0000000..8ee1e9e
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/LocalStateRestorationInfo.java
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+package jdk.nashorn.internal.codegen;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Encapsulates the information for restoring the local state when continuing execution after a rewrite triggered by
+ * an optimistic assumption failure. An instance of this class is specific to a program point.
+ *
+ */
+public class LocalStateRestorationInfo {
+    private final Type[] localVariableTypes;
+    private final int[] stackLoads;
+
+    LocalStateRestorationInfo(final Type[] localVariableTypes, final int[] stackLoads) {
+        this.localVariableTypes = localVariableTypes;
+        this.stackLoads = stackLoads;
+    }
+
+    /**
+     * Returns the types of the local variables at the continuation of a program point.
+     * @return the types of the local variables at the continuation of a program point.
+     */
+    public Type[] getLocalVariableTypes() {
+        return localVariableTypes.clone();
+    }
+
+    /**
+     * Returns the indices of local variables that need to be loaded on stack before jumping to the continuation of the
+     * program point.
+     * @return the indices of local variables that need to be loaded on stack.
+     */
+    public int[] getStackLoads() {
+        return stackLoads.clone();
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java b/nashorn/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
new file mode 100644
index 0000000..130bd66
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/LocalVariableTypesCalculator.java
@@ -0,0 +1,1489 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
+import static jdk.nashorn.internal.ir.Expression.isAlwaysFalse;
+import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BaseNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.Block;
+import jdk.nashorn.internal.ir.BreakNode;
+import jdk.nashorn.internal.ir.BreakableNode;
+import jdk.nashorn.internal.ir.CaseNode;
+import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ContinueNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessor;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.JumpStatement;
+import jdk.nashorn.internal.ir.LabelNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LexicalContextNode;
+import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
+import jdk.nashorn.internal.ir.LoopNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.PropertyNode;
+import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.RuntimeNode;
+import jdk.nashorn.internal.ir.RuntimeNode.Request;
+import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Statement;
+import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TernaryNode;
+import jdk.nashorn.internal.ir.ThrowNode;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.WhileNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
+import jdk.nashorn.internal.parser.TokenType;
+
+/**
+ * Calculates types for local variables. For purposes of local variable type calculation, the only types used are
+ * Undefined, boolean, int, long, double, and Object. The calculation eagerly widens types of local variable to their
+ * widest at control flow join points.
+ * TODO: investigate a more sophisticated solution that uses use/def information to only widens the type of a local
+ * variable to its widest used type after the join point. That would eliminate some widenings of undefined variables to
+ * object, most notably those used only in loops. We need a full liveness analysis for that. Currently, we can establish
+ * per-type liveness, which eliminates most of unwanted dead widenings.
+ */
+final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
+
+    private static class JumpOrigin {
+        final JoinPredecessor node;
+        final Map<Symbol, LvarType> types;
+
+        JumpOrigin(final JoinPredecessor node, final Map<Symbol, LvarType> types) {
+            this.node = node;
+            this.types = types;
+        }
+    }
+
+    private static class JumpTarget {
+        private final List<JumpOrigin> origins = new LinkedList<>();
+        private Map<Symbol, LvarType> types = Collections.emptyMap();
+
+        void addOrigin(final JoinPredecessor originNode, final Map<Symbol, LvarType> originTypes) {
+            origins.add(new JumpOrigin(originNode, originTypes));
+            this.types = getUnionTypes(this.types, originTypes);
+        }
+    }
+    private enum LvarType {
+        UNDEFINED(Type.UNDEFINED),
+        BOOLEAN(Type.BOOLEAN),
+        INT(Type.INT),
+        LONG(Type.LONG),
+        DOUBLE(Type.NUMBER),
+        OBJECT(Type.OBJECT);
+
+        private final Type type;
+        private LvarType(final Type type) {
+            this.type = type;
+        }
+    }
+
+    private static final Map<Type, LvarType> TO_LVAR_TYPE = new IdentityHashMap<>();
+
+    static {
+        for(final LvarType lvarType: LvarType.values()) {
+            TO_LVAR_TYPE.put(lvarType.type, lvarType);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private static IdentityHashMap<Symbol, LvarType> cloneMap(final Map<Symbol, LvarType> map) {
+        return (IdentityHashMap<Symbol, LvarType>)((IdentityHashMap<?,?>)map).clone();
+    }
+
+    private LocalVariableConversion createConversion(final Symbol symbol, final LvarType branchLvarType,
+            final Map<Symbol, LvarType> joinLvarTypes, final LocalVariableConversion next) {
+        final LvarType targetType = joinLvarTypes.get(symbol);
+        assert targetType != null;
+        if(targetType == branchLvarType) {
+            return next;
+        }
+        // NOTE: we could naively just use symbolIsUsed(symbol, branchLvarType) here, but that'd be wrong. While
+        // technically a conversion will read the value of the symbol with that type, but it will also write it to a new
+        // type, and that type might be dead (we can't know yet). For this reason, we don't treat conversion reads as
+        // real uses until we know their target type is live. If we didn't do this, and just did a symbolIsUsed here,
+        // we'd introduce false live variables which could nevertheless turn into dead ones in a subsequent
+        // deoptimization, causing a shift in the list of live locals that'd cause erroneous restoration of
+        // continuations (since RewriteException's byteCodeSlots carries an array and not a name-value map).
+
+        symbolIsConverted(symbol, branchLvarType, targetType);
+        //symbolIsUsed(symbol, branchLvarType);
+        return new LocalVariableConversion(symbol, branchLvarType.type, targetType.type, next);
+    }
+
+    private static Map<Symbol, LvarType> getUnionTypes(final Map<Symbol, LvarType> types1, final Map<Symbol, LvarType> types2) {
+        if(types1 == types2 || types1.isEmpty()) {
+            return types2;
+        } else if(types2.isEmpty()) {
+            return types1;
+        }
+        final Set<Symbol> commonSymbols = new HashSet<>(types1.keySet());
+        commonSymbols.retainAll(types2.keySet());
+        // We have a chance of returning an unmodified set if both sets have the same keys and one is strictly wider
+        // than the other.
+        final int commonSize = commonSymbols.size();
+        final int types1Size = types1.size();
+        final int types2Size = types2.size();
+        if(commonSize == types1Size && commonSize == types2Size) {
+            boolean matches1 = true, matches2 = true;
+            Map<Symbol, LvarType> union = null;
+            for(final Symbol symbol: commonSymbols) {
+                final LvarType type1 = types1.get(symbol);
+                final LvarType type2 = types2.get(symbol);
+                final LvarType widest = widestLvarType(type1,  type2);
+                if(widest != type1 && matches1) {
+                    matches1 = false;
+                    if(!matches2) {
+                        union = cloneMap(types1);
+                    }
+                }
+                if (widest != type2 && matches2) {
+                    matches2 = false;
+                    if(!matches1) {
+                        union = cloneMap(types2);
+                    }
+                }
+                if(!(matches1 || matches2) && union != null) { //remove overly enthusiastic "union can be null" warning
+                    assert union != null;
+                    union.put(symbol, widest);
+                }
+            }
+            return matches1 ? types1 : matches2 ? types2 : union;
+        }
+        // General case
+        final Map<Symbol, LvarType> union;
+        if(types1Size > types2Size) {
+            union = cloneMap(types1);
+            union.putAll(types2);
+        } else {
+            union = cloneMap(types2);
+            union.putAll(types1);
+        }
+        for(final Symbol symbol: commonSymbols) {
+            final LvarType type1 = types1.get(symbol);
+            final LvarType type2 = types2.get(symbol);
+            union.put(symbol, widestLvarType(type1,  type2));
+        }
+        return union;
+    }
+
+    private static void symbolIsUsed(final Symbol symbol, final LvarType type) {
+        if(type != LvarType.UNDEFINED) {
+            symbol.setHasSlotFor(type.type);
+        }
+    }
+
+    private static class SymbolConversions {
+        private static byte I2L = 1 << 0;
+        private static byte I2D = 1 << 1;
+        private static byte I2O = 1 << 2;
+        private static byte L2D = 1 << 3;
+        private static byte L2O = 1 << 4;
+        private static byte D2O = 1 << 5;
+
+        private byte conversions;
+
+        void recordConversion(final LvarType from, final LvarType to) {
+            switch(from) {
+            case UNDEFINED:
+                return;
+            case INT:
+            case BOOLEAN:
+                switch(to) {
+                case LONG:
+                    recordConversion(I2L);
+                    return;
+                case DOUBLE:
+                    recordConversion(I2D);
+                    return;
+                case OBJECT:
+                    recordConversion(I2O);
+                    return;
+                default:
+                    illegalConversion(from, to);
+                    return;
+                }
+            case LONG:
+                switch(to) {
+                case DOUBLE:
+                    recordConversion(L2D);
+                    return;
+                case OBJECT:
+                    recordConversion(L2O);
+                    return;
+                default:
+                    illegalConversion(from, to);
+                    return;
+                }
+            case DOUBLE:
+                if(to == LvarType.OBJECT) {
+                    recordConversion(D2O);
+                }
+                return;
+            default:
+                illegalConversion(from, to);
+            }
+        }
+
+        private static void illegalConversion(final LvarType from, final LvarType to) {
+            throw new AssertionError("Invalid conversion from " + from + " to " + to);
+        }
+
+        void recordConversion(final byte convFlag) {
+            conversions = (byte)(conversions | convFlag);
+        }
+
+        boolean hasConversion(final byte convFlag) {
+            return (conversions & convFlag) != 0;
+        }
+
+        void calculateTypeLiveness(final Symbol symbol) {
+            if(symbol.hasSlotFor(Type.OBJECT)) {
+                if(hasConversion(D2O)) {
+                    symbol.setHasSlotFor(Type.NUMBER);
+                }
+                if(hasConversion(L2O)) {
+                    symbol.setHasSlotFor(Type.LONG);
+                }
+                if(hasConversion(I2O)) {
+                    symbol.setHasSlotFor(Type.INT);
+                }
+            }
+            if(symbol.hasSlotFor(Type.NUMBER)) {
+                if(hasConversion(L2D)) {
+                    symbol.setHasSlotFor(Type.LONG);
+                }
+                if(hasConversion(I2D)) {
+                    symbol.setHasSlotFor(Type.INT);
+                }
+            }
+            if(symbol.hasSlotFor(Type.LONG)) {
+                if(hasConversion(I2L)) {
+                    symbol.setHasSlotFor(Type.INT);
+                }
+            }
+        }
+    }
+
+    private void symbolIsConverted(final Symbol symbol, final LvarType from, final LvarType to) {
+        SymbolConversions conversions = symbolConversions.get(symbol);
+        if(conversions == null) {
+            conversions = new SymbolConversions();
+            symbolConversions.put(symbol, conversions);
+        }
+        conversions.recordConversion(from, to);
+    }
+
+    private static LvarType toLvarType(final Type type) {
+        assert type != null;
+        final LvarType lvarType = TO_LVAR_TYPE.get(type);
+        if(lvarType != null) {
+            return lvarType;
+        }
+        assert type.isObject();
+        return LvarType.OBJECT;
+    }
+    private static LvarType widestLvarType(final LvarType t1, final LvarType t2) {
+        if(t1 == t2) {
+            return t1;
+        }
+        // Undefined or boolean to anything always widens to object.
+        if(t1.ordinal() < LvarType.INT.ordinal() || t2.ordinal() < LvarType.INT.ordinal()) {
+            return LvarType.OBJECT;
+        }
+        // NOTE: we allow "widening" of long to double even though it can lose precision. ECMAScript doesn't have an
+        // Int64 type anyway, so this loss of precision is actually more conformant to the specification...
+        return LvarType.values()[Math.max(t1.ordinal(), t2.ordinal())];
+    }
+    private final Compiler compiler;
+    private final Map<Label, JumpTarget> jumpTargets = new IdentityHashMap<>();
+    // Local variable type mapping at the currently evaluated point. No map instance is ever modified; setLvarType() always
+    // allocates a new map. Immutability of maps allows for cheap snapshots by just keeping the reference to the current
+    // value.
+    private Map<Symbol, LvarType> localVariableTypes = new IdentityHashMap<>();
+
+    // Whether the current point in the AST is reachable code
+    private boolean reachable = true;
+    // Return type of the function
+    private Type returnType = Type.UNKNOWN;
+    // Synthetic return node that we must insert at the end of the function if it's end is reachable.
+    private ReturnNode syntheticReturn;
+
+    // Topmost current split node (if any)
+    private SplitNode topSplit;
+    private boolean split;
+
+    private boolean alreadyEnteredTopLevelFunction;
+
+    // LvarType and conversion information gathered during the top-down pass; applied to nodes in the bottom-up pass.
+    private final Map<JoinPredecessor, LocalVariableConversion> localVariableConversions = new IdentityHashMap<>();
+
+    private final Map<IdentNode, LvarType> identifierLvarTypes = new IdentityHashMap<>();
+    private final Map<Symbol, SymbolConversions> symbolConversions = new IdentityHashMap<>();
+
+    private SymbolToType symbolToType = new SymbolToType();
+
+    // Stack of open labels for starts of catch blocks, one for every currently traversed try block; for inserting
+    // control flow edges to them. Note that we currently don't insert actual control flow edges, but instead edges that
+    // help us with type calculations. This means that some operations that can result in an exception being thrown
+    // aren't considered (function calls, side effecting property getters and setters etc.), while some operations that
+    // don't result in control flow transfers do originate an edge to the catch blocks (namely, assignments to local
+    // variables).
+    private final Deque<Label> catchLabels = new ArrayDeque<>();
+
+    LocalVariableTypesCalculator(final Compiler compiler) {
+        super(new LexicalContext());
+        this.compiler = compiler;
+    }
+
+    private JumpTarget createJumpTarget(final Label label) {
+        assert !jumpTargets.containsKey(label);
+        final JumpTarget jumpTarget = new JumpTarget();
+        jumpTargets.put(label, jumpTarget);
+        return jumpTarget;
+    }
+
+    private void doesNotContinueSequentially() {
+        reachable = false;
+        localVariableTypes = Collections.emptyMap();
+    }
+
+
+    @Override
+    public boolean enterBinaryNode(final BinaryNode binaryNode) {
+        final Expression lhs = binaryNode.lhs();
+        final Expression rhs = binaryNode.rhs();
+        final boolean isAssignment = binaryNode.isAssignment();
+
+        final TokenType tokenType = Token.descType(binaryNode.getToken());
+        if(tokenType.isLeftAssociative()) {
+            assert !isAssignment;
+            final boolean isLogical = binaryNode.isLogical();
+            final Label joinLabel = isLogical ? new Label("") : null;
+            lhs.accept(this);
+            if(isLogical) {
+                jumpToLabel((JoinPredecessor)lhs, joinLabel);
+            }
+            rhs.accept(this);
+            if(isLogical) {
+                jumpToLabel((JoinPredecessor)rhs, joinLabel);
+            }
+            joinOnLabel(joinLabel);
+        } else {
+            rhs.accept(this);
+            if(isAssignment) {
+                if(lhs instanceof BaseNode) {
+                    ((BaseNode)lhs).getBase().accept(this);
+                    if(lhs instanceof IndexNode) {
+                        ((IndexNode)lhs).getIndex().accept(this);
+                    } else {
+                        assert lhs instanceof AccessNode;
+                    }
+                } else {
+                    assert lhs instanceof IdentNode;
+                    if(binaryNode.isSelfModifying()) {
+                        ((IdentNode)lhs).accept(this);
+                    }
+                }
+            } else {
+                lhs.accept(this);
+            }
+        }
+
+        if(isAssignment && lhs instanceof IdentNode) {
+            if(binaryNode.isSelfModifying()) {
+                onSelfAssignment((IdentNode)lhs, binaryNode);
+            } else {
+                onAssignment((IdentNode)lhs, rhs);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean enterBlock(final Block block) {
+        for(final Symbol symbol: block.getSymbols()) {
+            if(symbol.isBytecodeLocal() && getLocalVariableTypeOrNull(symbol) == null) {
+                setType(symbol, LvarType.UNDEFINED);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public boolean enterBreakNode(final BreakNode breakNode) {
+        if(!reachable) {
+            return false;
+        }
+
+        final BreakableNode target = lc.getBreakable(breakNode.getLabelName());
+        return splitAwareJumpToLabel(breakNode, target, target.getBreakLabel());
+    }
+
+    @Override
+    public boolean enterContinueNode(final ContinueNode continueNode) {
+        if(!reachable) {
+            return false;
+        }
+        final LoopNode target = lc.getContinueTo(continueNode.getLabelName());
+        return splitAwareJumpToLabel(continueNode, target, target.getContinueLabel());
+    }
+
+    private boolean splitAwareJumpToLabel(final JumpStatement jumpStatement, final BreakableNode target, final Label targetLabel) {
+        final JoinPredecessor jumpOrigin;
+        if(topSplit != null && lc.isExternalTarget(topSplit, target)) {
+            // If the jump target is outside the topmost split node, then we'll create a synthetic jump origin in the
+            // split node.
+            jumpOrigin = new JoinPredecessorExpression();
+            topSplit.addJump(jumpOrigin, targetLabel);
+        } else {
+            // Otherwise, the original jump statement is the jump origin
+            jumpOrigin = jumpStatement;
+        }
+
+        jumpToLabel(jumpOrigin, targetLabel, getBreakTargetTypes(target));
+        doesNotContinueSequentially();
+        return false;
+    }
+
+    @Override
+    protected boolean enterDefault(final Node node) {
+        return reachable;
+    }
+
+    private void enterDoWhileLoop(final WhileNode loopNode) {
+        final JoinPredecessorExpression test = loopNode.getTest();
+        final Block body = loopNode.getBody();
+        final Label continueLabel = loopNode.getContinueLabel();
+        final Label breakLabel = loopNode.getBreakLabel();
+        final Map<Symbol, LvarType> beforeLoopTypes = localVariableTypes;
+        final Label repeatLabel = new Label("");
+        for(;;) {
+            jumpToLabel(loopNode, repeatLabel, beforeLoopTypes);
+            final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes;
+            body.accept(this);
+            if(reachable) {
+                jumpToLabel(body, continueLabel);
+            }
+            joinOnLabel(continueLabel);
+            if(!reachable) {
+                break;
+            }
+            test.accept(this);
+            jumpToLabel(test, breakLabel);
+            if(isAlwaysFalse(test)) {
+                break;
+            }
+            jumpToLabel(test, repeatLabel);
+            joinOnLabel(repeatLabel);
+            if(localVariableTypes.equals(beforeRepeatTypes)) {
+                break;
+            }
+            resetJoinPoint(continueLabel);
+            resetJoinPoint(breakLabel);
+            resetJoinPoint(repeatLabel);
+        }
+
+        if(isAlwaysTrue(test)) {
+            doesNotContinueSequentially();
+        }
+
+        leaveBreakable(loopNode);
+    }
+
+    @Override
+    public boolean enterForNode(final ForNode forNode) {
+        if(!reachable) {
+            return false;
+        }
+
+        final Expression init = forNode.getInit();
+        if(forNode.isForIn()) {
+            forNode.getModify().accept(this);
+            enterTestFirstLoop(forNode, null, init);
+        } else {
+            if(init != null) {
+                init.accept(this);
+            }
+            enterTestFirstLoop(forNode, forNode.getModify(), null);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        if(alreadyEnteredTopLevelFunction) {
+            return false;
+        }
+        int pos = 0;
+        if(!functionNode.isVarArg()) {
+            for (final IdentNode param : functionNode.getParameters()) {
+                final Symbol symbol = param.getSymbol();
+                // Parameter is not necessarily bytecode local as it can be scoped due to nested context use, but it
+                // must have a slot if we aren't in a function with vararg signature.
+                assert symbol.hasSlot();
+                final Type callSiteParamType = compiler.getParamType(functionNode, pos);
+                final LvarType paramType = callSiteParamType == null ? LvarType.OBJECT : toLvarType(callSiteParamType);
+                setType(symbol, paramType);
+                // Make sure parameter slot for its incoming value is not marked dead. NOTE: this is a heuristic. Right
+                // now, CodeGenerator.expandParameters() relies on the fact that every parameter's final slot width will
+                // be at least the same as incoming width, therefore even if a parameter is never read, we'll still keep
+                // its slot.
+                symbolIsUsed(symbol);
+                setIdentifierLvarType(param, paramType);
+                pos++;
+            }
+        }
+        setCompilerConstantAsObject(functionNode, CompilerConstants.THIS);
+
+        // TODO: coarse-grained. If we wanted to solve it completely precisely,
+        // we'd also need to push/pop its type when handling WithNode (so that
+        // it can go back to undefined after a 'with' block.
+        if(functionNode.hasScopeBlock() || functionNode.needsParentScope()) {
+            setCompilerConstantAsObject(functionNode, CompilerConstants.SCOPE);
+        }
+        if(functionNode.needsCallee()) {
+            setCompilerConstantAsObject(functionNode, CompilerConstants.CALLEE);
+        }
+        if(functionNode.needsArguments()) {
+            setCompilerConstantAsObject(functionNode, CompilerConstants.ARGUMENTS);
+        }
+
+        alreadyEnteredTopLevelFunction = true;
+        return true;
+    }
+
+    @Override
+    public boolean enterIdentNode(final IdentNode identNode) {
+        final Symbol symbol = identNode.getSymbol();
+        if(symbol.isBytecodeLocal()) {
+            symbolIsUsed(symbol);
+            setIdentifierLvarType(identNode, getLocalVariableType(symbol));
+        }
+        return false;
+    }
+
+    @Override
+    public boolean enterIfNode(final IfNode ifNode) {
+        if(!reachable) {
+            return false;
+        }
+
+        final Expression test = ifNode.getTest();
+        final Block pass = ifNode.getPass();
+        final Block fail = ifNode.getFail();
+
+        test.accept(this);
+
+        final Map<Symbol, LvarType> afterTestLvarTypes = localVariableTypes;
+        if(!isAlwaysFalse(test)) {
+            pass.accept(this);
+        }
+        final Map<Symbol, LvarType> passLvarTypes = localVariableTypes;
+        final boolean reachableFromPass = reachable;
+
+        reachable = true;
+        localVariableTypes = afterTestLvarTypes;
+        if(!isAlwaysTrue(test) && fail != null) {
+            fail.accept(this);
+            final boolean reachableFromFail = reachable;
+            reachable |= reachableFromPass;
+            if(!reachable) {
+                return false;
+            }
+
+            if(reachableFromFail) {
+                if(reachableFromPass) {
+                    final Map<Symbol, LvarType> failLvarTypes = localVariableTypes;
+                    localVariableTypes = getUnionTypes(passLvarTypes, failLvarTypes);
+                    setConversion(pass, passLvarTypes, localVariableTypes);
+                    setConversion(fail, failLvarTypes, localVariableTypes);
+                }
+                return false;
+            }
+        }
+
+        if(reachableFromPass) {
+            localVariableTypes = getUnionTypes(afterTestLvarTypes, passLvarTypes);
+            // IfNode itself is associated with conversions that might need to be performed after the test if there's no
+            // else branch. E.g.
+            // if(x = 1, cond) { x = 1.0 } must widen "x = 1" to a double.
+            setConversion(pass, passLvarTypes, localVariableTypes);
+            setConversion(ifNode, afterTestLvarTypes, localVariableTypes);
+        } else {
+            localVariableTypes = afterTestLvarTypes;
+        }
+
+        return false;
+    }
+
+    @Override
+    public boolean enterPropertyNode(final PropertyNode propertyNode) {
+        // Avoid falsely adding property keys to the control flow graph
+        if(propertyNode.getValue() != null) {
+            propertyNode.getValue().accept(this);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean enterReturnNode(final ReturnNode returnNode) {
+        final Expression returnExpr = returnNode.getExpression();
+        final Type returnExprType;
+        if(returnExpr != null) {
+            returnExpr.accept(this);
+            returnExprType = getType(returnExpr);
+        } else {
+            returnExprType = Type.UNDEFINED;
+        }
+        returnType = Type.widestReturnType(returnType, returnExprType);
+        doesNotContinueSequentially();
+        return false;
+    }
+
+    @Override
+    public boolean enterSplitNode(final SplitNode splitNode) {
+        // Need to visit inside of split nodes. While it's true that they don't have local variables, we need to visit
+        // breaks, continues, and returns in them.
+        if(topSplit == null) {
+            topSplit = splitNode;
+        }
+        split = true;
+        setType(getCompilerConstantSymbol(lc.getCurrentFunction(), CompilerConstants.RETURN), LvarType.UNDEFINED);
+        return true;
+    }
+
+    @Override
+    public boolean enterSwitchNode(final SwitchNode switchNode) {
+        if(!reachable) {
+            return false;
+        }
+
+        final Expression expr = switchNode.getExpression();
+        expr.accept(this);
+
+        final List<CaseNode> cases = switchNode.getCases();
+        if(cases.isEmpty()) {
+            return false;
+        }
+
+        // Control flow is different for all-integer cases where we dispatch by switch table, and for all other cases
+        // where we do sequential comparison. Note that CaseNode objects act as join points.
+        final boolean isInteger = switchNode.isInteger();
+        final Label breakLabel = switchNode.getBreakLabel();
+        final boolean hasDefault = switchNode.getDefaultCase() != null;
+
+        boolean tagUsed = false;
+        for(final CaseNode caseNode: cases) {
+            final Expression test = caseNode.getTest();
+            if(!isInteger && test != null) {
+                test.accept(this);
+                if(!tagUsed) {
+                    symbolIsUsed(switchNode.getTag(), LvarType.OBJECT);
+                    tagUsed = true;
+                }
+            }
+            // CaseNode carries the conversions that need to be performed on its entry from the test.
+            // CodeGenerator ensures these are only emitted when arriving on the branch and not through a
+            // fallthrough.
+            jumpToLabel(caseNode, caseNode.getBody().getEntryLabel());
+        }
+        if(!hasDefault) {
+            // No default case means we can arrive at the break label without entering any cases. In that case
+            // SwitchNode will carry the conversions that need to be performed before it does that jump.
+            jumpToLabel(switchNode, breakLabel);
+        }
+
+        // All cases are arrived at through jumps
+        doesNotContinueSequentially();
+
+        Block previousBlock = null;
+        for(final CaseNode caseNode: cases) {
+            final Block body = caseNode.getBody();
+            final Label entryLabel = body.getEntryLabel();
+            if(previousBlock != null && reachable) {
+                jumpToLabel(previousBlock, entryLabel);
+            }
+            joinOnLabel(entryLabel);
+            assert reachable == true;
+            body.accept(this);
+            previousBlock = body;
+        }
+        if(previousBlock != null && reachable) {
+            jumpToLabel(previousBlock, breakLabel);
+        }
+        leaveBreakable(switchNode);
+        return false;
+    }
+
+    @Override
+    public boolean enterTernaryNode(final TernaryNode ternaryNode) {
+        final Expression test = ternaryNode.getTest();
+        final Expression trueExpr = ternaryNode.getTrueExpression();
+        final Expression falseExpr = ternaryNode.getFalseExpression();
+
+        test.accept(this);
+
+        final Map<Symbol, LvarType> testExitLvarTypes = localVariableTypes;
+        if(!isAlwaysFalse(test)) {
+            trueExpr.accept(this);
+        }
+        final Map<Symbol, LvarType> trueExitLvarTypes = localVariableTypes;
+        localVariableTypes = testExitLvarTypes;
+        if(!isAlwaysTrue(test)) {
+            falseExpr.accept(this);
+        }
+        final Map<Symbol, LvarType> falseExitLvarTypes = localVariableTypes;
+        localVariableTypes = getUnionTypes(trueExitLvarTypes, falseExitLvarTypes);
+        setConversion((JoinPredecessor)trueExpr, trueExitLvarTypes, localVariableTypes);
+        setConversion((JoinPredecessor)falseExpr, falseExitLvarTypes, localVariableTypes);
+        return false;
+    }
+
+    private void enterTestFirstLoop(final LoopNode loopNode, final JoinPredecessorExpression modify, final Expression iteratorValues) {
+        final JoinPredecessorExpression test = loopNode.getTest();
+        if(isAlwaysFalse(test)) {
+            test.accept(this);
+            return;
+        }
+
+        final Label continueLabel = loopNode.getContinueLabel();
+        final Label breakLabel = loopNode.getBreakLabel();
+
+        final Label repeatLabel = modify == null ? continueLabel : new Label("");
+        final Map<Symbol, LvarType> beforeLoopTypes = localVariableTypes;
+        for(;;) {
+            jumpToLabel(loopNode, repeatLabel, beforeLoopTypes);
+            final Map<Symbol, LvarType> beforeRepeatTypes = localVariableTypes;
+            if(test != null) {
+                test.accept(this);
+            }
+            if(!isAlwaysTrue(test)) {
+                jumpToLabel(test, breakLabel);
+            }
+            if(iteratorValues instanceof IdentNode) {
+                // Receives iterator values; they're currently all objects (JDK-8034954).
+                onAssignment((IdentNode)iteratorValues, LvarType.OBJECT);
+            }
+            final Block body = loopNode.getBody();
+            body.accept(this);
+            if(reachable) {
+                jumpToLabel(body, continueLabel);
+            }
+            joinOnLabel(continueLabel);
+            if(!reachable) {
+                break;
+            }
+            if(modify != null) {
+                modify.accept(this);
+                jumpToLabel(modify, repeatLabel);
+                joinOnLabel(repeatLabel);
+            }
+            if(localVariableTypes.equals(beforeRepeatTypes)) {
+                break;
+            }
+            // Reset the join points and repeat the analysis
+            resetJoinPoint(continueLabel);
+            resetJoinPoint(breakLabel);
+            resetJoinPoint(repeatLabel);
+        }
+
+        if(isAlwaysTrue(test) && iteratorValues == null) {
+            doesNotContinueSequentially();
+        }
+
+        leaveBreakable(loopNode);
+    }
+
+    @Override
+    public boolean enterThrowNode(final ThrowNode throwNode) {
+        if(!reachable) {
+            return false;
+        }
+
+        throwNode.getExpression().accept(this);
+        jumpToCatchBlock(throwNode);
+        doesNotContinueSequentially();
+        return false;
+    }
+
+    @Override
+    public boolean enterTryNode(final TryNode tryNode) {
+        if(!reachable) {
+            return false;
+        }
+
+        // This is the label for the join point at the entry of the catch blocks.
+        final Label catchLabel = new Label("");
+        catchLabels.push(catchLabel);
+
+        // Presume that even the start of the try block can immediately go to the catch
+        jumpToLabel(tryNode, catchLabel);
+
+        final Block body = tryNode.getBody();
+        body.accept(this);
+        catchLabels.pop();
+
+        // Final exit label for the whole try/catch construct (after the try block and after all catches).
+        final Label endLabel = new Label("");
+
+        boolean canExit = false;
+        if(reachable) {
+            jumpToLabel(body, endLabel);
+            canExit = true;
+        }
+        doesNotContinueSequentially();
+
+        joinOnLabel(catchLabel);
+        for(final CatchNode catchNode: tryNode.getCatches()) {
+            final IdentNode exception = catchNode.getException();
+            onAssignment(exception, LvarType.OBJECT);
+            final Expression condition = catchNode.getExceptionCondition();
+            if(condition != null) {
+                condition.accept(this);
+            }
+            final Map<Symbol, LvarType> afterConditionTypes = localVariableTypes;
+            final Block catchBody = catchNode.getBody();
+            // TODO: currently, we consider that the catch blocks are always reachable from the try block as currently
+            // we lack enough analysis to prove that no statement before a break/continue/return in the try block can
+            // throw an exception.
+            reachable = true;
+            catchBody.accept(this);
+            final Symbol exceptionSymbol = exception.getSymbol();
+            if(reachable) {
+                localVariableTypes = cloneMap(localVariableTypes);
+                localVariableTypes.remove(exceptionSymbol);
+                jumpToLabel(catchBody, endLabel);
+                canExit = true;
+            }
+            localVariableTypes = cloneMap(afterConditionTypes);
+            localVariableTypes.remove(exceptionSymbol);
+        }
+        // NOTE: if we had one or more conditional catch blocks with no unconditional catch block following them, then
+        // there will be an unconditional rethrow, so the join point can never be reached from the last
+        // conditionExpression.
+        doesNotContinueSequentially();
+
+        if(canExit) {
+            joinOnLabel(endLabel);
+        }
+
+        return false;
+    }
+
+
+    @Override
+    public boolean enterUnaryNode(final UnaryNode unaryNode) {
+        final Expression expr = unaryNode.getExpression();
+        expr.accept(this);
+
+        if(unaryNode.isSelfModifying()) {
+            if(expr instanceof IdentNode) {
+                onSelfAssignment((IdentNode)expr, unaryNode);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public boolean enterVarNode(final VarNode varNode) {
+        final Expression init = varNode.getInit();
+        if(init != null) {
+            init.accept(this);
+            onAssignment(varNode.getName(), init);
+        }
+        return false;
+    }
+
+    @Override
+    public boolean enterWhileNode(final WhileNode whileNode) {
+        if(!reachable) {
+            return false;
+        }
+        if(whileNode.isDoWhile()) {
+            enterDoWhileLoop(whileNode);
+        } else {
+            enterTestFirstLoop(whileNode, null, null);
+        }
+        return false;
+    }
+
+    private Map<Symbol, LvarType> getBreakTargetTypes(final BreakableNode target) {
+        // Remove symbols defined in the the blocks that are being broken out of.
+        Map<Symbol, LvarType> types = localVariableTypes;
+        for(final Iterator<LexicalContextNode> it = lc.getAllNodes(); it.hasNext();) {
+            final LexicalContextNode node = it.next();
+            if(node instanceof Block) {
+                for(final Symbol symbol: ((Block)node).getSymbols()) {
+                    if(localVariableTypes.containsKey(symbol)) {
+                        if(types == localVariableTypes) {
+                            types = cloneMap(localVariableTypes);
+                        }
+                        types.remove(symbol);
+                    }
+                }
+            }
+            if(node == target) {
+                break;
+            }
+        }
+        return types;
+    }
+
+    private LvarType getLocalVariableType(final Symbol symbol) {
+        final LvarType type = getLocalVariableTypeOrNull(symbol);
+        assert type != null;
+        return type;
+    }
+
+    private LvarType getLocalVariableTypeOrNull(final Symbol symbol) {
+        return localVariableTypes.get(symbol);
+    }
+
+    private JumpTarget getOrCreateJumpTarget(final Label label) {
+        JumpTarget jumpTarget = jumpTargets.get(label);
+        if(jumpTarget == null) {
+            jumpTarget = createJumpTarget(label);
+        }
+        return jumpTarget;
+    }
+
+
+    /**
+     * If there's a join point associated with a label, insert the join point into the flow.
+     * @param label the label to insert a join point for.
+     */
+    private void joinOnLabel(final Label label) {
+        final JumpTarget jumpTarget = jumpTargets.remove(label);
+        if(jumpTarget == null) {
+            return;
+        }
+        assert !jumpTarget.origins.isEmpty();
+        reachable = true;
+        localVariableTypes = getUnionTypes(jumpTarget.types, localVariableTypes);
+        for(final JumpOrigin jumpOrigin: jumpTarget.origins) {
+            setConversion(jumpOrigin.node, jumpOrigin.types, localVariableTypes);
+        }
+    }
+
+    /**
+     * If we're in a try/catch block, add an edge from the specified node to the try node's pre-catch label.
+     */
+    private void jumpToCatchBlock(final JoinPredecessor jumpOrigin) {
+        final Label currentCatchLabel = catchLabels.peek();
+        if(currentCatchLabel != null) {
+            jumpToLabel(jumpOrigin, currentCatchLabel);
+        }
+    }
+
+    private void jumpToLabel(final JoinPredecessor jumpOrigin, final Label label) {
+        jumpToLabel(jumpOrigin, label, localVariableTypes);
+    }
+
+    private void jumpToLabel(final JoinPredecessor jumpOrigin, final Label label, final Map<Symbol, LvarType> types) {
+        getOrCreateJumpTarget(label).addOrigin(jumpOrigin, types);
+    }
+
+    @Override
+    public Node leaveBlock(final Block block) {
+        if(lc.isFunctionBody()) {
+            if(reachable) {
+                // reachable==true means we can reach the end of the function without an explicit return statement. We
+                // need to insert a synthetic one then. This logic used to be in Lower.leaveBlock(), but Lower's
+                // reachability analysis (through Terminal.isTerminal() flags) is not precise enough so
+                // Lower$BlockLexicalContext.afterSetStatements will sometimes think the control flow terminates even
+                // when it didn't. Example: function() { switch((z)) { default: {break; } throw x; } }.
+                createSyntheticReturn(block);
+                assert !reachable;
+            }
+            // We must calculate the return type here (and not in leaveFunctionNode) as it can affect the liveness of
+            // the :return symbol and thus affect conversion type liveness calculations for it.
+            calculateReturnType();
+        }
+
+        boolean cloned = false;
+        for(final Symbol symbol: block.getSymbols()) {
+            // Undefine the symbol outside the block
+            if(localVariableTypes.containsKey(symbol)) {
+                if(!cloned) {
+                    localVariableTypes = cloneMap(localVariableTypes);
+                    cloned = true;
+                }
+                localVariableTypes.remove(symbol);
+            }
+
+            if(symbol.hasSlot()) {
+                final SymbolConversions conversions = symbolConversions.get(symbol);
+                if(conversions != null) {
+                    // Potentially make some currently dead types live if they're needed as a source of a type
+                    // conversion at a join.
+                    conversions.calculateTypeLiveness(symbol);
+                }
+                if(symbol.slotCount() == 0) {
+                    // This is a local variable that is never read. It won't need a slot.
+                    symbol.setNeedsSlot(false);
+                }
+            }
+        }
+
+        if(reachable) {
+            // TODO: this is totally backwards. Block should not be breakable, LabelNode should be breakable.
+            final LabelNode labelNode = lc.getCurrentBlockLabelNode();
+            if(labelNode != null) {
+                jumpToLabel(labelNode, block.getBreakLabel());
+            }
+        }
+        leaveBreakable(block);
+        return block;
+    }
+
+    private void calculateReturnType() {
+        // NOTE: if return type is unknown, then the function does not explicitly return a value. Such a function under
+        // ECMAScript rules returns Undefined, which has Type.OBJECT. We might consider an optimization in the future
+        // where we can return void functions.
+        if(returnType.isUnknown()) {
+            returnType = Type.OBJECT;
+        }
+
+        if(split) {
+            // If the function is split, the ":return" symbol is used and needs a slot. Note we can't mark the return
+            // symbol as used in enterSplitNode, as we don't know the final return type of the function earlier than
+            // here.
+            final Symbol retSymbol = getCompilerConstantSymbol(lc.getCurrentFunction(), CompilerConstants.RETURN);
+            retSymbol.setHasSlotFor(returnType);
+            retSymbol.setNeedsSlot(true);
+        }
+    }
+
+    private void createSyntheticReturn(final Block body) {
+        final FunctionNode functionNode = lc.getCurrentFunction();
+        final long token = functionNode.getToken();
+        final int finish = functionNode.getFinish();
+        final List<Statement> statements = body.getStatements();
+        final int lineNumber = statements.isEmpty() ? functionNode.getLineNumber() : statements.get(statements.size() - 1).getLineNumber();
+        final IdentNode returnExpr;
+        if(functionNode.isProgram()) {
+            returnExpr = new IdentNode(token, finish, RETURN.symbolName()).setSymbol(getCompilerConstantSymbol(functionNode, RETURN));
+        } else {
+            returnExpr = null;
+        }
+        syntheticReturn = new ReturnNode(lineNumber, token, finish, returnExpr);
+        syntheticReturn.accept(this);
+    }
+
+    /**
+     * Leave a breakable node. If there's a join point associated with its break label (meaning there was at least one
+     * break statement to the end of the node), insert the join point into the flow.
+     * @param breakable the breakable node being left.
+     */
+    private void leaveBreakable(final BreakableNode breakable) {
+        joinOnLabel(breakable.getBreakLabel());
+    }
+
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+        // Sets the return type of the function and also performs the bottom-up pass of applying type and conversion
+        // information to nodes as well as doing the calculation on nested functions as required.
+        FunctionNode newFunction = functionNode;
+        final NodeVisitor<LexicalContext> applyChangesVisitor = new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            private boolean inOuterFunction = true;
+            private final Deque<JoinPredecessor> joinPredecessors = new ArrayDeque<>();
+
+            @Override
+            protected boolean enterDefault(final Node node) {
+                if(!inOuterFunction) {
+                    return false;
+                }
+                if(node instanceof JoinPredecessor) {
+                    joinPredecessors.push((JoinPredecessor)node);
+                }
+                return inOuterFunction;
+            }
+
+            @Override
+            public boolean enterFunctionNode(final FunctionNode fn) {
+                if(compiler.isOnDemandCompilation()) {
+                    // Only calculate nested function local variable types if we're doing eager compilation
+                    return false;
+                }
+                inOuterFunction = false;
+                return true;
+            }
+
+            @SuppressWarnings("fallthrough")
+            @Override
+            public Node leaveBinaryNode(final BinaryNode binaryNode) {
+                if(binaryNode.isComparison()) {
+                    final Expression lhs = binaryNode.lhs();
+                    final Expression rhs = binaryNode.rhs();
+
+                    Type cmpWidest = Type.widest(lhs.getType(), rhs.getType());
+                    boolean newRuntimeNode = false, finalized = false;
+                    final TokenType tt = binaryNode.tokenType();
+                    switch (tt) {
+                    case EQ_STRICT:
+                    case NE_STRICT:
+                        // Specialize comparison with undefined
+                        final Expression undefinedNode = createIsUndefined(binaryNode, lhs, rhs,
+                                tt == TokenType.EQ_STRICT ? Request.IS_UNDEFINED : Request.IS_NOT_UNDEFINED);
+                        if(undefinedNode != binaryNode) {
+                            return undefinedNode;
+                        }
+                        // Specialize comparison of boolean with non-boolean
+                        if (lhs.getType().isBoolean() != rhs.getType().isBoolean()) {
+                            newRuntimeNode = true;
+                            cmpWidest = Type.OBJECT;
+                            finalized = true;
+                        }
+                        // fallthrough
+                    default:
+                        if (newRuntimeNode || cmpWidest.isObject()) {
+                            return new RuntimeNode(binaryNode).setIsFinal(finalized);
+                        }
+                    }
+                } else if(binaryNode.isOptimisticUndecidedType()) {
+                    // At this point, we can assign a static type to the optimistic binary ADD operator as now we know
+                    // the types of its operands.
+                    return binaryNode.decideType();
+                }
+                return binaryNode;
+            }
+
+            @Override
+            protected Node leaveDefault(final Node node) {
+                if(node instanceof JoinPredecessor) {
+                    final JoinPredecessor original = joinPredecessors.pop();
+                    assert original.getClass() == node.getClass() : original.getClass().getName() + "!=" + node.getClass().getName();
+                    return (Node)setLocalVariableConversion(original, (JoinPredecessor)node);
+                }
+                return node;
+            }
+
+            @Override
+            public Node leaveBlock(final Block block) {
+                if(inOuterFunction && syntheticReturn != null && lc.isFunctionBody()) {
+                    final ArrayList<Statement> stmts = new ArrayList<>(block.getStatements());
+                    stmts.add((ReturnNode)syntheticReturn.accept(this));
+                    return block.setStatements(lc, stmts);
+                }
+                return super.leaveBlock(block);
+            }
+
+            @Override
+            public Node leaveFunctionNode(final FunctionNode nestedFunctionNode) {
+                inOuterFunction = true;
+                final FunctionNode newNestedFunction = (FunctionNode)nestedFunctionNode.accept(
+                        new LocalVariableTypesCalculator(compiler));
+                lc.replace(nestedFunctionNode, newNestedFunction);
+                return newNestedFunction;
+            }
+
+            @Override
+            public Node leaveIdentNode(final IdentNode identNode) {
+                final IdentNode original = (IdentNode)joinPredecessors.pop();
+                final Symbol symbol = identNode.getSymbol();
+                if(symbol == null) {
+                    assert identNode.isPropertyName();
+                    return identNode;
+                } else if(symbol.hasSlot()) {
+                    assert !symbol.isScope() || symbol.isParam(); // Only params can be slotted and scoped.
+                    assert original.getName().equals(identNode.getName());
+                    final LvarType lvarType = identifierLvarTypes.remove(original);
+                    if(lvarType != null) {
+                        return setLocalVariableConversion(original, identNode.setType(lvarType.type));
+                    }
+                    // If there's no type, then the identifier must've been in unreachable code. In that case, it can't
+                    // have assigned conversions either.
+                    assert localVariableConversions.get(original) == null;
+                } else {
+                    assert identIsDeadAndHasNoLiveConversions(original);
+                }
+                return identNode;
+            }
+
+            @Override
+            public Node leaveLiteralNode(final LiteralNode<?> literalNode) {
+                //for e.g. ArrayLiteralNodes the initial types may have been narrowed due to the
+                //introduction of optimistic behavior - hence ensure that all literal nodes are
+                //reinitialized
+                return literalNode.initialize(lc);
+            }
+
+            @Override
+            public Node leaveRuntimeNode(final RuntimeNode runtimeNode) {
+                final Request request = runtimeNode.getRequest();
+                final boolean isEqStrict = request == Request.EQ_STRICT;
+                if(isEqStrict || request == Request.NE_STRICT) {
+                    return createIsUndefined(runtimeNode, runtimeNode.getArgs().get(0), runtimeNode.getArgs().get(1),
+                            isEqStrict ? Request.IS_UNDEFINED : Request.IS_NOT_UNDEFINED);
+                }
+                return runtimeNode;
+            }
+
+            @SuppressWarnings("unchecked")
+            private <T extends JoinPredecessor> T setLocalVariableConversion(final JoinPredecessor original, final T jp) {
+                // NOTE: can't use Map.remove() as our copy-on-write AST semantics means some nodes appear twice (in
+                // finally blocks), so we need to be able to access conversions for them multiple times.
+                return (T)jp.setLocalVariableConversion(lc, localVariableConversions.get(original));
+            }
+        };
+
+        newFunction = newFunction.setBody(lc, (Block)newFunction.getBody().accept(applyChangesVisitor));
+        newFunction = newFunction.setReturnType(lc, returnType);
+
+
+        newFunction = newFunction.setState(lc, CompilationState.LOCAL_VARIABLE_TYPES_CALCULATED);
+        newFunction = newFunction.setParameters(lc, newFunction.visitParameters(applyChangesVisitor));
+        return newFunction;
+    }
+
+    private static Expression createIsUndefined(final Expression parent, final Expression lhs, final Expression rhs, final Request request) {
+        if (isUndefinedIdent(lhs) || isUndefinedIdent(rhs)) {
+            return new RuntimeNode(parent, request, lhs, rhs);
+        }
+        return parent;
+    }
+
+    private static boolean isUndefinedIdent(final Expression expr) {
+        return expr instanceof IdentNode && "undefined".equals(((IdentNode)expr).getName());
+    }
+
+    private boolean identIsDeadAndHasNoLiveConversions(final IdentNode identNode) {
+        final LocalVariableConversion conv = localVariableConversions.get(identNode);
+        return conv == null || !conv.isLive();
+    }
+
+    private void onAssignment(final IdentNode identNode, final Expression rhs) {
+        onAssignment(identNode, toLvarType(getType(rhs)));
+    }
+
+    private void onAssignment(final IdentNode identNode, final LvarType type) {
+        final Symbol symbol = identNode.getSymbol();
+        assert symbol != null : identNode.getName();
+        if(!symbol.isBytecodeLocal()) {
+            return;
+        }
+        assert type != null;
+        final LvarType finalType;
+        if(type == LvarType.UNDEFINED && getLocalVariableType(symbol) != LvarType.UNDEFINED) {
+            // Explicit assignment of a known undefined local variable to a local variable that is not undefined will
+            // materialize that undefined in the assignment target. Note that assigning known undefined to known
+            // undefined will *not* initialize the variable, e.g. "var x; var y = x;" compiles to no-op.
+            finalType = LvarType.OBJECT;
+            symbol.setFlag(Symbol.HAS_OBJECT_VALUE);
+        } else {
+            finalType = type;
+        }
+        setType(symbol, finalType);
+        // Explicit assignment of an undefined value. Make sure the variable can store an object
+        // TODO: if we communicated the fact to codegen with a flag on the IdentNode that the value was already
+        // undefined before the assignment, we could just ignore it. In general, we could ignore an assignment if we
+        // know that the value assigned is the same as the current value of the variable, but we'd need constant
+        // propagation for that.
+        setIdentifierLvarType(identNode, finalType);
+        // For purposes of type calculation, we consider an assignment to a local variable to be followed by
+        // the catch nodes of the current (if any) try block. This will effectively enforce that narrower
+        // assignments to a local variable in a try block will also have to store a widened value as well. Code
+        // within the try block will be able to keep loading the narrower value, but after the try block only
+        // the widest value will remain live.
+        // Rationale for this is that if there's an use for that variable in any of the catch blocks, or
+        // following the catch blocks, they must use the widest type.
+        // Example:
+        /*
+            Originally:
+            ===========
+            var x;
+            try {
+              x = 1; <-- stores into int slot for x
+              f(x); <-- loads the int slot for x
+              x = 3.14 <-- stores into the double slot for x
+              f(x); <-- loads the double slot for x
+              x = 1; <-- stores into int slot for x
+              f(x); <-- loads the int slot for x
+            } finally {
+              f(x); <-- loads the double slot for x, but can be reached by a path where x is int, so we need
+                           to go back and ensure that double values are also always stored along with int
+                           values.
+            }
+
+            After correction:
+            =================
+
+            var x;
+            try {
+              x = 1; <-- stores into both int and double slots for x
+              f(x); <-- loads the int slot for x
+              x = 3.14 <-- stores into the double slot for x
+              f(x); <-- loads the double slot for x
+              x = 1; <-- stores into both int and double slots for x
+              f(x); <-- loads the int slot for x
+            } finally {
+              f(x); <-- loads the double slot for x
+            }
+         */
+        jumpToCatchBlock(identNode);
+    }
+
+    private void onSelfAssignment(final IdentNode identNode, final Expression assignment) {
+        final Symbol symbol = identNode.getSymbol();
+        assert symbol != null : identNode.getName();
+        if(!symbol.isBytecodeLocal()) {
+            return;
+        }
+        final LvarType type = toLvarType(getType(assignment));
+        // Self-assignment never produce either a boolean or undefined
+        assert type != null && type != LvarType.UNDEFINED && type != LvarType.BOOLEAN;
+        setType(symbol, type);
+        jumpToCatchBlock(identNode);
+    }
+
+    private void resetJoinPoint(final Label label) {
+        jumpTargets.remove(label);
+    }
+
+    private void setCompilerConstantAsObject(final FunctionNode functionNode, final CompilerConstants cc) {
+        final Symbol symbol = getCompilerConstantSymbol(functionNode, cc);
+        setType(symbol, LvarType.OBJECT);
+        // never mark compiler constants as dead
+        symbolIsUsed(symbol);
+    }
+
+    private static Symbol getCompilerConstantSymbol(final FunctionNode functionNode, final CompilerConstants cc) {
+        return functionNode.getBody().getExistingSymbol(cc.symbolName());
+    }
+
+    private void setConversion(final JoinPredecessor node, final Map<Symbol, LvarType> branchLvarTypes, final Map<Symbol, LvarType> joinLvarTypes) {
+        if(node == null) {
+            return;
+        }
+        if(branchLvarTypes.isEmpty() || joinLvarTypes.isEmpty()) {
+            localVariableConversions.remove(node);
+        }
+
+        LocalVariableConversion conversion = null;
+        if(node instanceof IdentNode) {
+            // conversions on variable assignment in try block are special cases, as they only apply to the variable
+            // being assigned and all other conversions should be ignored.
+            final Symbol symbol = ((IdentNode)node).getSymbol();
+            conversion = createConversion(symbol, branchLvarTypes.get(symbol), joinLvarTypes, null);
+        } else {
+            for(final Map.Entry<Symbol, LvarType> entry: branchLvarTypes.entrySet()) {
+                final Symbol symbol = entry.getKey();
+                final LvarType branchLvarType = entry.getValue();
+                conversion = createConversion(symbol, branchLvarType, joinLvarTypes, conversion);
+            }
+        }
+        if(conversion != null) {
+            localVariableConversions.put(node, conversion);
+        } else {
+            localVariableConversions.remove(node);
+        }
+    }
+
+    private void setIdentifierLvarType(final IdentNode identNode, final LvarType type) {
+        assert type != null;
+        identifierLvarTypes.put(identNode, type);
+    }
+
+    /**
+     * Marks a local variable as having a specific type from this point onward. Invoked by stores to local variables.
+     * @param symbol the symbol representing the variable
+     * @param type the type
+     */
+    private void setType(final Symbol symbol, final LvarType type) {
+        if(getLocalVariableTypeOrNull(symbol) == type) {
+            return;
+        }
+        assert symbol.hasSlot();
+        assert !symbol.isGlobal();
+        localVariableTypes = localVariableTypes.isEmpty() ? new IdentityHashMap<Symbol, LvarType>() : cloneMap(localVariableTypes);
+        localVariableTypes.put(symbol, type);
+    }
+
+    /**
+     * Set a flag in the symbol marking it as needing to be able to store a value of a particular type. Every symbol for
+     * a local variable will be assigned between 1 and 6 local variable slots for storing all types it is known to need
+     * to store.
+     * @param symbol the symbol
+     */
+    private void symbolIsUsed(final Symbol symbol) {
+        symbolIsUsed(symbol, getLocalVariableType(symbol));
+    }
+
+    private Type getType(final Expression expr) {
+        return expr.getType(getSymbolToType());
+    }
+
+    private Function<Symbol, Type> getSymbolToType() {
+        // BinaryNode uses identity of the function to cache type calculations. Therefore, we must use different
+        // function instances for different localVariableTypes instances.
+        if(symbolToType.isStale()) {
+            symbolToType = new SymbolToType();
+        }
+        return symbolToType;
+    }
+
+    private class SymbolToType implements Function<Symbol, Type> {
+        private final Object boundTypes = localVariableTypes;
+        @Override
+        public Type apply(final Symbol t) {
+            return getLocalVariableType(t).type;
+        }
+
+        boolean isStale() {
+            return boundTypes != localVariableTypes;
+        }
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
index bf6872f..9f713e0 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Lower.java
@@ -27,10 +27,11 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
 import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-import static jdk.nashorn.internal.codegen.CompilerConstants.THIS;
+import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import java.util.ListIterator;
 import jdk.nashorn.internal.ir.BaseNode;
@@ -40,6 +41,7 @@
 import jdk.nashorn.internal.ir.BlockStatement;
 import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
@@ -56,6 +58,7 @@
 import jdk.nashorn.internal.ir.LoopNode;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.ReturnNode;
+import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
 import jdk.nashorn.internal.ir.Symbol;
@@ -69,9 +72,12 @@
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.CodeInstaller;
-import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * Lower to more primitive operations. After lowering, an AST still has no symbols
@@ -82,10 +88,10 @@
  * harder and context dependent to do any code copying after symbols have been
  * finalized.
  */
+@Logger(name="lower")
+final class Lower extends NodeOperatorVisitor<BlockLexicalContext> implements Loggable {
 
-final class Lower extends NodeOperatorVisitor<BlockLexicalContext> {
-
-    private static final DebugLogger LOG = new DebugLogger("lower");
+    private final DebugLogger log;
 
     // needed only to get unique eval id
     private final CodeInstaller<?> installer;
@@ -93,7 +99,7 @@
     /**
      * Constructor.
      */
-    Lower(final CodeInstaller<?> installer) {
+    Lower(final Compiler compiler) {
         super(new BlockLexicalContext() {
 
             @Override
@@ -136,40 +142,19 @@
                 return block.setIsTerminal(this, false);
             }
         });
-        this.installer = installer;
+
+        this.installer = compiler.getCodeInstaller();
+        this.log       = initLogger(compiler.getContext());
     }
 
     @Override
-    public boolean enterBlock(final Block block) {
-        final FunctionNode   function = lc.getCurrentFunction();
-        if (lc.isFunctionBody() && function.isProgram() && !function.hasDeclaredFunctions()) {
-            new ExpressionStatement(function.getLineNumber(), block.getToken(), block.getFinish(), LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED)).accept(this);
-        }
-        return true;
+    public DebugLogger getLogger() {
+        return log;
     }
 
     @Override
-    public Node leaveBlock(final Block block) {
-        //now we have committed the entire statement list to the block, but we need to truncate
-        //whatever is after the last terminal. block append won't append past it
-
-
-        if (lc.isFunctionBody()) {
-            final FunctionNode currentFunction = lc.getCurrentFunction();
-            final boolean isProgram = currentFunction.isProgram();
-            final Statement last = lc.getLastStatement();
-            final ReturnNode returnNode = new ReturnNode(
-                last == null ? currentFunction.getLineNumber() : last.getLineNumber(), //TODO?
-                currentFunction.getToken(),
-                currentFunction.getFinish(),
-                isProgram ?
-                    compilerConstant(RETURN) :
-                    LiteralNode.newInstance(block, ScriptRuntime.UNDEFINED));
-
-            returnNode.accept(this);
-        }
-
-        return block;
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
     }
 
     @Override
@@ -222,7 +207,7 @@
     }
 
     @Override
-    public Node leaveBlockStatement(BlockStatement blockStatement) {
+    public Node leaveBlockStatement(final BlockStatement blockStatement) {
         return addStatement(blockStatement);
     }
 
@@ -230,22 +215,24 @@
     public Node leaveForNode(final ForNode forNode) {
         ForNode newForNode = forNode;
 
-        final Node  test = forNode.getTest();
-        if (!forNode.isForIn() && conservativeAlwaysTrue(test)) {
+        final Expression test = forNode.getTest();
+        if (!forNode.isForIn() && isAlwaysTrue(test)) {
             newForNode = forNode.setTest(lc, null);
         }
 
-        return addStatement(checkEscape(newForNode));
-    }
-
-    @Override
-    public boolean enterFunctionNode(final FunctionNode functionNode) {
-        return !functionNode.isLazy();
+        newForNode = checkEscape(newForNode);
+        if(newForNode.isForIn()) {
+            // Wrap it in a block so its internally created iterator is restricted in scope
+            addStatementEnclosedInBlock(newForNode);
+        } else {
+            addStatement(newForNode);
+        }
+        return newForNode;
     }
 
     @Override
     public Node leaveFunctionNode(final FunctionNode functionNode) {
-        LOG.info("END FunctionNode: ", functionNode.getName());
+        log.info("END FunctionNode: ", functionNode.getName());
         return functionNode.setState(lc, CompilationState.LOWERED);
     }
 
@@ -255,6 +242,16 @@
     }
 
     @Override
+    public Node leaveIN(final BinaryNode binaryNode) {
+        return new RuntimeNode(binaryNode);
+    }
+
+    @Override
+    public Node leaveINSTANCEOF(final BinaryNode binaryNode) {
+        return new RuntimeNode(binaryNode);
+    }
+
+    @Override
     public Node leaveLabelNode(final LabelNode labelNode) {
         return addStatement(labelNode);
     }
@@ -265,16 +262,35 @@
         return returnNode;
     }
 
+    @Override
+    public Node leaveCaseNode(final CaseNode caseNode) {
+        // Try to represent the case test as an integer
+        final Node test = caseNode.getTest();
+        if (test instanceof LiteralNode) {
+            final LiteralNode<?> lit = (LiteralNode<?>)test;
+            if (lit.isNumeric() && !(lit.getValue() instanceof Integer)) {
+                if (JSType.isRepresentableAsInt(lit.getNumber())) {
+                    return caseNode.setTest((Expression)LiteralNode.newInstance(lit, lit.getInt32()).accept(this));
+                }
+            }
+        }
+        return caseNode;
+    }
 
     @Override
     public Node leaveSwitchNode(final SwitchNode switchNode) {
-        return addStatement(switchNode);
+        if(!switchNode.isInteger()) {
+            // Wrap it in a block so its internally created tag is restricted in scope
+            addStatementEnclosedInBlock(switchNode);
+        } else {
+            addStatement(switchNode);
+        }
+        return switchNode;
     }
 
     @Override
     public Node leaveThrowNode(final ThrowNode throwNode) {
-        addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
-        return throwNode;
+        return addStatement(throwNode); //ThrowNodes are always terminal, marked as such in constructor
     }
 
     private static Node ensureUniqueNamesIn(final Node node) {
@@ -308,12 +324,12 @@
         final long token      = tryNode.getToken();
         final int  finish     = tryNode.getFinish();
 
-        final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName("catch_all"));
+        final IdentNode exception = new IdentNode(token, finish, lc.getCurrentFunction().uniqueName(CompilerConstants.EXCEPTION_PREFIX.symbolName()));
 
-        final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), ThrowNode.IS_SYNTHETIC_RETHROW));
+        final Block catchBody = new Block(token, finish, new ThrowNode(lineNumber, token, finish, new IdentNode(exception), true));
         assert catchBody.isTerminal(); //ends with throw, so terminal
 
-        final CatchNode catchAllNode  = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, CatchNode.IS_SYNTHETIC_RETHROW);
+        final CatchNode catchAllNode  = new CatchNode(lineNumber, token, finish, new IdentNode(exception), null, catchBody, true);
         final Block     catchAllBlock = new Block(token, finish, catchAllNode);
 
         //catchallblock -> catchallnode (catchnode) -> exception -> throw
@@ -340,6 +356,8 @@
     private Node spliceFinally(final TryNode tryNode, final List<ThrowNode> rethrows, final Block finallyBody) {
         assert tryNode.getFinallyBody() == null;
 
+        final LexicalContext lowerLc = lc;
+
         final TryNode newTryNode = (TryNode)tryNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
             final List<Node> insideTry = new ArrayList<>();
 
@@ -369,12 +387,12 @@
 
             @Override
             public Node leaveBreakNode(final BreakNode breakNode) {
-                return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabel()));
+                return copy(breakNode, (Node)Lower.this.lc.getBreakable(breakNode.getLabelName()));
             }
 
             @Override
             public Node leaveContinueNode(final ContinueNode continueNode) {
-                return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabel()));
+                return copy(continueNode, Lower.this.lc.getContinueTo(continueNode.getLabelName()));
             }
 
             @Override
@@ -388,6 +406,7 @@
                     //still in the try block, store it in a result value and return it afterwards
                     resultNode = new IdentNode(Lower.this.compilerConstant(RETURN));
                     newStatements.add(new ExpressionStatement(returnNode.getLineNumber(), returnNode.getToken(), returnNode.getFinish(), new BinaryNode(Token.recast(returnNode.getToken(), TokenType.ASSIGN), resultNode, expr)));
+                    lowerLc.setFlag(lowerLc.getCurrentFunction(), FunctionNode.USES_RETURN_SYMBOL);
                 } else {
                     resultNode = null;
                 }
@@ -425,7 +444,7 @@
         final Block finallyBody = tryNode.getFinallyBody();
 
         if (finallyBody == null) {
-            return addStatement(tryNode);
+            return addStatement(ensureUnconditionalCatch(tryNode));
         }
 
         /*
@@ -468,7 +487,7 @@
         if (tryNode.getCatchBlocks().isEmpty()) {
             newTryNode = tryNode.setFinallyBody(null);
         } else {
-            Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), tryNode.setFinallyBody(null));
+            final Block outerBody = new Block(tryNode.getToken(), tryNode.getFinish(), ensureUnconditionalCatch(tryNode.setFinallyBody(null)));
             newTryNode = tryNode.setBody(outerBody).setCatchBlocks(null);
         }
 
@@ -481,6 +500,18 @@
         return spliceFinally(newTryNode, rethrows, finallyBody);
     }
 
+    private TryNode ensureUnconditionalCatch(final TryNode tryNode) {
+        final List<CatchNode> catches = tryNode.getCatches();
+        if(catches == null || catches.isEmpty() || catches.get(catches.size() - 1).getExceptionCondition() == null) {
+            return tryNode;
+        }
+        // If the last catch block is conditional, add an unconditional rethrow block
+        final List<Block> newCatchBlocks = new ArrayList<>(tryNode.getCatchBlocks());
+
+        newCatchBlocks.add(catchAllBlock(tryNode));
+        return tryNode.setCatchBlocks(newCatchBlocks);
+    }
+
     @Override
     public Node leaveVarNode(final VarNode varNode) {
         addStatement(varNode);
@@ -492,12 +523,12 @@
 
     @Override
     public Node leaveWhileNode(final WhileNode whileNode) {
-        final Node test  = whileNode.getTest();
+        final Expression test = whileNode.getTest();
         final Block body = whileNode.getBody();
 
-        if (conservativeAlwaysTrue(test)) {
+        if (isAlwaysTrue(test)) {
             //turn it into a for node without a test.
-            final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), null, null, body, null, ForNode.IS_FOR).accept(this);
+            final ForNode forNode = (ForNode)new ForNode(whileNode.getLineNumber(), whileNode.getToken(), whileNode.getFinish(), body, ForNode.IS_FOR).accept(this);
             lc.replace(whileNode, forNode);
             return forNode;
         }
@@ -571,23 +602,17 @@
 
             // 'eval' call with at least one argument
             if (args.size() >= 1 && EVAL.symbolName().equals(callee.getName())) {
-                final FunctionNode currentFunction = lc.getCurrentFunction();
-                return callNode.setEvalArgs(
-                    new CallNode.EvalArgs(
-                        (Expression)ensureUniqueNamesIn(args.get(0)).accept(this),
-                        compilerConstant(THIS),
-                        evalLocation(callee),
-                        currentFunction.isStrict()));
+                final List<Expression> evalArgs = new ArrayList<>(args.size());
+                for(final Expression arg: args) {
+                    evalArgs.add((Expression)ensureUniqueNamesIn(arg).accept(this));
+                }
+                return callNode.setEvalArgs(new CallNode.EvalArgs(evalArgs, evalLocation(callee)));
             }
         }
 
         return callNode;
     }
 
-    private static boolean conservativeAlwaysTrue(final Node node) {
-        return node == null || ((node instanceof LiteralNode) && Boolean.TRUE.equals(((LiteralNode<?>)node).getValue()));
-    }
-
     /**
      * Helper that given a loop body makes sure that it is not terminal if it
      * has a continue that leads to the loop header or to outer loops' loop
@@ -610,7 +635,7 @@
             @Override
             public Node leaveContinueNode(final ContinueNode node) {
                 // all inner loops have been popped.
-                if (lex.contains(lex.getContinueTo(node.getLabel()))) {
+                if (lex.contains(lex.getContinueTo(node.getLabelName()))) {
                     escapes.add(node);
                 }
                 return node;
@@ -620,10 +645,11 @@
         return !escapes.isEmpty();
     }
 
-    private LoopNode checkEscape(final LoopNode loopNode) {
+    @SuppressWarnings("unchecked")
+    private <T extends LoopNode> T checkEscape(final T loopNode) {
         final boolean escapes = controlFlowEscapes(lc, loopNode.getBody());
         if (escapes) {
-            return loopNode.
+            return (T)loopNode.
                 setBody(lc, loopNode.getBody().setIsTerminal(lc, false)).
                 setControlFlowEscapes(lc, escapes);
         }
@@ -636,6 +662,14 @@
         return statement;
     }
 
+    private void addStatementEnclosedInBlock(final Statement stmt) {
+        BlockStatement b = BlockStatement.createReplacement(stmt, Collections.<Statement>singletonList(stmt));
+        if(stmt.isTerminal()) {
+            b = b.setBlock(b.getBlock().setIsTerminal(null, true));
+        }
+        addStatement(b);
+    }
+
     /**
      * An internal expression has a symbol that is tagged internal. Check if
      * this is such a node
@@ -644,7 +678,10 @@
      * @return true if internal, false otherwise
      */
     private static boolean isInternalExpression(final Expression expression) {
-        final Symbol symbol = expression.getSymbol();
+        if (!(expression instanceof IdentNode)) {
+            return false;
+        }
+        final Symbol symbol = ((IdentNode)expression).getSymbol();
         return symbol != null && symbol.isInternal();
     }
 
@@ -656,8 +693,7 @@
      * @return true if an assignment to eval result, false otherwise
      */
     private static boolean isEvalResultAssignment(final Node expression) {
-        Node e = expression;
-        assert e.tokenType() != TokenType.DISCARD; //there are no discards this early anymore
+        final Node e = expression;
         if (e instanceof BinaryNode) {
             final Node lhs = ((BinaryNode)e).lhs();
             if (lhs instanceof IdentNode) {
@@ -666,5 +702,4 @@
         }
         return false;
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java b/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java
index 436622b..d4800f8 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MapCreator.java
@@ -34,19 +34,19 @@
 import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.SpillProperty;
 
 /**
  * Class that creates PropertyMap sent to script object constructors.
+ * @param <T> value type for tuples, e.g. Symbol
  */
-public class MapCreator {
+public class MapCreator<T> {
     /** Object structure for objects associated with this map */
     private final Class<?> structure;
 
     /** key set for object map */
-    final List<String> keys;
-
-    /** corresponding symbol set for object map */
-    final List<Symbol> symbols;
+    private final List<MapTuple<T>> tuples;
 
     /**
      * Constructor
@@ -55,31 +55,38 @@
      * @param keys      list of keys for map
      * @param symbols   list of symbols for map
      */
-    MapCreator(final Class<?> structure, final List<String> keys, final List<Symbol> symbols) {
+    MapCreator(final Class<? extends ScriptObject> structure, final List<MapTuple<T>> tuples) {
         this.structure = structure;
-        this.keys      = keys;
-        this.symbols   = symbols;
+        this.tuples    = tuples;
     }
 
     /**
      * Constructs a property map based on a set of fields.
      *
-     * @param hasArguments does the created object have an "arguments" property
+     * @param hasArguments  does the created object have an "arguments" property
      * @param fieldCount    Number of fields in use.
-     * @param fieldMaximum Number of fields available.
-     *
+     * @param fieldMaximum  Number of fields available.
+     * @param evalCode      is this property map created for 'eval' code?
      * @return New map populated with accessor properties.
      */
-    PropertyMap makeFieldMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum) {
+    PropertyMap makeFieldMap(final boolean hasArguments, final int fieldCount, final int fieldMaximum, final boolean evalCode) {
         final List<Property> properties = new ArrayList<>();
-        assert keys != null;
+        assert tuples != null;
 
-        for (int i = 0, length = keys.size(); i < length; i++) {
-            final String key    = keys.get(i);
-            final Symbol symbol = symbols.get(i);
+        for (final MapTuple<T> tuple : tuples) {
+            final String   key         = tuple.key;
+            final Symbol   symbol      = tuple.symbol;
+            final Class<?> initialType = tuple.getValueType();
 
             if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) {
-                properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), structure, symbol.getFieldIndex()));
+                final int      flags    = getPropertyFlags(symbol, hasArguments, evalCode);
+                final Property property = new AccessorProperty(
+                        key,
+                        flags,
+                        structure,
+                        symbol.getFieldIndex(),
+                        initialType);
+                properties.add(property);
             }
         }
 
@@ -89,14 +96,20 @@
     PropertyMap makeSpillMap(final boolean hasArguments) {
         final List<Property> properties = new ArrayList<>();
         int spillIndex = 0;
-        assert keys != null;
+        assert tuples != null;
 
-        for (int i = 0, length = keys.size(); i < length; i++) {
-            final String key    = keys.get(i);
-            final Symbol symbol = symbols.get(i);
+        for (final MapTuple<T> tuple : tuples) {
+            final String key    = tuple.key;
+            final Symbol symbol = tuple.symbol;
 
+            //TODO initial type is object here no matter what. Is that right?
             if (symbol != null && !isValidArrayIndex(getArrayIndex(key))) {
-                properties.add(new AccessorProperty(key, getPropertyFlags(symbol, hasArguments), spillIndex++));
+                final int flags = getPropertyFlags(symbol, hasArguments, false);
+                properties.add(
+                        new SpillProperty(
+                                key,
+                                flags,
+                                spillIndex++));
             }
         }
 
@@ -111,34 +124,31 @@
      *
      * @return flags to use for fields
      */
-    protected int getPropertyFlags(final Symbol symbol, final boolean hasArguments) {
+    static int getPropertyFlags(final Symbol symbol, final boolean hasArguments, final boolean evalCode) {
         int flags = 0;
 
         if (symbol.isParam()) {
-            flags |= Property.IS_ALWAYS_OBJECT | Property.IS_PARAMETER;
+            flags |= Property.IS_PARAMETER;
         }
 
         if (hasArguments) {
-            flags |= Property.IS_ALWAYS_OBJECT | Property.HAS_ARGUMENTS;
+            flags |= Property.HAS_ARGUMENTS;
         }
 
-        if (symbol.isScope()) {
+        // See ECMA 5.1 10.5 Declaration Binding Instantiation.
+        // Step 2  If code is eval code, then let configurableBindings
+        // be true else let configurableBindings be false.
+        // We have to make vars, functions declared in 'eval' code
+        // configurable. But vars, functions from any other code is
+        // not configurable.
+        if (symbol.isScope() && !evalCode) {
             flags |= Property.NOT_CONFIGURABLE;
         }
 
-        if (symbol.canBePrimitive()) {
-            flags |= Property.CAN_BE_PRIMITIVE;
-        }
-
-        if (symbol.canBeUndefined()) {
-            flags |= Property.CAN_BE_UNDEFINED;
-        }
-
         if (symbol.isFunctionDeclaration()) {
             flags |= Property.IS_FUNCTION_DECLARATION;
         }
 
         return flags;
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/MapTuple.java b/nashorn/src/jdk/nashorn/internal/codegen/MapTuple.java
new file mode 100644
index 0000000..024c3d6
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MapTuple.java
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.Symbol;
+
+/**
+ * A tuple of values used for map creation
+ * @param <T> value type
+ */
+class MapTuple<T> {
+    final String key;
+    final Symbol symbol;
+    final Type   type;
+    final T      value;
+
+    MapTuple(final String key, final Symbol symbol, final Type type) {
+        this(key, symbol, type, null);
+    }
+
+    MapTuple(final String key, final Symbol symbol, final Type type, final T value) {
+        this.key    = key;
+        this.symbol = symbol;
+        this.type   = type;
+        this.value  = value;
+    }
+
+    public Class<?> getValueType() {
+        return OBJECT_FIELDS_ONLY ? Object.class : null; //until proven otherwise we are undefined, see NASHORN-592 int.class;
+    }
+
+    boolean isPrimitive() {
+        return !OBJECT_FIELDS_ONLY && getValueType().isPrimitive() && getValueType() != boolean.class;
+    }
+
+    @Override
+    public String toString() {
+        return "[key=" + key + ", symbol=" + symbol + ", value=" + value + " (" + (value == null ? "null" : value.getClass().getSimpleName()) +")]";
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
index 91129ec..415417d 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/MethodEmitter.java
@@ -43,6 +43,10 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPEQ;
 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ACMPNE;
 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPEQ;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGE;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPGT;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLE;
+import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPLT;
 import static jdk.internal.org.objectweb.asm.Opcodes.IF_ICMPNE;
 import static jdk.internal.org.objectweb.asm.Opcodes.INSTANCEOF;
 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKEINTERFACE;
@@ -64,11 +68,17 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.methodDescriptor;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticField;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
 
 import java.io.PrintStream;
 import java.lang.reflect.Array;
+import java.util.Collection;
 import java.util.EnumSet;
+import java.util.IdentityHashMap;
 import java.util.List;
+import java.util.Map;
 import jdk.internal.dynalink.support.NameCodec;
 import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
@@ -79,19 +89,26 @@
 import jdk.nashorn.internal.codegen.types.BitwiseType;
 import jdk.nashorn.internal.codegen.types.NumericType;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.JoinPredecessor;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TryNode;
+import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ArgumentSetter;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
 import jdk.nashorn.internal.runtime.JSType;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.RewriteException;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -111,27 +128,34 @@
     /** The ASM MethodVisitor we are plugged into */
     private final MethodVisitor method;
 
-    /** Current type stack for current evaluation */
-    private Label.Stack stack;
-
     /** Parent classEmitter representing the class of this method */
     private final ClassEmitter classEmitter;
 
     /** FunctionNode representing this method, or null if none exists */
     protected FunctionNode functionNode;
 
+    /** Current type stack for current evaluation */
+    private Label.Stack stack;
+
     /** Check whether this emitter ever has a function return point */
     private boolean hasReturn;
 
-    /** The script environment */
-    private final ScriptEnvironment env;
+    private boolean preventUndefinedLoad;
+
+    /**
+     * Map of live local variable definitions.
+     */
+    private final Map<Symbol, LocalVariableDef> localVariableDefs = new IdentityHashMap<>();
+
+    /** The context */
+    private final Context context;
 
     /** Threshold in chars for when string constants should be split */
     static final int LARGE_STRING_THRESHOLD = 32 * 1024;
 
     /** Debug flag, should we dump all generated bytecode along with stacks? */
-    private static final DebugLogger LOG   = new DebugLogger("codegen", "nashorn.codegen.debug");
-    private static final boolean     DEBUG = LOG.isEnabled();
+    private final DebugLogger log;
+    private final boolean     debug;
 
     /** dump stack on a particular line, or -1 if disabled */
     private static final int DEBUG_TRACE_LINE;
@@ -153,6 +177,12 @@
     /** Bootstrap for runtime node indy:s */
     private static final Handle RUNTIMEBOOTSTRAP = new Handle(H_INVOKESTATIC, RuntimeCallSite.BOOTSTRAP.className(), RuntimeCallSite.BOOTSTRAP.name(), RuntimeCallSite.BOOTSTRAP.descriptor());
 
+    /** Bootstrap for array populators */
+    private static final Handle POPULATE_ARRAY_BOOTSTRAP = new Handle(H_INVOKESTATIC, RewriteException.BOOTSTRAP.className(), RewriteException.BOOTSTRAP.name(), RewriteException.BOOTSTRAP.descriptor());
+
+    /** Bootstrap for global name invalidation */
+    private static final Handle INVALIDATE_NAME_BOOTSTRAP = new Handle(H_INVOKESTATIC, Global.BOOTSTRAP.className(), Global.BOOTSTRAP.name(), Global.BOOTSTRAP.descriptor());
+
     /**
      * Constructor - internal use from ClassEmitter only
      * @see ClassEmitter#method
@@ -173,11 +203,13 @@
      * @param functionNode a function node representing this method
      */
     MethodEmitter(final ClassEmitter classEmitter, final MethodVisitor method, final FunctionNode functionNode) {
-        this.env          = classEmitter.getEnv();
+        this.context      = classEmitter.getContext();
         this.classEmitter = classEmitter;
         this.method       = method;
         this.functionNode = functionNode;
         this.stack        = null;
+        this.log          = context.getLogger(CodeGenerator.class);
+        this.debug        = log.isEnabled();
     }
 
     /**
@@ -203,6 +235,14 @@
         classEmitter.endMethod(this);
     }
 
+    boolean isReachable() {
+        return stack != null;
+    }
+
+    private void doesNotContinueSequentially() {
+        stack = null;
+    }
+
     private void newStack() {
         stack = new Label.Stack();
     }
@@ -216,7 +256,7 @@
      * Push a type to the existing stack
      * @param type the type
      */
-    private void pushType(final Type type) {
+    void pushType(final Type type) {
         if (type != null) {
             stack.push(type);
         }
@@ -230,7 +270,7 @@
      * @return the type that was retrieved
      */
     private Type popType(final Type expected) {
-        final Type type = stack.pop();
+        final Type type = popType();
         assert type.isObject() && expected.isObject() ||
             type.isEquivalentTo(expected) : type + " is not compatible with " + expected;
         return type;
@@ -246,26 +286,40 @@
     }
 
     /**
-     * Pop a type from the existing stack, ensuring that it is numeric,
-     * assert if not
+     * Pop a type from the existing stack, ensuring that it is numeric. Boolean type is popped as int type.
      *
      * @return the type
      */
     private NumericType popNumeric() {
-        final Type type = stack.pop();
-        assert type.isNumeric() : type + " is not numeric";
+        final Type type = popType();
+        if(type.isBoolean()) {
+            // Booleans are treated as int for purposes of arithmetic operations
+            return Type.INT;
+        }
+        assert type.isNumeric();
         return (NumericType)type;
     }
 
     /**
      * Pop a type from the existing stack, ensuring that it is an integer type
-     * (integer or long), assert if not
+     * (integer or long). Boolean type is popped as int type.
      *
      * @return the type
      */
+    private BitwiseType popBitwise() {
+        final Type type = popType();
+        if(type == Type.BOOLEAN) {
+            return Type.INT;
+        }
+        return (BitwiseType)type;
+    }
+
     private BitwiseType popInteger() {
-        final Type type = stack.pop();
-        assert type.isInteger() || type.isLong() : type + " is not an integer or long";
+        final Type type = popType();
+        if(type == Type.BOOLEAN) {
+            return Type.INT;
+        }
+        assert type == Type.INT;
         return (BitwiseType)type;
     }
 
@@ -276,7 +330,7 @@
      * @return the type
      */
     private ArrayType popArray() {
-        final Type type = stack.pop();
+        final Type type = popType();
         assert type.isArray() : type;
         return (ArrayType)type;
     }
@@ -307,13 +361,14 @@
      * object type on the stack
      *
      * @param classDescriptor class descriptor for the object type
+     * @param type the type of the new object
      *
      * @return the method emitter
      */
-    MethodEmitter _new(final String classDescriptor) {
+    MethodEmitter _new(final String classDescriptor, final Type type) {
         debug("new", classDescriptor);
         method.visitTypeInsn(NEW, classDescriptor);
-        pushType(Type.OBJECT);
+        pushType(type);
         return this;
     }
 
@@ -326,7 +381,7 @@
      * @return the method emitter
      */
     MethodEmitter _new(final Class<?> clazz) {
-        return _new(className(clazz));
+        return _new(className(clazz), Type.typeFor(clazz));
     }
 
     /**
@@ -358,25 +413,40 @@
         debug("dup", depth);
 
         switch (depth) {
-        case 0:
+        case 0: {
+            final int l0 = stack.getTopLocalLoad();
             pushType(peekType());
+            stack.markLocalLoad(l0);
             break;
+        }
         case 1: {
+            final int l0 = stack.getTopLocalLoad();
             final Type p0 = popType();
+            final int l1 = stack.getTopLocalLoad();
             final Type p1 = popType();
             pushType(p0);
+            stack.markLocalLoad(l0);
             pushType(p1);
+            stack.markLocalLoad(l1);
             pushType(p0);
+            stack.markLocalLoad(l0);
             break;
         }
         case 2: {
+            final int l0 = stack.getTopLocalLoad();
             final Type p0 = popType();
+            final int l1 = stack.getTopLocalLoad();
             final Type p1 = popType();
+            final int l2 = stack.getTopLocalLoad();
             final Type p2 = popType();
             pushType(p0);
+            stack.markLocalLoad(l0);
             pushType(p2);
+            stack.markLocalLoad(l2);
             pushType(p1);
+            stack.markLocalLoad(l1);
             pushType(p0);
+            stack.markLocalLoad(l0);
             break;
         }
         default:
@@ -398,13 +468,22 @@
         debug("dup2");
 
         if (peekType().isCategory2()) {
+            final int l0 = stack.getTopLocalLoad();
             pushType(peekType());
+            stack.markLocalLoad(l0);
         } else {
-            final Type type = get2();
-            pushType(type);
-            pushType(type);
-            pushType(type);
-            pushType(type);
+            final int l0 = stack.getTopLocalLoad();
+            final Type p0 = popType();
+            final int l1 = stack.getTopLocalLoad();
+            final Type p1 = popType();
+            pushType(p0);
+            stack.markLocalLoad(l0);
+            pushType(p1);
+            stack.markLocalLoad(l1);
+            pushType(p0);
+            stack.markLocalLoad(l0);
+            pushType(p1);
+            stack.markLocalLoad(l1);
         }
         method.visitInsn(DUP2);
         return this;
@@ -454,35 +533,42 @@
     MethodEmitter swap() {
         debug("swap");
 
+        final int l0 = stack.getTopLocalLoad();
         final Type p0 = popType();
+        final int l1 = stack.getTopLocalLoad();
         final Type p1 = popType();
         p0.swap(method, p1);
 
         pushType(p0);
+        stack.markLocalLoad(l0);
         pushType(p1);
-        debug("after ", p0, p1);
+        stack.markLocalLoad(l1);
         return this;
     }
 
+    void pack() {
+        final Type type = peekType();
+        if (type.isInteger()) {
+            convert(PRIMITIVE_FIELD_TYPE);
+        } else if (type.isLong()) {
+            //nop
+        } else if (type.isNumber()) {
+            invokestatic("java/lang/Double", "doubleToRawLongBits", "(D)J");
+        } else {
+            assert false : type + " cannot be packed!";
+        }
+        //all others are nops, objects aren't packed
+    }
+
     /**
-     * Add a local variable. This is a nop if the symbol has no slot
-     *
-     * @param symbol symbol for the local variable
-     * @param start  start of scope
-     * @param end    end of scope
+     * Initializes a bytecode method parameter
+     * @param symbol the symbol for the parameter
+     * @param type the type of the parameter
+     * @param start the label for the start of the method
      */
-    void localVariable(final Symbol symbol, final Label start, final Label end) {
-        if (!symbol.hasSlot()) {
-            return;
-        }
-
-        String name = symbol.getName();
-
-        if (name.equals(THIS.symbolName())) {
-            name = THIS_DEBUGGER.symbolName();
-        }
-
-        method.visitLocalVariable(name, symbol.getSymbolType().getDescriptor(), null, start.getLabel(), end.getLabel(), symbol.getSlot());
+    void initializeMethodParameter(final Symbol symbol, final Type type, final Label start) {
+        assert symbol.isBytecodeLocal();
+        localVariableDefs.put(symbol, new LocalVariableDef(start.getLabel(), type));
     }
 
     /**
@@ -550,8 +636,8 @@
      */
     MethodEmitter shr() {
         debug("shr");
-        popType(Type.INT);
-        pushType(popInteger().shr(method));
+        popInteger();
+        pushType(popBitwise().shr(method));
         return this;
     }
 
@@ -563,21 +649,21 @@
      */
     MethodEmitter shl() {
         debug("shl");
-        popType(Type.INT);
-        pushType(popInteger().shl(method));
+        popInteger();
+        pushType(popBitwise().shl(method));
         return this;
     }
 
     /**
-     * Pops two integer types from the stack, performs a bitwise arithetic shift right and pushes
+     * Pops two integer types from the stack, performs a bitwise arithmetic shift right and pushes
      * the result. The shift count, the first element, must be INT.
      *
      * @return the method emitter
      */
     MethodEmitter sar() {
         debug("sar");
-        popType(Type.INT);
-        pushType(popInteger().sar(method));
+        popInteger();
+        pushType(popBitwise().sar(method));
         return this;
     }
 
@@ -586,9 +672,9 @@
      *
      * @return the method emitter
      */
-    MethodEmitter neg() {
+    MethodEmitter neg(final int programPoint) {
         debug("neg");
-        pushType(popNumeric().neg(method));
+        pushType(popNumeric().neg(method, programPoint));
         return this;
     }
 
@@ -599,20 +685,49 @@
      * @param recovery label pointing to start of catch block
      */
     void _catch(final Label recovery) {
-        stack.clear();
-        stack.push(Type.OBJECT);
+        // While in JVM a catch block can be reached through normal control flow, our code generator never does this,
+        // so we might as well presume there's no stack on entry.
+        assert stack == null;
+        recovery.onCatch();
         label(recovery);
+        beginCatchBlock();
     }
 
     /**
+     * Add any number of labels for the start of a catch block and push the exception to the
+     * stack
+     *
+     * @param recoveries labels pointing to start of catch block
+     */
+    void _catch(final Collection<Label> recoveries) {
+        assert stack == null;
+        for(final Label l: recoveries) {
+            label(l);
+        }
+        beginCatchBlock();
+    }
+
+    private void beginCatchBlock() {
+        // It can happen that the catch label wasn't marked as reachable. They are marked as reachable if there's an
+        // assignment in the try block, but it's possible that there was none.
+        if(!isReachable()) {
+            newStack();
+        }
+        pushType(Type.typeFor(Throwable.class));
+    }
+    /**
      * Start a try/catch block.
      *
      * @param entry          start label for try
      * @param exit           end label for try
      * @param recovery       start label for catch
      * @param typeDescriptor type descriptor for exception
+     * @param isOptimismHandler true if this is a hander for {@code UnwarrantedOptimismException}. Normally joining on a
+     * catch handler kills temporary variables, but optimism handlers are an exception, as they need to capture
+     * temporaries as well, so they must remain live.
      */
-    void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor) {
+    private void _try(final Label entry, final Label exit, final Label recovery, final String typeDescriptor, final boolean isOptimismHandler) {
+        recovery.joinFromTry(entry.getStack(), isOptimismHandler);
         method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), typeDescriptor);
     }
 
@@ -625,7 +740,7 @@
      * @param clazz    exception class
      */
     void _try(final Label entry, final Label exit, final Label recovery, final Class<?> clazz) {
-        method.visitTryCatchBlock(entry.getLabel(), exit.getLabel(), recovery.getLabel(), CompilerConstants.className(clazz));
+        _try(entry, exit, recovery, CompilerConstants.className(clazz), clazz == UnwarrantedOptimismException.class);
     }
 
     /**
@@ -636,9 +751,12 @@
      * @param recovery start label for catch
      */
     void _try(final Label entry, final Label exit, final Label recovery) {
-        _try(entry, exit, recovery, (String)null);
+        _try(entry, exit, recovery, (String)null, false);
     }
 
+    void markLabelAsOptimisticCatchHandler(final Label label, final int liveLocalCount) {
+        label.markAsOptimisticCatchHandler(stack, liveLocalCount);
+    }
 
     /**
      * Load the constants array
@@ -665,6 +783,12 @@
         return this;
     }
 
+    MethodEmitter loadForcedInitializer(final Type type) {
+        debug("load forced initializer ", type);
+        pushType(type.loadForcedInitializer(method));
+        return this;
+    }
+
     /**
      * Push the empty value for the given type, i.e. EMPTY.
      *
@@ -805,22 +929,36 @@
     }
 
     /**
-     * Push a local variable to the stack. If the symbol representing
-     * the local variable doesn't have a slot, this is a NOP
+     * Pushes the value of an identifier to the stack. If the identifier does not represent a local variable or a
+     * parameter, this will be a no-op.
      *
-     * @param symbol the symbol representing the local variable.
+     * @param ident the identifier for the variable being loaded.
      *
      * @return the method emitter
      */
-    MethodEmitter load(final Symbol symbol) {
+    MethodEmitter load(final IdentNode ident) {
+        return load(ident.getSymbol(), ident.getType());
+    }
+
+    /**
+     * Pushes the value of the symbol to the stack with the specified type. No type conversion is being performed, and
+     * the type is only being used if the symbol addresses a local variable slot. The value of the symbol is loaded if
+     * it addresses a local variable slot, or it is a parameter (in which case it can also be loaded from a vararg array
+     * or the arguments object). If it is neither, the operation is a no-op.
+     *
+     * @param symbol the symbol addressing the value being loaded
+     * @param type the presumed type of the value when it is loaded from a local variable slot
+     * @return the method emitter
+     */
+    MethodEmitter load(final Symbol symbol, final Type type) {
         assert symbol != null;
         if (symbol.hasSlot()) {
-            final int slot = symbol.getSlot();
-            debug("load symbol", symbol.getName(), " slot=", slot);
-            final Type type = symbol.getSymbolType().load(method, slot);
-            pushType(type == Type.OBJECT && symbol.isThis() ? Type.THIS : type);
+            final int slot = symbol.getSlot(type);
+            debug("load symbol", symbol.getName(), " slot=", slot, "type=", type);
+            load(type, slot);
+           // _try(new Label("dummy"), new Label("dummy2"), recovery);
+           // method.visitTryCatchBlock(new Label(), arg1, arg2, arg3);
         } else if (symbol.isParam()) {
-            assert !symbol.isScope();
             assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
             final int index = symbol.getFieldIndex();
             if (functionNode.needsArguments()) {
@@ -841,7 +979,7 @@
     }
 
     /**
-     * Push a local variable to the stack, given an explicit bytecode slot
+     * Push a local variable to the stack, given an explicit bytecode slot.
      * This is used e.g. for stub generation where we know where items like
      * "this" and "scope" reside.
      *
@@ -853,7 +991,11 @@
     MethodEmitter load(final Type type, final int slot) {
         debug("explicit load", type, slot);
         final Type loadType = type.load(method, slot);
+        assert loadType != null;
         pushType(loadType == Type.OBJECT && isThisSlot(slot) ? Type.THIS : loadType);
+        assert !preventUndefinedLoad || (slot < stack.localVariableTypes.size() && stack.localVariableTypes.get(slot) != Type.UNKNOWN)
+            : "Attempted load of uninitialized slot " + slot + " (as type " + type + ")";
+        stack.markLocalLoad(slot);
         return this;
     }
 
@@ -861,7 +1003,7 @@
         if (functionNode == null) {
             return slot == CompilerConstants.JAVA_THIS.slot();
         }
-        final int thisSlot = compilerConstant(THIS).getSlot();
+        final int thisSlot = getCompilerConstantSymbol(THIS).getSlot(Type.OBJECT);
         assert !functionNode.needsCallee() || thisSlot == 1; // needsCallee -> thisSlot == 1
         assert functionNode.needsCallee() || thisSlot == 0; // !needsCallee -> thisSlot == 0
         return slot == thisSlot;
@@ -883,7 +1025,7 @@
         return this;
     }
 
-    private Symbol compilerConstant(final CompilerConstants cc) {
+    private Symbol getCompilerConstantSymbol(final CompilerConstants cc) {
         return functionNode.getBody().getExistingSymbol(cc.symbolName());
     }
 
@@ -893,22 +1035,38 @@
      * @return if this method has a slot allocated for the scope variable.
      */
     boolean hasScope() {
-        return compilerConstant(SCOPE).hasSlot();
+        return getCompilerConstantSymbol(SCOPE).hasSlot();
     }
 
     MethodEmitter loadCompilerConstant(final CompilerConstants cc) {
-        final Symbol symbol = compilerConstant(cc);
+        return loadCompilerConstant(cc, null);
+    }
+
+    MethodEmitter loadCompilerConstant(final CompilerConstants cc, final Type type) {
         if (cc == SCOPE && peekType() == Type.SCOPE) {
             dup();
             return this;
         }
-        return load(symbol);
+        return load(getCompilerConstantSymbol(cc), type != null ? type : getCompilerConstantType(cc));
     }
 
     void storeCompilerConstant(final CompilerConstants cc) {
-        final Symbol symbol = compilerConstant(cc);
+        storeCompilerConstant(cc, null);
+    }
+
+    void storeCompilerConstant(final CompilerConstants cc, final Type type) {
+        final Symbol symbol = getCompilerConstantSymbol(cc);
+        if(!symbol.hasSlot()) {
+            return;
+        }
         debug("store compiler constant ", symbol);
-        store(symbol);
+        store(symbol, type != null ? type : getCompilerConstantType(cc));
+    }
+
+    private static Type getCompilerConstantType(final CompilerConstants cc) {
+        final Class<?> constantType = cc.type();
+        assert constantType != null;
+        return Type.typeFor(constantType);
     }
 
     /**
@@ -940,48 +1098,215 @@
 
     /**
      * Pop a value from the stack and store it in a local variable represented
-     * by the given symbol. If the symbol has no slot, this is a NOP
+     * by the given identifier. If the symbol has no slot, this is a NOP
      *
-     * @param symbol symbol to store stack to
+     * @param ident identifier to store stack to
      */
-    void store(final Symbol symbol) {
+    void store(final IdentNode ident) {
+        final Type type = ident.getType();
+        final Symbol symbol = ident.getSymbol();
+        if(type == Type.UNDEFINED) {
+            assert peekType() == Type.UNDEFINED;
+            store(symbol, Type.OBJECT);
+        } else {
+            store(symbol, type);
+        }
+    }
+
+    /**
+     * Represents a definition of a local variable with a type. Used for local variable table building.
+     */
+    private static class LocalVariableDef {
+        // The start label from where this definition lives.
+        private final jdk.internal.org.objectweb.asm.Label label;
+        // The currently live type of the local variable.
+        private final Type type;
+
+        LocalVariableDef(final jdk.internal.org.objectweb.asm.Label label, final Type type) {
+            this.label = label;
+            this.type = type;
+        }
+
+    }
+
+    void closeLocalVariable(final Symbol symbol, final Label label) {
+        final LocalVariableDef def = localVariableDefs.get(symbol);
+        if(def != null) {
+            endLocalValueDef(symbol, def, label.getLabel());
+        }
+        if(isReachable()) {
+            markDeadLocalVariable(symbol);
+        }
+    }
+
+    void markDeadLocalVariable(final Symbol symbol) {
+        if(!symbol.isDead()) {
+            markDeadSlots(symbol.getFirstSlot(), symbol.slotCount());
+        }
+    }
+
+    void markDeadSlots(final int firstSlot, final int slotCount) {
+        stack.markDeadLocalVariables(firstSlot, slotCount);
+    }
+
+    private void endLocalValueDef(final Symbol symbol, final LocalVariableDef def, final jdk.internal.org.objectweb.asm.Label label) {
+        String name = symbol.getName();
+        if (name.equals(THIS.symbolName())) {
+            name = THIS_DEBUGGER.symbolName();
+        }
+        method.visitLocalVariable(name, def.type.getDescriptor(), null, def.label, label, symbol.getSlot(def.type));
+    }
+
+    void store(final Symbol symbol, final Type type) {
+        store(symbol, type, true);
+    }
+
+    /**
+     * Pop a value from the stack and store it in a variable denoted by the given symbol. The variable should be either
+     * a local variable, or a function parameter (and not a scoped variable). For local variables, this method will also
+     * do the bookeeping of the local variable table as well as mark values in all alternative slots for the symbol as
+     * dead. In this regard it differs from {@link #storeHidden(Type, int)}.
+     *
+     * @param symbol the symbol to store into.
+     * @param type the type to store
+     * @param onlySymbolLiveValue if true, this is the sole live value for the symbol. If false, currently live values should
+     * be kept live.
+     */
+    void store(final Symbol symbol, final Type type, final boolean onlySymbolLiveValue) {
         assert symbol != null : "No symbol to store";
         if (symbol.hasSlot()) {
-            final int slot = symbol.getSlot();
-            debug("store symbol", symbol.getName(), " slot=", slot);
-            popType(symbol.getSymbolType()).store(method, slot);
+            final boolean isLiveType = symbol.hasSlotFor(type);
+            final LocalVariableDef existingDef = localVariableDefs.get(symbol);
+            if(existingDef == null || existingDef.type != type) {
+                final jdk.internal.org.objectweb.asm.Label here = new jdk.internal.org.objectweb.asm.Label();
+                if(isLiveType) {
+                    final LocalVariableDef newDef = new LocalVariableDef(here, type);
+                    localVariableDefs.put(symbol, newDef);
+                }
+                method.visitLabel(here);
+                if(existingDef != null) {
+                    endLocalValueDef(symbol, existingDef, here);
+                }
+            }
+            if(isLiveType) {
+                final int slot = symbol.getSlot(type);
+                debug("store symbol", symbol.getName(), " type=", type, " slot=", slot);
+                storeHidden(type, slot, onlySymbolLiveValue);
+            } else {
+                if(onlySymbolLiveValue) {
+                    markDeadLocalVariable(symbol);
+                }
+                debug("dead store symbol ", symbol.getName(), " type=", type);
+                pop();
+            }
         } else if (symbol.isParam()) {
             assert !symbol.isScope();
             assert functionNode.isVarArg() : "Non-vararg functions have slotted parameters";
             final int index = symbol.getFieldIndex();
             if (functionNode.needsArguments()) {
+                convert(Type.OBJECT);
                 debug("store symbol", symbol.getName(), " arguments index=", index);
                 loadCompilerConstant(ARGUMENTS);
                 load(index);
                 ArgumentSetter.SET_ARGUMENT.invoke(this);
             } else {
+                convert(Type.OBJECT);
                 // varargs without arguments object - just do array store to __varargs__
                 debug("store symbol", symbol.getName(), " array index=", index);
                 loadCompilerConstant(VARARGS);
                 load(index);
                 ArgumentSetter.SET_ARRAY_ELEMENT.invoke(this);
             }
+        } else {
+            debug("dead store symbol ", symbol.getName(), " type=", type);
+            pop();
         }
     }
 
     /**
-     * Pop a value from the stack and store it in a given local variable
-     * slot.
+     * Pop a value from the stack and store it in a local variable slot. Note that in contrast with
+     * {@link #store(Symbol, Type)}, this method does not adjust the local variable table, nor marks slots for
+     * alternative value types for the symbol as being dead. For that reason, this method is usually not called
+     * directly. Notable exceptions are temporary internal locals (e.g. quick store, last-catch-condition, etc.) that
+     * are not desired to show up in the local variable table.
      *
      * @param type the type to pop
      * @param slot the slot
      */
-    void store(final Type type, final int slot) {
+    void storeHidden(final Type type, final int slot) {
+        storeHidden(type, slot, true);
+    }
+
+    void storeHidden(final Type type, final int slot, final boolean onlyLiveSymbolValue) {
+        explicitStore(type, slot);
+        stack.onLocalStore(type, slot, onlyLiveSymbolValue);
+    }
+
+    void storeTemp(final Type type, final int slot) {
+        explicitStore(type, slot);
+        defineTemporaryLocalVariable(slot, slot + type.getSlots());
+        onLocalStore(type, slot);
+    }
+
+    void onLocalStore(final Type type, final int slot) {
+        stack.onLocalStore(type, slot, true);
+    }
+
+    private void explicitStore(final Type type, final int slot) {
+        assert slot != -1;
+        debug("explicit store", type, slot);
         popType(type);
         type.store(method, slot);
     }
 
     /**
+     * Marks a range of slots as belonging to a defined local variable. The slots will start out with no live value
+     * in them.
+     * @param fromSlot first slot, inclusive.
+     * @param toSlot last slot, exclusive.
+     */
+    void defineBlockLocalVariable(final int fromSlot, final int toSlot) {
+        stack.defineBlockLocalVariable(fromSlot, toSlot);
+    }
+
+    /**
+     * Marks a range of slots as belonging to a defined temporary local variable. The slots will start out with no
+     * live value in them.
+     * @param fromSlot first slot, inclusive.
+     * @param toSlot last slot, exclusive.
+     */
+    void defineTemporaryLocalVariable(final int fromSlot, final int toSlot) {
+        stack.defineTemporaryLocalVariable(fromSlot, toSlot);
+    }
+
+    /**
+     * Defines a new temporary local variable and returns its allocated index.
+     * @param width the required width (in slots) for the new variable.
+     * @return the bytecode slot index where the newly allocated local begins.
+     */
+    int defineTemporaryLocalVariable(final int width) {
+        return stack.defineTemporaryLocalVariable(width);
+    }
+
+    void undefineLocalVariables(final int fromSlot, final boolean canTruncateSymbol) {
+        if(isReachable()) {
+            stack.undefineLocalVariables(fromSlot, canTruncateSymbol);
+        }
+    }
+
+    List<Type> getLocalVariableTypes() {
+        return stack.localVariableTypes;
+    }
+
+    List<Type> getWidestLiveLocals(final List<Type> localTypes) {
+        return stack.getWidestLiveLocals(localTypes);
+    }
+
+    String markSymbolBoundariesInLvarTypesDescriptor(final String lvarDescriptor) {
+        return stack.markSymbolBoundariesInLvarTypesDescriptor(lvarDescriptor);
+    }
+
+    /**
      * Increment/Decrement a local integer by the given value.
      *
      * @param slot the int slot
@@ -999,9 +1324,9 @@
     public void athrow() {
         debug("athrow");
         final Type receiver = popType(Type.OBJECT);
-        assert receiver.isObject();
+        assert Throwable.class.isAssignableFrom(receiver.getTypeClass()) : receiver.getTypeClass();
         method.visitInsn(ATHROW);
-        stack = null;
+        doesNotContinueSequentially();
     }
 
     /**
@@ -1130,11 +1455,7 @@
             popType(Type.OBJECT);
         }
 
-        if (opcode == INVOKEINTERFACE) {
-            method.visitMethodInsn(opcode, className, methodName, methodDescriptor, true);
-        } else {
-            method.visitMethodInsn(opcode, className, methodName, methodDescriptor, false);
-        }
+        method.visitMethodInsn(opcode, className, methodName, methodDescriptor, opcode == INVOKEINTERFACE);
 
         if (returnType != null) {
             pushType(returnType);
@@ -1197,7 +1518,7 @@
      *
      * @return the method emitter
      */
-    MethodEmitter invokeStatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) {
+    MethodEmitter invokestatic(final String className, final String methodName, final String methodDescriptor, final Type returnType) {
         invokestatic(className, methodName, methodDescriptor);
         popType();
         pushType(returnType);
@@ -1235,8 +1556,9 @@
      */
     void lookupswitch(final Label defaultLabel, final int[] values, final Label... table) {//Collection<Label> table) {
         debug("lookupswitch", peekType());
-        popType(Type.INT);
+        adjustStackForSwitch(defaultLabel, table);
         method.visitLookupSwitchInsn(defaultLabel.getLabel(), values, getLabels(table));
+        doesNotContinueSequentially();
     }
 
     /**
@@ -1248,8 +1570,17 @@
      */
     void tableswitch(final int lo, final int hi, final Label defaultLabel, final Label... table) {
         debug("tableswitch", peekType());
-        popType(Type.INT);
+        adjustStackForSwitch(defaultLabel, table);
         method.visitTableSwitchInsn(lo, hi, defaultLabel.getLabel(), getLabels(table));
+        doesNotContinueSequentially();
+    }
+
+    private void adjustStackForSwitch(final Label defaultLabel, final Label... table) {
+        popType(Type.INT);
+        joinTo(defaultLabel);
+        for(final Label label: table) {
+            joinTo(label);
+        }
     }
 
     /**
@@ -1305,7 +1636,7 @@
             convert(type);
         }
         popType(type)._return(method);
-        stack = null;
+        doesNotContinueSequentially();
     }
 
     /**
@@ -1322,7 +1653,7 @@
         debug("return [void]");
         assert stack.isEmpty() : stack;
         method.visitInsn(RETURN);
-        stack = null;
+        doesNotContinueSequentially();
     }
 
     /**
@@ -1331,8 +1662,10 @@
      * jump target is another method
      *
      * @param label destination label
+     * @param targetNode the node to which the destination label belongs (the label is normally a break or continue
+     * label)
      */
-    void splitAwareGoto(final LexicalContext lc, final Label label) {
+    void splitAwareGoto(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
         _goto(label);
     }
 
@@ -1359,7 +1692,7 @@
             assert peekType().isInteger() || peekType().isBoolean() || peekType().isObject() : "expecting integer type or object for jump, but found " + peekType();
             popType();
         }
-        mergeStackTo(label);
+        joinTo(label);
         method.visitJumpInsn(opcode, label.getLabel());
     }
 
@@ -1454,6 +1787,16 @@
     }
 
     /**
+     * Generate an if_icmplt
+     *
+     * @param label label to true case
+     */
+    void if_icmplt(final Label label) {
+        debug("if_icmplt", label);
+        jump(IF_ICMPLT, label, 2);
+    }
+
+    /**
      * Generate an ifle
      *
      * @param label label to true case
@@ -1464,6 +1807,16 @@
     }
 
     /**
+     * Generate an if_icmple
+     *
+     * @param label label to true case
+     */
+    void if_icmple(final Label label) {
+        debug("if_icmple", label);
+        jump(IF_ICMPLE, label, 2);
+    }
+
+    /**
      * Generate an ifgt
      *
      * @param label label to true case
@@ -1474,6 +1827,16 @@
     }
 
     /**
+     * Generate an if_icmpgt
+     *
+     * @param label label to true case
+     */
+    void if_icmpgt(final Label label) {
+        debug("if_icmpgt", label);
+        jump(IF_ICMPGT, label, 2);
+    }
+
+    /**
      * Generate an ifge
      *
      * @param label label to true case
@@ -1484,24 +1847,58 @@
     }
 
     /**
+     * Generate an if_icmpge
+     *
+     * @param label label to true case
+     */
+    void if_icmpge(final Label label) {
+        debug("if_icmpge", label);
+        jump(IF_ICMPGE, label, 2);
+    }
+
+    /**
      * Unconditional jump to a label
      *
      * @param label destination label
      */
     void _goto(final Label label) {
-        //debug("goto", label);
+        debug("goto", label);
         jump(GOTO, label, 0);
-        stack = null; //whoever reaches the point after us provides the stack, because we don't
+        doesNotContinueSequentially(); //whoever reaches the point after us provides the stack, because we don't
     }
 
     /**
-     * Examine two stacks and make sure they are of the same size and their
-     * contents are equivalent to each other
-     * @param s0 first stack
-     * @param s1 second stack
+     * Unconditional jump to the start label of a loop. It differs from ordinary {@link #_goto(Label)} in that it will
+     * preserve the current label stack, as the next instruction after the goto is loop body that the loop will come
+     * back to. Also used to jump at the start label of the continuation handler, as it behaves much like a loop test in
+     * the sense that after it is evaluated, it also jumps backwards.
      *
-     * @return true if stacks are equivalent, false otherwise
+     * @param loopStart start label of a loop
      */
+    void gotoLoopStart(final Label loopStart) {
+        debug("goto (loop)", loopStart);
+        jump(GOTO, loopStart, 0);
+    }
+
+    /**
+     * Unconditional jump without any control flow and data flow testing. You should not normally use this method when
+     * generating code, except if you're very sure that you know what you're doing. Normally only used for the
+     * admittedly torturous control flow of continuation handler plumbing.
+     * @param target the target of the jump
+     */
+    void uncheckedGoto(final Label target) {
+        method.visitJumpInsn(GOTO, target.getLabel());
+    }
+
+    /**
+     * Potential transfer of control to a catch block.
+     *
+     * @param catchLabel destination catch label
+     */
+    void canThrow(final Label catchLabel) {
+        catchLabel.joinFromTry(stack, false);
+    }
+
     /**
      * A join in control flow - helper function that makes sure all entry stacks
      * discovered for the join point so far are equivalent
@@ -1511,45 +1908,46 @@
      *
      * @param label label
      */
-    private void mergeStackTo(final Label label) {
-        //sometimes we can do a merge stack without having a stack - i.e. when jumping ahead to dead code
-        //see NASHORN-73. So far we had been saved by the line number nodes. This should have been fixed
-        //by Lower removing everything after an unconditionally executed terminating statement OR a break
-        //or continue in a block. Previously code left over after breaks and continues was still there
-        //and caused bytecode to be generated - which crashed on stack not being there, as the merge
-        //was not in fact preceeded by a visit. Furthermore, this led to ASM putting out its NOP NOP NOP
-        //ATHROW sequences instead of no code being generated at all. This should now be fixed.
-        assert stack != null : label + " entered with no stack. deadcode that remains?";
-
-        final Label.Stack labelStack = label.getStack();
-        if (labelStack == null) {
-            label.setStack(stack.copy());
-            return;
-        }
-        assert stack.isEquivalentTo(labelStack) : "stacks " + stack + " is not equivalent with " + labelStack + " at join point";
+    private void joinTo(final Label label) {
+        assert isReachable();
+        label.joinFrom(stack);
     }
 
     /**
      * Register a new label, enter it here.
-     *
-     * @param label the label
+     * @param label
      */
     void label(final Label label) {
-        /*
-         * If stack == null, this means that we came here not through a fallthrough.
-         * E.g. a label after an athrow. Then we create a new stack if one doesn't exist
-         * for this location already.
-         */
-        if (stack == null) {
-            stack = label.getStack();
-            if (stack == null) {
-                newStack();
-            }
+        breakLabel(label, -1);
+    }
+
+    /**
+     * Register a new break target label, enter it here.
+     *
+     * @param label the label
+     * @param liveLocals the number of live locals at this label
+     */
+    void breakLabel(final Label label, final int liveLocals) {
+        if (!isReachable()) {
+            // If we emit a label, and the label's stack is null, it must not be reachable.
+            assert (label.getStack() == null) != label.isReachable();
+        } else {
+            joinTo(label);
+        }
+        // Use label's stack as we might have no stack.
+        final Label.Stack labelStack = label.getStack();
+        stack = labelStack == null ? null : labelStack.clone();
+        if(stack != null && label.isBreakTarget() && liveLocals != -1) {
+            // This has to be done because we might not have another frame to provide us with its firstTemp if the label
+            // is only reachable through a break or continue statement; also in this case, the frame can actually
+            // give us a higher number of live locals, e.g. if it comes from a catch. Typical example:
+            // for(;;) { try{ throw 0; } catch(e) { break; } }.
+            // Since the for loop can only be exited through the break in the catch block, it'll bring with it the
+            // "e" as a live local, and we need to trim it off here.
+            assert stack.firstTemp >= liveLocals;
+            stack.firstTemp = liveLocals;
         }
         debug_label(label);
-
-        mergeStackTo(label); //we have to merge our stack to whatever is in the label
-
         method.visitLabel(label.getLabel());
     }
 
@@ -1561,13 +1959,32 @@
      * @return the method emitter
      */
     MethodEmitter convert(final Type to) {
-        final Type type = peekType().convert(method, to);
+        final Type from = peekType();
+        final Type type = from.convert(method, to);
         if (type != null) {
-            if (!peekType().isEquivalentTo(to)) {
-                debug("convert", peekType(), "->", to);
+            if (!from.isEquivalentTo(to)) {
+                debug("convert", from, "->", to);
             }
-            popType();
-            pushType(type);
+            if (type != from) {
+                final int l0 = stack.getTopLocalLoad();
+                popType();
+                pushType(type);
+                // NOTE: conversions from a primitive type are considered to preserve the "load" property of the value
+                // on the stack. Otherwise we could introduce temporary locals in a deoptimized rest-of (e.g. doing an
+                // "i < x.length" where "i" is int and ".length" gets deoptimized to long would end up converting i to
+                // long with "ILOAD i; I2L; LSTORE tmp; LLOAD tmp;"). Such additional temporary would cause an error
+                // when restoring the state of the function for rest-of execution, as the not-yet deoptimized variant
+                // would have the (now invalidated) assumption that "x.length" is an int, so it wouldn't have the I2L,
+                // and therefore neither the subsequent LSTORE tmp; LLOAD tmp;. By making sure conversions from a
+                // primitive type don't erase the "load" information, we don't introduce temporaries in the deoptimized
+                // rest-of that didn't exist in the more optimistic version that triggered the deoptimization.
+                // NOTE: as a more general observation, we could theoretically track the operations required to
+                // reproduce any stack value as long as they are all local loads, constant loads, and stack operations.
+                // We won't go there in the current system
+                if(!from.isObject()) {
+                    stack.markLocalLoad(l0);
+                }
+            }
         }
         return this;
     }
@@ -1590,8 +2007,8 @@
      * @return common type
      */
     private BitwiseType get2i() {
-        final BitwiseType p0 = popInteger();
-        final BitwiseType p1 = popInteger();
+        final BitwiseType p0 = popBitwise();
+        final BitwiseType p1 = popBitwise();
         assert p0.isEquivalentTo(p1) : "expecting equivalent types on stack but got " + p0 + " and " + p1;
         return p0;
     }
@@ -1613,9 +2030,9 @@
      *
      * @return the method emitter
      */
-    MethodEmitter add() {
+    MethodEmitter add(final int programPoint) {
         debug("add");
-        pushType(get2().add(method));
+        pushType(get2().add(method, programPoint));
         return this;
     }
 
@@ -1624,9 +2041,9 @@
      *
      * @return the method emitter
      */
-    MethodEmitter sub() {
+    MethodEmitter sub(final int programPoint) {
         debug("sub");
-        pushType(get2n().sub(method));
+        pushType(get2n().sub(method, programPoint));
         return this;
     }
 
@@ -1635,9 +2052,9 @@
      *
      * @return the method emitter
      */
-    MethodEmitter mul() {
+    MethodEmitter mul(final int programPoint) {
         debug("mul ");
-        pushType(get2n().mul(method));
+        pushType(get2n().mul(method, programPoint));
         return this;
     }
 
@@ -1646,9 +2063,9 @@
      *
      * @return the method emitter
      */
-    MethodEmitter div() {
+    MethodEmitter div(final int programPoint) {
         debug("div");
-        pushType(get2n().div(method));
+        pushType(get2n().div(method, programPoint));
         return this;
     }
 
@@ -1657,9 +2074,9 @@
      *
      * @return the method emitter
      */
-    MethodEmitter rem() {
+    MethodEmitter rem(final int programPoint) {
         debug("rem");
-        pushType(get2n().rem(method));
+        pushType(get2n().rem(method, programPoint));
         return this;
     }
 
@@ -1670,13 +2087,23 @@
      * @return array of Types
      */
     protected Type[] getTypesFromStack(final int count) {
-        final Type[] types = new Type[count];
-        int pos = 0;
-        for (int i = count - 1; i >= 0; i--) {
-            types[i] = stack.peek(pos++);
-        }
+        return stack.getTopTypes(count);
+    }
 
-        return types;
+    int[] getLocalLoadsOnStack(final int from, final int to) {
+        return stack.getLocalLoads(from, to);
+    }
+
+    int getStackSize() {
+        return stack.size();
+    }
+
+    int getFirstTemp() {
+        return stack.firstTemp;
+    }
+
+    int getUsedSlotsWithLiveTemporaries() {
+        return stack.getUsedSlotsWithLiveTemporaries();
     }
 
     /**
@@ -1703,6 +2130,15 @@
         return descriptor;
     }
 
+    MethodEmitter invalidateSpecialName(final String name) {
+        //this is a nop if the global hasn't registered this as a special name - we can just ignore it
+        if (Global.instance().isSpecialName(name)) {
+            debug("dynamic_invalidate_name", "name=", name);
+            method.visitInvokeDynamicInsn(name, "()V", INVALIDATE_NAME_BOOTSTRAP);
+        }
+        return this;
+    }
+
     /**
      * Generate a dynamic new
      *
@@ -1712,6 +2148,7 @@
      * @return the method emitter
      */
     MethodEmitter dynamicNew(final int argCount, final int flags) {
+        assert !isOptimistic(flags);
         debug("dynamic_new", "argcount=", argCount);
         final String signature = getDynamicSignature(Type.OBJECT, argCount);
         method.visitInvokeDynamicInsn("dyn:new", signature, LINKERBOOTSTRAP, flags);
@@ -1738,6 +2175,14 @@
         return this;
     }
 
+    MethodEmitter dynamicArrayPopulatorCall(final int argCount, final int startIndex) {
+        debug("populate_array", "args=", argCount, "startIndex=", startIndex);
+        final String signature = getDynamicSignature(Type.OBJECT_ARRAY, argCount);
+        method.visitInvokeDynamicInsn("populateArray", signature, POPULATE_ARRAY_BOOTSTRAP, startIndex);
+        pushType(Type.OBJECT_ARRAY);
+        return this;
+    }
+
     /**
      * Generate a dynamic call for a runtime node
      *
@@ -1768,7 +2213,7 @@
      * @return the method emitter
      */
     MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
-        debug("dynamic_get", name, valueType);
+        debug("dynamic_get", name, valueType, getProgramPoint(flags));
 
         Type type = valueType;
         if (type.isObject() || type.isBoolean()) {
@@ -1780,7 +2225,6 @@
                 NameCodec.encode(name), Type.getMethodDescriptor(type, Type.OBJECT), LINKERBOOTSTRAP, flags);
 
         pushType(type);
-
         convert(valueType); //most probably a nop
 
         return this;
@@ -1794,7 +2238,8 @@
      * @param flags     call site flags
      */
      void dynamicSet(final String name, final int flags) {
-        debug("dynamic_set", name, peekType());
+         assert !isOptimistic(flags);
+         debug("dynamic_set", name, peekType());
 
         Type type = peekType();
         if (type.isObject() || type.isBoolean()) { //promote strings to objects etc
@@ -1818,7 +2263,8 @@
      * @return the method emitter
      */
     MethodEmitter dynamicGetIndex(final Type result, final int flags, final boolean isMethod) {
-        debug("dynamic_get_index", peekType(1), "[", peekType(), "]");
+        assert result.getTypeClass().isPrimitive() || result.getTypeClass() == Object.class;
+        debug("dynamic_get_index", peekType(1), "[", peekType(), "]", getProgramPoint(flags));
 
         Type resultType = result;
         if (result.isBoolean()) {
@@ -1836,8 +2282,7 @@
 
         final String signature = Type.getMethodDescriptor(resultType, Type.OBJECT /*e.g STRING->OBJECT*/, index);
 
-        method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod",
-                signature, LINKERBOOTSTRAP, flags);
+        method.visitInvokeDynamicInsn(isMethod ? "dyn:getMethod|getElem|getProp" : "dyn:getElem|getProp|getMethod", signature, LINKERBOOTSTRAP, flags);
         pushType(resultType);
 
         if (result.isBoolean()) {
@@ -1847,6 +2292,13 @@
         return this;
     }
 
+    private static String getProgramPoint(final int flags) {
+        if((flags & CALLSITE_OPTIMISTIC) == 0) {
+            return "";
+        }
+        return "pp=" + String.valueOf((flags & (-1 << CALLSITE_PROGRAM_POINT_SHIFT)) >> CALLSITE_PROGRAM_POINT_SHIFT);
+    }
+
     /**
      * Dynamic setter for indexed structures. Pop value, index and receiver from
      * stack, generate appropriate signature based on types
@@ -1854,6 +2306,7 @@
      * @param flags call site flags for setter
      */
     void dynamicSetIndex(final int flags) {
+        assert !isOptimistic(flags);
         debug("dynamic_set_index", peekType(2), "[", peekType(1), "] =", peekType());
 
         Type value = peekType();
@@ -2012,7 +2465,7 @@
      * @param label label
      */
     void lineNumber(final int line) {
-        if (env._debug_lines) {
+        if (context.getEnv()._debug_lines) {
             debug_label("[LINE]", line);
             final jdk.internal.org.objectweb.asm.Label l = new jdk.internal.org.objectweb.asm.Label();
             method.visitLabel(l);
@@ -2020,6 +2473,44 @@
         }
     }
 
+    void beforeJoinPoint(final JoinPredecessor joinPredecessor) {
+        LocalVariableConversion next = joinPredecessor.getLocalVariableConversion();
+        while(next != null) {
+            final Symbol symbol = next.getSymbol();
+            if(next.isLive()) {
+                emitLocalVariableConversion(next, true);
+            } else {
+                markDeadLocalVariable(symbol);
+            }
+            next = next.getNext();
+        }
+    }
+
+    void beforeTry(final TryNode tryNode, final Label recovery) {
+        LocalVariableConversion next = tryNode.getLocalVariableConversion();
+        while(next != null) {
+            if(next.isLive()) {
+                final Type to = emitLocalVariableConversion(next, false);
+                recovery.getStack().onLocalStore(to, next.getSymbol().getSlot(to), true);
+            }
+            next = next.getNext();
+        }
+    }
+
+    private Type emitLocalVariableConversion(final LocalVariableConversion conversion, final boolean onlySymbolLiveValue) {
+        final Type from = conversion.getFrom();
+        final Type to = conversion.getTo();
+        final Symbol symbol = conversion.getSymbol();
+        assert symbol.isBytecodeLocal();
+        if(from == Type.UNDEFINED) {
+            loadUndefined(to);
+        } else {
+            load(symbol, from).convert(to);
+        }
+        store(symbol, to, onlySymbolLiveValue);
+        return to;
+    }
+
     /*
      * Debugging below
      */
@@ -2087,7 +2578,7 @@
      * @param args debug information to print
      */
     private void debug(final Object... args) {
-        if (DEBUG) {
+        if (debug) {
             debug(30, args);
         }
     }
@@ -2099,13 +2590,13 @@
      * @param args debug information to print
      */
     private void debug_label(final Object... args) {
-        if (DEBUG) {
+        if (debug) {
             debug(22, args);
         }
     }
 
     private void debug(final int padConstant, final Object... args) {
-        if (DEBUG) {
+        if (debug) {
             final StringBuilder sb = new StringBuilder();
             int pad;
 
@@ -2118,7 +2609,7 @@
                 pad--;
             }
 
-            if (stack != null && !stack.isEmpty()) {
+            if (isReachable() && !stack.isEmpty()) {
                 sb.append("{");
                 sb.append(stack.size());
                 sb.append(":");
@@ -2148,7 +2639,10 @@
                     } else {
                         sb.append(t.getDescriptor());
                     }
-
+                    final int loadIndex = stack.localLoads[stack.sp - 1 - pos];
+                    if(loadIndex != Label.Stack.NON_LOAD) {
+                        sb.append('(').append(loadIndex).append(')');
+                    }
                     if (pos + 1 < stack.size()) {
                         sb.append(' ');
                     }
@@ -2168,10 +2662,10 @@
                 sb.append(' ');
             }
 
-            if (env != null) { //early bootstrap code doesn't have inited context yet
-                LOG.info(sb);
+            if (context.getEnv() != null) { //early bootstrap code doesn't have inited context yet
+                log.info(sb);
                 if (DEBUG_TRACE_LINE == linePrefix) {
-                    new Throwable().printStackTrace(LOG.getOutputStream());
+                    new Throwable().printStackTrace(log.getOutputStream());
                 }
             }
         }
@@ -2189,8 +2683,17 @@
         return hasReturn;
     }
 
-    List<Label> getExternalTargets() {
-        return null;
+    /**
+     * Invoke to enforce assertions preventing load from a local variable slot that's known to not have been written to.
+     * Used by CodeGenerator, as it strictly enforces tracking of stores. Simpler uses of MethodEmitter, e.g. those
+     * for creating initializers for structure  classes, array getters, etc. don't have strict tracking of stores,
+     * therefore they would fail if they had this assertion turned on.
+     */
+    void setPreventUndefinedLoad() {
+        this.preventUndefinedLoad = true;
     }
 
+    private static boolean isOptimistic(final int flags) {
+        return (flags & CALLSITE_OPTIMISTIC) != 0;
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Namespace.java b/nashorn/src/jdk/nashorn/internal/codegen/Namespace.java
index 72f77a5..5c5115a 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Namespace.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Namespace.java
@@ -80,7 +80,6 @@
             if (counter != null) {
                 final int count = counter + 1;
                 namespaceDirectory.put(base, count);
-
                 return base + '-' + count;
             }
         }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java b/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
index 21cc3c5..815ce27 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectClassGenerator.java
@@ -35,12 +35,20 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.className;
 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT;
+import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.JSType.GET_UNDEFINED;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_DOUBLE_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_INT_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_LONG_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_OBJECT_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.TYPE_UNDEFINED_INDEX;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import java.util.Arrays;
-import java.util.Collections;
 import java.util.EnumSet;
 import java.util.Iterator;
 import java.util.LinkedList;
@@ -49,24 +57,35 @@
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.Context;
-import jdk.nashorn.internal.runtime.DebugLogger;
 import jdk.nashorn.internal.runtime.FunctionScope;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.Undefined;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
  * Generates the ScriptObject subclass structure with fields for a user objects.
  */
-public final class ObjectClassGenerator {
+@Logger(name="fields")
+public final class ObjectClassGenerator implements Loggable {
 
     /**
-     * Marker for scope parameters.
+     * Type guard to make sure we don't unnecessarily explode field storages. Rather unbox e.g.
+     * a java.lang.Number than blow up the field. Gradually, optimistic types should create almost
+     * no boxed types
      */
-    static final String SCOPE_MARKER = "P";
+    private static final MethodHandle IS_TYPE_GUARD = findOwnMH("isType", boolean.class, Class.class, Object.class);
+
+    /**
+     * Marker for scope parameters
+     */
+    private static final String SCOPE_MARKER = "P";
 
     /**
      * Minimum number of extra fields in an object.
@@ -77,29 +96,26 @@
      * Debug field logger
      * Should we print debugging information for fields when they are generated and getters/setters are called?
      */
-    public static final DebugLogger LOG = new DebugLogger("fields", "nashorn.fields.debug");
-
-    /**
-     * is field debugging enabled. Several modules in codegen and properties use this, hence
-     * public access.
-     */
-    public static final boolean DEBUG_FIELDS = LOG.isEnabled();
+    private final DebugLogger log;
 
     /**
      * Should the runtime only use java.lang.Object slots for fields? If this is false, the representation
      * will be a primitive 64-bit long value used for all primitives and a java.lang.Object for references.
      * This introduces a larger number of method handles in the system, as we need to have different getters
-     * and setters for the different fields. Currently this introduces significant overhead in Hotspot.
+     * and setters for the different fields.
      *
      * This is engineered to plug into the TaggedArray implementation, when it's done.
      */
-    public static final boolean OBJECT_FIELDS_ONLY = !Options.getBooleanProperty("nashorn.fields.dual");
+    public static final boolean OBJECT_FIELDS_ONLY = Options.getBooleanProperty("nashorn.fields.objects");
 
     /** The field types in the system */
     private static final List<Type> FIELD_TYPES = new LinkedList<>();
 
     /** What type is the primitive type in dual representation */
-    public static final Type PRIMITIVE_TYPE = Type.LONG;
+    public static final Type PRIMITIVE_FIELD_TYPE = Type.LONG;
+
+    private static final MethodHandle GET_DIFFERENT           = findOwnMH("getDifferent", Object.class, Object.class, Class.class, MethodHandle.class, MethodHandle.class, int.class);
+    private static final MethodHandle GET_DIFFERENT_UNDEFINED = findOwnMH("getDifferentUndefined", Object.class, int.class);
 
     /**
      * The list of field types that we support - one type creates one field. This is currently either
@@ -107,33 +123,16 @@
      */
     static {
         if (!OBJECT_FIELDS_ONLY) {
-            System.err.println("WARNING!!! Running with primitive fields - there is untested functionality!");
-            FIELD_TYPES.add(PRIMITIVE_TYPE);
+            FIELD_TYPES.add(PRIMITIVE_FIELD_TYPE);
         }
         FIELD_TYPES.add(Type.OBJECT);
     }
+    private static boolean initialized = false;
 
     /** The context */
     private final Context context;
 
     /**
-     * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
-     *  in the dual--fields world
-     */
-    public static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
-            Arrays.asList(
-                Type.INT,
-                Type.LONG,
-                Type.NUMBER,
-                Type.OBJECT));
-
-    //these are hard coded for speed and so that we can switch on them
-    private static final int TYPE_INT_INDEX    = 0; //getAccessorTypeIndex(int.class);
-    private static final int TYPE_LONG_INDEX   = 1; //getAccessorTypeIndex(long.class);
-    private static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class);
-    private static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class);
-
-    /**
      * Constructor
      *
      * @param context a context
@@ -141,64 +140,39 @@
     public ObjectClassGenerator(final Context context) {
         this.context = context;
         assert context != null;
-    }
-
-    /**
-     * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes())
-     *
-     * @param type the type
-     *
-     * @return the accessor index, or -1 if no accessor of this type exists
-     */
-    public static int getAccessorTypeIndex(final Type type) {
-        return getAccessorTypeIndex(type.getTypeClass());
-    }
-
-    /**
-     * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes())
-     *
-     * Note that this is hardcoded with respect to the dynamic contents of the accessor
-     * types array for speed. Hotspot got stuck with this as 5% of the runtime in
-     * a benchmark when it looped over values and increased an index counter. :-(
-     *
-     * @param type the type
-     *
-     * @return the accessor index, or -1 if no accessor of this type exists
-     */
-    public static int getAccessorTypeIndex(final Class<?> type) {
-        if (type == int.class) {
-            return 0;
-        } else if (type == long.class) {
-            return 1;
-        } else if (type == double.class) {
-            return 2;
-        } else if (!type.isPrimitive()) {
-            return 3;
+        this.log = initLogger(context);
+        if (!initialized) {
+            initialized = true;
+            if (OBJECT_FIELDS_ONLY) {
+                log.warning("Running with object fields only - this is a deprecated configuration.");
+            }
         }
-        return -1;
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context ctxt) {
+        return ctxt.getLogger(this.getClass());
     }
 
     /**
-     * Return the number of accessor types available.
-     *
-     * @return number of accessor types in system
+     * Pack a number into a primitive long field
+     * @param n number object
+     * @return primitive long value with all the bits in the number
      */
-    public static int getNumberOfAccessorTypes() {
-        return ACCESSOR_TYPES.size();
-    }
-
-    /**
-     * Return the accessor type based on its index in [0..getNumberOfAccessorTypes())
-     * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always
-     * go to a type of higher index
-     *
-     * @param index accessor type index
-     *
-     * @return a type corresponding to the index.
-     */
-
-    public static Type getAccessorType(final int index) {
-        return ACCESSOR_TYPES.get(index);
+    public static long pack(final Number n) {
+        if (n instanceof Integer) {
+            return n.intValue();
+        } else if (n instanceof Long) {
+            return n.longValue();
+        } else if (n instanceof Double) {
+            return Double.doubleToRawLongBits(n.doubleValue());
+        }
+        throw new AssertionError("cannot pack" + n);
     }
 
     /**
@@ -232,10 +206,10 @@
      * @param clazz the JavaScript scope class.
      * @return the number of fields in the scope class.
      */
-    public static int getFieldCount(Class<?> clazz) {
+    public static int getFieldCount(final Class<?> clazz) {
         final String name = clazz.getSimpleName();
         final String prefix = JS_OBJECT_PREFIX.symbolName();
-        if(prefix.equals(name)) {
+        if (prefix.equals(name)) {
             return 0;
         }
         final int scopeMarker = name.indexOf(SCOPE_MARKER);
@@ -264,13 +238,16 @@
      * @param fieldNames fields to initialize to undefined, where applicable
      */
     private static void initializeToUndefined(final MethodEmitter init, final String className, final List<String> fieldNames) {
+        if (!OBJECT_FIELDS_ONLY) {
+            // no need to initialize anything to undefined in the dual field world
+            // - then we have a constant getter for undefined for any unknown type
+            return;
+        }
+
         if (fieldNames.isEmpty()) {
             return;
         }
 
-        // always initialize fields to undefined, even with --dual-fields. Then it's ok to
-        // remember things like "widest set type" in properties, and if it's object, don't
-        // add any special "return undefined" getters, saving an invalidation
         init.load(Type.OBJECT, JAVA_THIS.slot());
         init.loadUndefined(Type.OBJECT);
 
@@ -324,8 +301,12 @@
         init.returnVoid();
         init.end();
 
-        newEmptyInit(classEmitter, className);
-        newAllocate(classEmitter, className);
+        final MethodEmitter initWithSpillArrays = newInitWithSpillArraysMethod(classEmitter, ScriptObject.class);
+        initWithSpillArrays.returnVoid();
+        initWithSpillArrays.end();
+
+        newEmptyInit(className, classEmitter);
+        newAllocate(className, classEmitter);
 
         return toByteArray(classEmitter);
     }
@@ -340,8 +321,8 @@
      * @return Byte codes for generated class.
      */
     public byte[] generate(final int fieldCount, final int paramCount) {
-        final String className          = getClassName(fieldCount, paramCount);
-        final String superName          = className(FunctionScope.class);
+        final String       className    = getClassName(fieldCount, paramCount);
+        final String       superName    = className(FunctionScope.class);
         final ClassEmitter classEmitter = newClassEmitter(className, superName);
         final List<String> initFields   = addFields(classEmitter, fieldCount);
 
@@ -350,6 +331,11 @@
         init.returnVoid();
         init.end();
 
+        final MethodEmitter initWithSpillArrays = newInitWithSpillArraysMethod(classEmitter, FunctionScope.class);
+        initializeToUndefined(initWithSpillArrays, className, initFields);
+        initWithSpillArrays.returnVoid();
+        initWithSpillArrays.end();
+
         final MethodEmitter initWithArguments = newInitScopeWithArgumentsMethod(classEmitter);
         initializeToUndefined(initWithArguments, className, initFields);
         initWithArguments.returnVoid();
@@ -391,7 +377,7 @@
      * @return Open class emitter.
      */
     private ClassEmitter newClassEmitter(final String className, final String superName) {
-        final ClassEmitter classEmitter = new ClassEmitter(context.getEnv(), className, superName);
+        final ClassEmitter classEmitter = new ClassEmitter(context, className, superName);
         classEmitter.begin();
 
         return classEmitter;
@@ -414,6 +400,18 @@
         return init;
     }
 
+     private static MethodEmitter newInitWithSpillArraysMethod(final ClassEmitter classEmitter, final Class<?> superClass) {
+        final MethodEmitter init = classEmitter.init(PropertyMap.class, long[].class, Object[].class);
+        init.begin();
+        init.load(Type.OBJECT, JAVA_THIS.slot());
+        init.load(Type.OBJECT, INIT_MAP.slot());
+        init.load(Type.LONG_ARRAY, 2);
+        init.load(Type.OBJECT_ARRAY, 3);
+        init.invoke(constructorNoLookup(superClass, PropertyMap.class, long[].class, Object[].class));
+
+        return init;
+    }
+
     /**
      * Allocate and initialize a new <init> method for scopes.
      * @param classEmitter  Open class emitter.
@@ -453,7 +451,7 @@
      * @param classEmitter Open class emitter.
      * @param className    Name of JavaScript class.
      */
-    private static void newEmptyInit(final ClassEmitter classEmitter, final String className) {
+    private static void newEmptyInit(final String className, final ClassEmitter classEmitter) {
         final MethodEmitter emptyInit = classEmitter.init();
         emptyInit.begin();
         emptyInit.load(Type.OBJECT, JAVA_THIS.slot());
@@ -469,10 +467,10 @@
      * @param classEmitter Open class emitter.
      * @param className    Name of JavaScript class.
      */
-    private static void newAllocate(final ClassEmitter classEmitter, final String className) {
+    private static void newAllocate(final String className, final ClassEmitter classEmitter) {
         final MethodEmitter allocate = classEmitter.method(EnumSet.of(Flag.PUBLIC, Flag.STATIC), ALLOCATE.symbolName(), ScriptObject.class, PropertyMap.class);
         allocate.begin();
-        allocate._new(className);
+        allocate._new(className, Type.typeFor(ScriptObject.class));
         allocate.dup();
         allocate.load(Type.typeFor(PropertyMap.class), 0);
         allocate.invoke(constructorNoLookup(className, PropertyMap.class));
@@ -492,7 +490,7 @@
         final byte[] code = classEmitter.toByteArray();
         final ScriptEnvironment env = context.getEnv();
 
-        if (env._print_code) {
+        if (env._print_code && env._print_code_dir == null) {
             env.getErr().println(ClassEmitter.disassemble(code));
         }
 
@@ -504,20 +502,174 @@
     }
 
     /** Double to long bits, used with --dual-fields for primitive double values */
-    private static final MethodHandle PACK_DOUBLE =
+    public static final MethodHandle PACK_DOUBLE =
         MH.explicitCastArguments(MH.findStatic(MethodHandles.publicLookup(), Double.class, "doubleToRawLongBits", MH.type(long.class, double.class)), MH.type(long.class, double.class));
 
     /** double bits to long, used with --dual-fields for primitive double values */
-    private static MethodHandle UNPACK_DOUBLE =
+    public static final MethodHandle UNPACK_DOUBLE =
         MH.findStatic(MethodHandles.publicLookup(), Double.class, "longBitsToDouble", MH.type(double.class, long.class));
 
-    /** object conversion quickies with JS semantics - used for return value and parameter filter */
-    private static MethodHandle[] CONVERT_OBJECT = {
-        JSType.TO_INT32.methodHandle(),
-        JSType.TO_UINT32.methodHandle(),
-        JSType.TO_NUMBER.methodHandle(),
-        null
-    };
+    //type != forType, so use the correct getter for forType, box it and throw
+    @SuppressWarnings("unused")
+    private static Object getDifferent(final Object receiver, final Class<?> forType, final MethodHandle primitiveGetter, final MethodHandle objectGetter, final int programPoint) {
+        //create the sametype getter, and upcast to value. no matter what the store format is,
+        //
+        final MethodHandle sameTypeGetter = getterForType(forType, primitiveGetter, objectGetter);
+        final MethodHandle mh = MH.asType(sameTypeGetter, sameTypeGetter.type().changeReturnType(Object.class));
+        try {
+            final Object value = mh.invokeExact(receiver);
+            throw new UnwarrantedOptimismException(value, programPoint);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static Object getDifferentUndefined(final int programPoint) {
+        throw new UnwarrantedOptimismException(Undefined.getUndefined(), programPoint);
+    }
+
+    private static MethodHandle getterForType(final Class<?> forType, final MethodHandle primitiveGetter, final MethodHandle objectGetter) {
+        switch (getAccessorTypeIndex(forType)) {
+        case TYPE_INT_INDEX:
+            assert !OBJECT_FIELDS_ONLY : "this can only happen with dual fields";
+            return MH.explicitCastArguments(primitiveGetter, primitiveGetter.type().changeReturnType(int.class));
+        case TYPE_LONG_INDEX:
+            assert !OBJECT_FIELDS_ONLY : "this can only happen with dual fields";
+            return primitiveGetter;
+        case TYPE_DOUBLE_INDEX:
+            assert !OBJECT_FIELDS_ONLY : "this can only happen with dual fields";
+            return MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE);
+        case TYPE_OBJECT_INDEX:
+            return objectGetter;
+        default:
+            throw new AssertionError(forType);
+        }
+    }
+
+    //no optimism here. we do unconditional conversion to types
+    private static MethodHandle createGetterInner(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter, final List<MethodHandle> converters, final int programPoint) {
+        final int fti = forType == null ? TYPE_UNDEFINED_INDEX : getAccessorTypeIndex(forType);
+        final int ti  = getAccessorTypeIndex(type);
+        //this means fail if forType != type
+        final boolean isOptimistic = converters == CONVERT_OBJECT_OPTIMISTIC;
+        final boolean isPrimitiveStorage = forType != null && forType.isPrimitive();
+
+        //which is the primordial getter
+        final MethodHandle getter = OBJECT_FIELDS_ONLY ? objectGetter : isPrimitiveStorage ? primitiveGetter : objectGetter;
+
+        if (forType == null) {
+            if (isOptimistic) {
+                //return undefined if asking for object. otherwise throw UnwarrantedOptimismException
+                if (ti == TYPE_OBJECT_INDEX) {
+                    return MH.dropArguments(GET_UNDEFINED.get(TYPE_OBJECT_INDEX), 0, Object.class);
+                }
+                //throw exception
+                return MH.asType(
+                    MH.dropArguments(
+                            MH.insertArguments(
+                                    GET_DIFFERENT_UNDEFINED,
+                                    0,
+                                    programPoint),
+                            0,
+                            Object.class),
+                    getter.type().changeReturnType(type));
+            }
+            //return an undefined and coerce it to the appropriate type
+            return MH.dropArguments(GET_UNDEFINED.get(ti), 0, Object.class);
+        }
+
+        assert forType != null;
+        assert !OBJECT_FIELDS_ONLY || forType == Object.class : forType;
+
+        if (isOptimistic) {
+            if (fti < ti) {
+                //asking for a wider type than currently stored. then it's OK to coerce.
+                //e.g. stored as int,  ask for long or double
+                //e.g. stored as long, ask for double
+                assert fti != TYPE_UNDEFINED_INDEX;
+                final MethodHandle tgetter = getterForType(forType, primitiveGetter, objectGetter);
+                return MH.asType(tgetter, tgetter.type().changeReturnType(type));
+            } else if (fti == ti) {
+                //Fast path, never throw exception - exact getter, just unpack if needed
+                return getterForType(forType, primitiveGetter, objectGetter);
+            } else {
+                assert fti > ti;
+                //if asking for a narrower type than the storage - throw exception
+                //unless FTI is object, in that case we have to go through the converters
+                //there is no
+                if (fti == TYPE_OBJECT_INDEX) {
+                    return MH.filterReturnValue(
+                            objectGetter,
+                            MH.insertArguments(
+                                    converters.get(ti),
+                                    1,
+                                    programPoint));
+                }
+
+                //asking for narrower primitive than we have stored, that is an
+                //UnwarrantedOptimismException
+                return MH.asType(
+                        MH.filterArguments(
+                            objectGetter,
+                            0,
+                            MH.insertArguments(
+                                    GET_DIFFERENT,
+                                    1,
+                                    forType,
+                                    primitiveGetter,
+                                    objectGetter,
+                                    programPoint)),
+                        objectGetter.type().changeReturnType(type));
+            }
+        }
+
+        assert !isOptimistic;
+            //freely coerce the result to whatever you asked for, this is e.g. Object->int for a & b
+        final MethodHandle tgetter = getterForType(forType, primitiveGetter, objectGetter);
+        if (fti == TYPE_OBJECT_INDEX) {
+            if (fti != ti) {
+                return MH.filterReturnValue(tgetter, CONVERT_OBJECT.get(ti));
+            }
+            return tgetter;
+        }
+
+        assert !OBJECT_FIELDS_ONLY;
+        //final MethodType pmt = primitiveGetter.type();
+        assert primitiveGetter != null;
+        final MethodType tgetterType = tgetter.type();
+        switch (fti) {
+        case TYPE_INT_INDEX: {
+            return MH.asType(tgetter, tgetterType.changeReturnType(type));
+        }
+        case TYPE_LONG_INDEX:
+            switch (ti) {
+            case TYPE_INT_INDEX:
+                //get int while an int, truncating cast of long value
+                return MH.filterReturnValue(tgetter, JSType.TO_INT32_L.methodHandle);
+            case TYPE_LONG_INDEX:
+                return primitiveGetter;
+            default:
+                return MH.asType(tgetter, tgetterType.changeReturnType(type));
+            }
+        case TYPE_DOUBLE_INDEX:
+            switch (ti) {
+            case TYPE_INT_INDEX:
+                return MH.filterReturnValue(tgetter, JSType.TO_INT32_D.methodHandle);
+            case TYPE_LONG_INDEX:
+                return MH.explicitCastArguments(tgetter, tgetterType.changeReturnType(type));
+            case TYPE_DOUBLE_INDEX:
+                assert tgetterType.returnType() == double.class;
+                return tgetter;
+            default:
+                return MH.asType(tgetter, tgetterType.changeReturnType(Object.class));
+            }
+        default:
+            throw new UnsupportedOperationException(forType + "=>" + type);
+        }
+    }
 
     /**
      * Given a primitiveGetter (optional for non dual fields) and an objectSetter that retrieve
@@ -526,7 +678,7 @@
      * and we want an Object getter, in the dual fields world we'd pick the primitiveGetter,
      * which reads a long, use longBitsToDouble on the result to unpack it, and then change the
      * return type to Object, boxing it. In the objects only world there are only object fields,
-     * primtives are boxed when asked for them and we don't need to bother with primitive encoding
+     * primitives are boxed when asked for them and we don't need to bother with primitive encoding
      * (or even undefined, which if forType==null) representation, so we just return whatever is
      * in the object field. The object field is always initiated to Undefined, so here, where we have
      * the representation for Undefined in all our bits, this is not a problem.
@@ -543,110 +695,18 @@
      * @param type            type to retrieve it as
      * @param primitiveGetter getter to read the primitive version of this field (null if Objects Only)
      * @param objectGetter    getter to read the object version of this field
+     * @param programPoint    program point for getter, if program point is INVALID_PROGRAM_POINT, then this is not an optimistic getter
      *
      * @return getter for the given representation that returns the given type
      */
-    public static MethodHandle createGetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter) {
-        final int fti = forType == null ? -1 : getAccessorTypeIndex(forType);
-        final int ti  = getAccessorTypeIndex(type);
-
-        if (fti == TYPE_OBJECT_INDEX || OBJECT_FIELDS_ONLY) {
-            if (ti == TYPE_OBJECT_INDEX) {
-                return objectGetter;
-            }
-
-            return MH.filterReturnValue(objectGetter, CONVERT_OBJECT[ti]);
-        }
-
-        assert !OBJECT_FIELDS_ONLY;
-        if (forType == null) {
-            return GET_UNDEFINED[ti];
-        }
-
-        final MethodType pmt = primitiveGetter.type();
-
-        switch (fti) {
-        case TYPE_INT_INDEX:
-        case TYPE_LONG_INDEX:
-            switch (ti) {
-            case TYPE_INT_INDEX:
-                //get int while an int, truncating cast of long value
-                return MH.explicitCastArguments(primitiveGetter, pmt.changeReturnType(int.class));
-            case TYPE_LONG_INDEX:
-                return primitiveGetter;
-            default:
-                return MH.asType(primitiveGetter, pmt.changeReturnType(type));
-            }
-        case TYPE_DOUBLE_INDEX:
-            final MethodHandle getPrimitiveAsDouble = MH.filterReturnValue(primitiveGetter, UNPACK_DOUBLE);
-            switch (ti) {
-            case TYPE_INT_INDEX:
-            case TYPE_LONG_INDEX:
-                return MH.explicitCastArguments(getPrimitiveAsDouble, pmt.changeReturnType(type));
-            case TYPE_DOUBLE_INDEX:
-                return getPrimitiveAsDouble;
-            default:
-                return MH.asType(getPrimitiveAsDouble, pmt.changeReturnType(Object.class));
-            }
-        default:
-            assert false;
-            return null;
-        }
-    }
-
-    private static final MethodHandle IS_TYPE_GUARD = findOwnMH("isType", boolean.class, Class.class, Object.class);
-
-    @SuppressWarnings("unused")
-    private static boolean isType(final Class<?> boxedForType, final Object x) {
-        return x.getClass() == boxedForType;
-    }
-
-    private static Class<? extends Number> getBoxedType(final Class<?> forType) {
-        if (forType == int.class) {
-            return Integer.class;
-        }
-
-        if (forType == long.class) {
-            return Long.class;
-        }
-
-        if (forType == double.class) {
-            return Double.class;
-        }
-
-        assert false;
-        return null;
-    }
-
-    /**
-     * If we are setting boxed types (because the compiler couldn't determine which they were) to
-     * a primitive field, we can reuse the primitive field getter, as long as we are setting an element
-     * of the same boxed type as the primitive type representation
-     *
-     * @param forType           the current type
-     * @param primitiveSetter   primitive setter for the current type with an element of the current type
-     * @param objectSetter      the object setter
-     *
-     * @return method handle that checks if the element to be set is of the currenttype, even though it's boxed
-     *  and instead of using the generic object setter, that would blow up the type and invalidate the map,
-     *  unbox it and call the primitive setter instead
-     */
-    public static MethodHandle createGuardBoxedPrimitiveSetter(final Class<?> forType, final MethodHandle primitiveSetter, final MethodHandle objectSetter) {
-        final Class<? extends Number> boxedForType = getBoxedType(forType);
-        //object setter that checks for primitive if current type is primitive
-
-        return MH.guardWithTest(
-            MH.insertArguments(
-                MH.dropArguments(
-                    IS_TYPE_GUARD,
-                    1,
-                    Object.class),
-                0,
-                boxedForType),
-                MH.asType(
-                    primitiveSetter,
-                    objectSetter.type()),
-                objectSetter);
+    public static MethodHandle createGetter(final Class<?> forType, final Class<?> type, final MethodHandle primitiveGetter, final MethodHandle objectGetter, final int programPoint) {
+        return createGetterInner(
+                forType,
+                type,
+                primitiveGetter,
+                objectGetter,
+                isValid(programPoint) ? CONVERT_OBJECT_OPTIMISTIC : CONVERT_OBJECT,
+                programPoint);
     }
 
     /**
@@ -699,11 +759,61 @@
             }
             return MH.asType(MH.filterArguments(primitiveSetter, 1, PACK_DOUBLE), pmt.changeParameterType(1, type));
         default:
-            assert false;
-            return null;
+            throw new UnsupportedOperationException(forType + "=>" + type);
         }
     }
 
+    @SuppressWarnings("unused")
+    private static boolean isType(final Class<?> boxedForType, final Object x) {
+        return x != null && x.getClass() == boxedForType;
+    }
+
+    private static Class<? extends Number> getBoxedType(final Class<?> forType) {
+        if (forType == int.class) {
+            return Integer.class;
+        }
+
+        if (forType == long.class) {
+            return Long.class;
+        }
+
+        if (forType == double.class) {
+            return Double.class;
+        }
+
+        assert false;
+        return null;
+    }
+
+    /**
+     * If we are setting boxed types (because the compiler couldn't determine which they were) to
+     * a primitive field, we can reuse the primitive field getter, as long as we are setting an element
+     * of the same boxed type as the primitive type representation
+     *
+     * @param forType           the current type
+     * @param primitiveSetter   primitive setter for the current type with an element of the current type
+     * @param objectSetter      the object setter
+     *
+     * @return method handle that checks if the element to be set is of the currenttype, even though it's boxed
+     *  and instead of using the generic object setter, that would blow up the type and invalidate the map,
+     *  unbox it and call the primitive setter instead
+     */
+    public static MethodHandle createGuardBoxedPrimitiveSetter(final Class<?> forType, final MethodHandle primitiveSetter, final MethodHandle objectSetter) {
+        final Class<? extends Number> boxedForType = getBoxedType(forType);
+        //object setter that checks for primitive if current type is primitive
+        return MH.guardWithTest(
+            MH.insertArguments(
+                MH.dropArguments(
+                    IS_TYPE_GUARD,
+                    1,
+                    Object.class),
+                0,
+                boxedForType),
+                MH.asType(
+                    primitiveSetter,
+                    objectSetter.type()),
+                objectSetter);
+    }
     /**
      * Add padding to field count to avoid creating too many classes and have some spare fields
      * @param count the field count
@@ -713,80 +823,9 @@
         return count / FIELD_PADDING * FIELD_PADDING + FIELD_PADDING;
     }
 
-    //
-    // Provide generic getters and setters for undefined types. If a type is undefined, all
-    // and marshals the set to the correct setter depending on the type of the value being set.
-    // Note that there are no actual undefined versions of int, long and double in JavaScript,
-    // but executing toInt32, toLong and toNumber always returns a working result, 0, 0L or NaN
-    //
-
-    /** The value of Undefined cast to an int32 */
-    public static final int    UNDEFINED_INT    = 0;
-    /** The value of Undefined cast to a long */
-    public static final long   UNDEFINED_LONG   = 0L;
-    /** The value of Undefined cast to a double */
-    public static final double UNDEFINED_DOUBLE = Double.NaN;
-
-    /**
-     * Compute type name for correct undefined getter
-     * @param type the type
-     * @return name of getter
-     */
-    private static String typeName(final Type type) {
-        String name = type.getTypeClass().getName();
-        final int dot = name.lastIndexOf('.');
-        if (dot != -1) {
-            name = name.substring(dot + 1);
-        }
-        return Character.toUpperCase(name.charAt(0)) + name.substring(1);
-    }
-
-    /**
-     * Handles for undefined getters of the different types
-     */
-    private static final MethodHandle[] GET_UNDEFINED = new MethodHandle[ObjectClassGenerator.getNumberOfAccessorTypes()];
-
-    /**
-     * Used to wrap getters for undefined values, where this matters. Currently only in dual fields.
-     * If an object starts out as undefined it needs special getters until it has been assigned
-     * something the first time
-     *
-     * @param returnType type to cast the undefined to
-     *
-     * @return undefined as returnType
-     */
-    public static MethodHandle getUndefined(final Class<?> returnType) {
-        return GET_UNDEFINED[ObjectClassGenerator.getAccessorTypeIndex(returnType)];
-    }
-
-    static {
-        int pos = 0;
-        for (final Type type : ACCESSOR_TYPES) {
-            GET_UNDEFINED[pos++] = findOwnMH("getUndefined" + typeName(type), type.getTypeClass(), Object.class);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private static int getUndefinedInt(final Object obj) {
-        return UNDEFINED_INT;
-    }
-
-    @SuppressWarnings("unused")
-    private static long getUndefinedLong(final Object obj) {
-        return UNDEFINED_LONG;
-    }
-
-    @SuppressWarnings("unused")
-    private static double getUndefinedDouble(final Object obj) {
-        return UNDEFINED_DOUBLE;
-    }
-
-    @SuppressWarnings("unused")
-    private static Object getUndefinedObject(final Object obj) {
-        return ScriptRuntime.UNDEFINED;
-    }
-
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), ObjectClassGenerator.class, name, MH.type(rtype, types));
     }
+
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java b/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java
index d129d59..1a09ca6 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ObjectCreator.java
@@ -28,22 +28,21 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
 
 import java.util.List;
-import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptObject;
 
 /**
  * Base class for object creation code generation.
+ * @param <T> value type
  */
-public abstract class ObjectCreator {
+public abstract class ObjectCreator<T> {
 
-    /** List of keys to initiate in this ObjectCreator */
-    protected final List<String>  keys;
-
-    /** List of symbols to initiate in this ObjectCreator */
-    protected final List<Symbol>  symbols;
+    /** List of keys & symbols to initiate in this ObjectCreator */
+    final List<MapTuple<T>> tuples;
 
     /** Code generator */
-    protected final CodeGenerator codegen;
+    final CodeGenerator codegen;
 
     /** Property map */
     protected PropertyMap   propertyMap;
@@ -55,15 +54,13 @@
      * Constructor
      *
      * @param codegen      the code generator
-     * @param keys         the keys
-     * @param symbols      the symbols corresponding to keys, same index
+     * @param tuples       key,symbol,value (optional) tuples
      * @param isScope      is this object scope
      * @param hasArguments does the created object have an "arguments" property
      */
-    protected ObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final boolean isScope, final boolean hasArguments) {
+    ObjectCreator(final CodeGenerator codegen, final List<MapTuple<T>> tuples, final boolean isScope, final boolean hasArguments) {
         this.codegen       = codegen;
-        this.keys          = keys;
-        this.symbols       = symbols;
+        this.tuples        = tuples;
         this.isScope       = isScope;
         this.hasArguments  = hasArguments;
     }
@@ -85,8 +82,8 @@
      * @param clazz type of MapCreator
      * @return map creator instantiated by type
      */
-    protected MapCreator newMapCreator(final Class<?> clazz) {
-        return new MapCreator(clazz, keys, symbols);
+    protected MapCreator<?> newMapCreator(final Class<? extends ScriptObject> clazz) {
+        return new MapCreator<>(clazz, tuples);
     }
 
     /**
@@ -107,6 +104,10 @@
         return method;
     }
 
+    PropertyMap getMap() {
+        return propertyMap;
+    }
+
     /**
      * Is this a scope object
      * @return true if scope
@@ -122,4 +123,27 @@
     protected boolean hasArguments() {
         return hasArguments;
     }
+
+    /**
+     * Technique for loading an initial value. Defined by anonymous subclasses in code gen.
+     *
+     * @param value Value to load.
+     * @param type the type of the value to load
+     */
+    protected abstract void loadValue(T value, Type type);
+
+    MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple, final boolean pack) {
+        loadValue(tuple.value, tuple.type);
+        if (pack && tuple.isPrimitive()) {
+            method.pack();
+        } else {
+            method.convert(Type.OBJECT);
+        }
+        return method;
+    }
+
+    MethodEmitter loadTuple(final MethodEmitter method, final MapTuple<T> tuple) {
+        return loadTuple(method, tuple, true);
+    }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java b/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
new file mode 100644
index 0000000..ac402e9
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesCalculator.java
@@ -0,0 +1,284 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
+import java.util.ArrayDeque;
+import java.util.BitSet;
+import java.util.Deque;
+import jdk.nashorn.internal.IntDeque;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.ExpressionStatement;
+import jdk.nashorn.internal.ir.ForNode;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LoopNode;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Optimistic;
+import jdk.nashorn.internal.ir.PropertyNode;
+import jdk.nashorn.internal.ir.SplitNode;
+import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.TernaryNode;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.WhileNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
+import jdk.nashorn.internal.runtime.ScriptObject;
+
+/**
+ * Assigns optimistic types to expressions that can have them. This class mainly contains logic for which expressions
+ * must not ever be marked as optimistic, assigning narrowest non-invalidated types to program points from the
+ * compilation environment, as well as initializing optimistic types of global properties for scripts.
+ */
+final class OptimisticTypesCalculator extends NodeVisitor<LexicalContext> {
+
+    final Compiler compiler;
+
+    // Per-function bit set of program points that must never be optimistic.
+    final Deque<BitSet> neverOptimistic = new ArrayDeque<>();
+    // Per-function depth of split nodes
+    final IntDeque splitDepth = new IntDeque();
+
+    OptimisticTypesCalculator(final Compiler compiler) {
+        super(new LexicalContext());
+        this.compiler = compiler;
+    }
+
+    @Override
+    public boolean enterAccessNode(final AccessNode accessNode) {
+        tagNeverOptimistic(accessNode.getBase());
+        return true;
+    }
+
+    @Override
+    public boolean enterPropertyNode(final PropertyNode propertyNode) {
+        if(propertyNode.getKeyName().equals(ScriptObject.PROTO_PROPERTY_NAME)) {
+            tagNeverOptimistic(propertyNode.getValue());
+        }
+        return super.enterPropertyNode(propertyNode);
+    }
+
+    @Override
+    public boolean enterBinaryNode(final BinaryNode binaryNode) {
+        if(binaryNode.isAssignment()) {
+            final Expression lhs = binaryNode.lhs();
+            if(!binaryNode.isSelfModifying()) {
+                tagNeverOptimistic(lhs);
+            }
+            if(lhs instanceof IdentNode) {
+                final Symbol symbol = ((IdentNode)lhs).getSymbol();
+                // Assignment to internal symbols is never optimistic, except for self-assignment expressions
+                if(symbol.isInternal() && !binaryNode.rhs().isSelfModifying()) {
+                    tagNeverOptimistic(binaryNode.rhs());
+                }
+            }
+        } else if(binaryNode.isTokenType(TokenType.INSTANCEOF)) {
+            tagNeverOptimistic(binaryNode.lhs());
+            tagNeverOptimistic(binaryNode.rhs());
+        }
+        return true;
+    }
+
+    @Override
+    public boolean enterCallNode(final CallNode callNode) {
+        tagNeverOptimistic(callNode.getFunction());
+        return true;
+    }
+
+    @Override
+    public boolean enterCatchNode(final CatchNode catchNode) {
+        // Condition is never optimistic (always coerced to boolean).
+        tagNeverOptimistic(catchNode.getExceptionCondition());
+        return true;
+    }
+
+    @Override
+    public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) {
+        final Expression expr = expressionStatement.getExpression();
+        if(!expr.isSelfModifying()) {
+            tagNeverOptimistic(expr);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean enterForNode(final ForNode forNode) {
+        if(forNode.isForIn()) {
+            // for..in has the iterable in its "modify"
+            tagNeverOptimistic(forNode.getModify());
+        } else {
+            // Test is never optimistic (always coerced to boolean).
+            tagNeverOptimisticLoopTest(forNode);
+        }
+        return true;
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        if (!neverOptimistic.isEmpty() && compiler.isOnDemandCompilation()) {
+            // This is a nested function, and we're doing on-demand compilation. In these compilations, we never descend
+            // into nested functions.
+            return false;
+        }
+        neverOptimistic.push(new BitSet());
+        splitDepth.push(0);
+        return true;
+    }
+
+    @Override
+    public boolean enterIfNode(final IfNode ifNode) {
+        // Test is never optimistic (always coerced to boolean).
+        tagNeverOptimistic(ifNode.getTest());
+        return true;
+    }
+
+    @Override
+    public boolean enterIndexNode(final IndexNode indexNode) {
+        tagNeverOptimistic(indexNode.getBase());
+        return true;
+    }
+
+    @Override
+    public boolean enterTernaryNode(final TernaryNode ternaryNode) {
+        // Test is never optimistic (always coerced to boolean).
+        tagNeverOptimistic(ternaryNode.getTest());
+        return true;
+    }
+
+    @Override
+    public boolean enterUnaryNode(final UnaryNode unaryNode) {
+        if(unaryNode.isTokenType(TokenType.NOT) || unaryNode.isTokenType(TokenType.NEW)) {
+            // Operand of boolean negation is never optimistic (always coerced to boolean).
+            // Operand of "new" is never optimistic (always coerced to Object).
+            tagNeverOptimistic(unaryNode.getExpression());
+        }
+        return true;
+    }
+
+    @Override
+    public boolean enterSplitNode(final SplitNode splitNode) {
+        splitDepth.getAndIncrement();
+        return true;
+    }
+
+    @Override
+    public Node leaveSplitNode(final SplitNode splitNode) {
+        final int depth = splitDepth.decrementAndGet();
+        assert depth >= 0;
+        return splitNode;
+    }
+
+    @Override
+    public boolean enterVarNode(final VarNode varNode) {
+        tagNeverOptimistic(varNode.getName());
+        return true;
+    }
+
+    @Override
+    public boolean enterWhileNode(final WhileNode whileNode) {
+        // Test is never optimistic (always coerced to boolean).
+        tagNeverOptimisticLoopTest(whileNode);
+        return true;
+    }
+
+    @Override
+    protected Node leaveDefault(final Node node) {
+        if(node instanceof Optimistic) {
+            return leaveOptimistic((Optimistic)node);
+        }
+        return node;
+    }
+
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+        neverOptimistic.pop();
+        final int lastSplitDepth = splitDepth.pop();
+        assert lastSplitDepth == 0;
+        return functionNode.setState(lc, CompilationState.OPTIMISTIC_TYPES_ASSIGNED);
+    }
+
+    @Override
+    public Node leaveIdentNode(final IdentNode identNode) {
+        if(inSplitNode()) {
+            return identNode;
+        }
+        final Symbol symbol = identNode.getSymbol();
+        if(symbol == null) {
+            assert identNode.isPropertyName();
+            return identNode;
+        } else if(symbol.isBytecodeLocal()) {
+            // Identifiers accessing bytecode local variables will never be optimistic, as type calculation phase over
+            // them will always assign them statically provable types. Note that access to function parameters can still
+            // be optimistic if the parameter needs to be in scope as it's used by a nested function.
+            return identNode;
+        } else if(symbol.isParam() && lc.getCurrentFunction().isVarArg()) {
+            // Parameters in vararg methods are not optimistic; we always access them using Object getters.
+            return identNode.setType(identNode.getMostPessimisticType());
+        } else {
+            assert symbol.isScope();
+            return leaveOptimistic(identNode);
+        }
+    }
+
+    private Expression leaveOptimistic(final Optimistic opt) {
+        final int pp = opt.getProgramPoint();
+        if(isValid(pp) && !inSplitNode() && !neverOptimistic.peek().get(pp)) {
+            return (Expression)opt.setType(compiler.getOptimisticType(opt));
+        }
+        return (Expression)opt;
+    }
+
+    private void tagNeverOptimistic(final Expression expr) {
+        if(expr instanceof Optimistic) {
+            final int pp = ((Optimistic)expr).getProgramPoint();
+            if(isValid(pp)) {
+                neverOptimistic.peek().set(pp);
+            }
+        }
+    }
+
+    private void tagNeverOptimisticLoopTest(final LoopNode loopNode) {
+        final JoinPredecessorExpression test = loopNode.getTest();
+        if(test != null) {
+            tagNeverOptimistic(test.getExpression());
+        }
+    }
+
+    private boolean inSplitNode() {
+        return splitDepth.peek() > 0;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java b/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
new file mode 100644
index 0000000..a1a95bc
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/OptimisticTypesPersistence.java
@@ -0,0 +1,338 @@
+/*
+ * 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.  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.
+ */
+package jdk.nashorn.internal.codegen;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.Files;
+import java.security.AccessController;
+import java.security.MessageDigest;
+import java.security.PrivilegedAction;
+import java.text.SimpleDateFormat;
+import java.util.Base64;
+import java.util.Date;
+import java.util.Map;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.Source;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * Static utility that encapsulates persistence of decompilation information for functions. Normally, the type info
+ * persistence feature is enabled and operates in an operating-system specific per-user cache directory. You can
+ * override the directory by specifying it in the {@code nashorn.typeInfo.cacheDir} directory. Also, you can disable the
+ * type info persistence altogether by specifying the {@code nashorn.typeInfo.disabled} system property.
+ */
+public final class OptimisticTypesPersistence {
+    // The name of the default subdirectory within the system cache directory where we store type info.
+    private static final String DEFAULT_CACHE_SUBDIR_NAME = "com.oracle.java.NashornTypeInfo";
+    // The directory where we cache type info
+    private static final File cacheDir = createCacheDir();
+    // In-process locks to make sure we don't have a cross-thread race condition manipulating any file.
+    private static final Object[] locks = cacheDir == null ? null : createLockArray();
+
+    // Only report one read/write error every minute
+    private static final long ERROR_REPORT_THRESHOLD = 60000L;
+
+    private static volatile long lastReportedError;
+
+    /**
+     * Retrieves an opaque descriptor for the persistence location for a given function. It should be passed to
+     * {@link #load(Object)} and {@link #store(Object, Map)} methods.
+     * @param source the source where the function comes from
+     * @param functionId the unique ID number of the function within the source
+     * @param paramTypes the types of the function parameters (as persistence is per parameter type specialization).
+     * @return an opaque descriptor for the persistence location. Can be null if persistence is disabled.
+     */
+    public static Object getLocationDescriptor(final Source source, final int functionId, final Type[] paramTypes) {
+        if(cacheDir == null) {
+            return null;
+        }
+        final StringBuilder b = new StringBuilder(48);
+        // Base64-encode the digest of the source, and append the function id.
+        b.append(source.getDigest()).append('-').append(functionId);
+        // Finally, if this is a parameter-type specialized version of the function, add the parameter types to the file name.
+        if(paramTypes != null && paramTypes.length > 0) {
+            b.append('-');
+            for(final Type t: paramTypes) {
+                b.append(Type.getShortSignatureDescriptor(t));
+            }
+        }
+        return new LocationDescriptor(new File(cacheDir, b.toString()));
+    }
+
+    private static final class LocationDescriptor {
+        private final File file;
+
+        LocationDescriptor(final File file) {
+            this.file = file;
+        }
+    }
+
+
+    /**
+     * Stores the map of optimistic types for a given function.
+     * @param locationDescriptor the opaque persistence location descriptor, retrieved by calling
+     * {@link #getLocationDescriptor(Source, int, Type[])}.
+     * @param optimisticTypes the map of optimistic types.
+     */
+    @SuppressWarnings("resource")
+    public static void store(final Object locationDescriptor, final Map<Integer, Type> optimisticTypes) {
+        if(locationDescriptor == null || optimisticTypes.isEmpty()) {
+            return;
+        }
+        final File file = ((LocationDescriptor)locationDescriptor).file;
+
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                synchronized(getFileLock(file)) {
+                    try (final FileOutputStream out = new FileOutputStream(file)) {
+                        out.getChannel().lock(); // lock exclusive
+                        final DataOutputStream dout = new DataOutputStream(new BufferedOutputStream(out));
+                        Type.writeTypeMap(optimisticTypes, dout);
+                        dout.flush();
+                    } catch(final Exception e) {
+                        reportError("write", file, e);
+                    }
+                }
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Loads the map of optimistic types for a given function.
+     * @param locationDescriptor the opaque persistence location descriptor, retrieved by calling
+     * {@link #getLocationDescriptor(Source, int, Type[])}.
+     * @return the map of optimistic types, or null if persisted type information could not be retrieved.
+     */
+    @SuppressWarnings("resource")
+    public static Map<Integer, Type> load(final Object locationDescriptor) {
+        if (locationDescriptor == null) {
+            return null;
+        }
+        final File file = ((LocationDescriptor)locationDescriptor).file;
+        return AccessController.doPrivileged(new PrivilegedAction<Map<Integer, Type>>() {
+            @Override
+            public Map<Integer, Type> run() {
+                try {
+                    if(!file.isFile()) {
+                        return null;
+                    }
+                    synchronized(getFileLock(file)) {
+                        try (final FileInputStream in = new FileInputStream(file)) {
+                            in.getChannel().lock(0, Long.MAX_VALUE, true); // lock shared
+                            final DataInputStream din = new DataInputStream(new BufferedInputStream(in));
+                            return Type.readTypeMap(din);
+                        }
+                    }
+                } catch (final Exception e) {
+                    reportError("read", file, e);
+                    return null;
+                }
+            }
+        });
+    }
+
+    private static void reportError(final String msg, final File file, final Exception e) {
+        final long now = System.currentTimeMillis();
+        if(now - lastReportedError > ERROR_REPORT_THRESHOLD) {
+            getLogger().warning(String.format("Failed to %s %s", msg, file), e);
+            lastReportedError = now;
+        }
+    }
+
+    private static File createCacheDir() {
+        if(Options.getBooleanProperty("nashorn.typeInfo.disabled")) {
+            return null;
+        }
+        try {
+            return createCacheDirPrivileged();
+        } catch(final Exception e) {
+            getLogger().warning("Failed to create cache dir", e);
+            return null;
+        }
+    }
+
+    private static File createCacheDirPrivileged() {
+        return AccessController.doPrivileged(new PrivilegedAction<File>() {
+            @Override
+            public File run() {
+                final String explicitDir = System.getProperty("nashorn.typeInfo.cacheDir");
+                final File dir;
+                if(explicitDir != null) {
+                    dir = new File(explicitDir);
+                } else {
+                    // When no directory is explicitly specified, get an operating system specific cache directory,
+                    // and create "com.oracle.java.NashornTypeInfo" in it.
+                    final File systemCacheDir = getSystemCacheDir();
+                    dir = new File(systemCacheDir, DEFAULT_CACHE_SUBDIR_NAME);
+                    if (isSymbolicLink(dir)) {
+                        return null;
+                    }
+                }
+                final String versionDirName;
+                try {
+                    versionDirName = getVersionDirName();
+                } catch(final Exception e) {
+                    getLogger().warning("Failed to calculate version dir name", e);
+                    return null;
+                }
+                final File versionDir = new File(dir, versionDirName);
+                if (isSymbolicLink(versionDir)) {
+                    return null;
+                }
+                versionDir.mkdirs();
+                if(versionDir.isDirectory()) {
+                    getLogger().info("Optimistic type persistence directory is " + versionDir);
+                    return versionDir;
+                }
+                getLogger().warning("Could not create optimistic type persistence directory " + versionDir);
+                return null;
+            }
+        });
+    }
+
+    /**
+     * Returns an operating system specific root directory for cache files.
+     * @return an operating system specific root directory for cache files.
+     */
+    private static File getSystemCacheDir() {
+        final String os = System.getProperty("os.name", "generic");
+        if("Mac OS X".equals(os)) {
+            // Mac OS X stores caches in ~/Library/Caches
+            return new File(new File(System.getProperty("user.home"), "Library"), "Caches");
+        } else if(os.startsWith("Windows")) {
+            // On Windows, temp directory is the best approximation of a cache directory, as its contents persist across
+            // reboots and various cleanup utilities know about it. java.io.tmpdir normally points to a user-specific
+            // temp directory, %HOME%\LocalSettings\Temp.
+            return new File(System.getProperty("java.io.tmpdir"));
+        } else {
+            // In all other cases we're presumably dealing with a UNIX flavor (Linux, Solaris, etc.); "~/.cache"
+            return new File(System.getProperty("user.home"), ".cache");
+        }
+    }
+
+    /**
+     * In order to ensure that changes in Nashorn code don't cause corruption in the data, we'll create a
+     * per-code-version directory. Normally, this will create the SHA-1 digest of the nashorn.jar. In case the classpath
+     * for nashorn is local directory (e.g. during development), this will create the string "dev-" followed by the
+     * timestamp of the most recent .class file.
+     * @return
+     */
+    private static String getVersionDirName() throws Exception {
+        final URL url = OptimisticTypesPersistence.class.getResource("");
+        final String protocol = url.getProtocol();
+        if (protocol.equals("jar")) {
+            // Normal deployment: nashorn.jar
+            final String jarUrlFile = url.getFile();
+            final String filePath = jarUrlFile.substring(0, jarUrlFile.indexOf('!'));
+            final URL file = new URL(filePath);
+            try (final InputStream in = file.openStream()) {
+                final byte[] buf = new byte[128*1024];
+                final MessageDigest digest = MessageDigest.getInstance("SHA-1");
+                for(;;) {
+                    final int l = in.read(buf);
+                    if(l == -1) {
+                        return Base64.getUrlEncoder().withoutPadding().encodeToString(digest.digest());
+                    }
+                    digest.update(buf, 0, l);
+                }
+            }
+        } else if(protocol.equals("file")) {
+            // Development
+            final String fileStr = url.getFile();
+            final String className = OptimisticTypesPersistence.class.getName();
+            final int packageNameLen = className.lastIndexOf('.');
+            final String dirStr = fileStr.substring(0, fileStr.length() - packageNameLen - 1);
+            final File dir = new File(dirStr);
+            return "dev-" + new SimpleDateFormat("yyyyMMdd-HHmmss").format(new Date(getLastModifiedClassFile(dir, 0L)));
+        } else {
+            throw new AssertionError();
+        }
+    }
+
+    private static long getLastModifiedClassFile(final File dir, final long max) {
+        long currentMax = max;
+        for(final File f: dir.listFiles()) {
+            if(f.getName().endsWith(".class")) {
+                final long lastModified = f.lastModified();
+                if (lastModified > currentMax) {
+                    currentMax = lastModified;
+                }
+            } else if (f.isDirectory()) {
+                final long lastModified = getLastModifiedClassFile(f, currentMax);
+                if (lastModified > currentMax) {
+                    currentMax = lastModified;
+                }
+            }
+        }
+        return currentMax;
+    }
+
+    /**
+     * Returns true if the specified file is a symbolic link, and also logs a warning if it is.
+     * @param file the file
+     * @return true if file is a symbolic link, false otherwise.
+     */
+    private static boolean isSymbolicLink(final File file) {
+        if (Files.isSymbolicLink(file.toPath())) {
+            getLogger().warning("Directory " + file + " is a symlink");
+            return true;
+        }
+        return false;
+    }
+
+    private static Object[] createLockArray() {
+        final Object[] lockArray = new Object[Runtime.getRuntime().availableProcessors() * 2];
+        for (int i = 0; i < lockArray.length; ++i) {
+            lockArray[i] = new Object();
+        }
+        return lockArray;
+    }
+
+    private static Object getFileLock(final File file) {
+        return locks[(file.hashCode() & Integer.MAX_VALUE) % locks.length];
+    }
+
+    private static DebugLogger getLogger() {
+        try {
+            return Context.getContext().getLogger(RecompilableScriptFunctionData.class);
+        } catch (final Exception e) {
+            e.printStackTrace();
+            return DebugLogger.DISABLED_LOGGER;
+        }
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/ProgramPoints.java b/nashorn/src/jdk/nashorn/internal/codegen/ProgramPoints.java
new file mode 100644
index 0000000..c04546b
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/ProgramPoints.java
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.FIRST_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.MAX_PROGRAM_POINT_VALUE;
+
+import java.util.HashSet;
+import java.util.Set;
+import jdk.nashorn.internal.IntDeque;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.BinaryNode;
+import jdk.nashorn.internal.ir.CallNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Optimistic;
+import jdk.nashorn.internal.ir.UnaryNode;
+import jdk.nashorn.internal.ir.VarNode;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * Find program points in the code that are needed for optimistic assumptions
+ */
+class ProgramPoints extends NodeVisitor<LexicalContext> {
+
+    private final IntDeque nextProgramPoint = new IntDeque();
+    private final Set<Node> noProgramPoint = new HashSet<>();
+
+    ProgramPoints() {
+        super(new LexicalContext());
+    }
+
+    private int next() {
+        final int next = nextProgramPoint.getAndIncrement();
+        if(next > MAX_PROGRAM_POINT_VALUE) {
+            throw new AssertionError("Function has more than " + MAX_PROGRAM_POINT_VALUE + " program points");
+        }
+        return next;
+    }
+
+    @Override
+    public boolean enterFunctionNode(final FunctionNode functionNode) {
+        nextProgramPoint.push(FIRST_PROGRAM_POINT);
+        return true;
+    }
+
+    @Override
+    public Node leaveFunctionNode(final FunctionNode functionNode) {
+        nextProgramPoint.pop();
+        return functionNode;
+    }
+
+    private Expression setProgramPoint(final Optimistic optimistic) {
+        if (noProgramPoint.contains(optimistic)) {
+            return (Expression)optimistic;
+        }
+        return (Expression)(optimistic.canBeOptimistic() ? optimistic.setProgramPoint(next()) : optimistic);
+    }
+
+    @Override
+    public boolean enterVarNode(final VarNode varNode) {
+        noProgramPoint.add(varNode.getAssignmentDest());
+        return true;
+    }
+
+    @Override
+    public boolean enterIdentNode(final IdentNode identNode) {
+        if (identNode.isInternal()) {
+            noProgramPoint.add(identNode);
+        }
+        return true;
+    }
+
+    @Override
+    public Node leaveIdentNode(final IdentNode identNode) {
+        if(identNode.isPropertyName()) {
+            return identNode;
+        }
+        return setProgramPoint(identNode);
+    }
+
+    @Override
+    public Node leaveCallNode(final CallNode callNode) {
+        return setProgramPoint(callNode);
+    }
+
+    @Override
+    public Node leaveAccessNode(final AccessNode accessNode) {
+        return setProgramPoint(accessNode);
+    }
+
+    @Override
+    public Node leaveIndexNode(final IndexNode indexNode) {
+        return setProgramPoint(indexNode);
+    }
+
+    @Override
+    public Node leaveBinaryNode(final BinaryNode binaryNode) {
+        return setProgramPoint(binaryNode);
+    }
+
+    @Override
+    public Node leaveUnaryNode(final UnaryNode unaryNode) {
+        return setProgramPoint(unaryNode);
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java b/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
deleted file mode 100644
index 4056ec0..0000000
--- a/nashorn/src/jdk/nashorn/internal/codegen/RangeAnalyzer.java
+++ /dev/null
@@ -1,475 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.codegen;
-
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import jdk.nashorn.internal.codegen.types.Range;
-import jdk.nashorn.internal.codegen.types.Type;
-import jdk.nashorn.internal.ir.Assignment;
-import jdk.nashorn.internal.ir.BinaryNode;
-import jdk.nashorn.internal.ir.Expression;
-import jdk.nashorn.internal.ir.ForNode;
-import jdk.nashorn.internal.ir.IdentNode;
-import jdk.nashorn.internal.ir.LexicalContext;
-import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.LiteralNode.ArrayLiteralNode;
-import jdk.nashorn.internal.ir.LoopNode;
-import jdk.nashorn.internal.ir.Node;
-import jdk.nashorn.internal.ir.RuntimeNode;
-import jdk.nashorn.internal.ir.Symbol;
-import jdk.nashorn.internal.ir.UnaryNode;
-import jdk.nashorn.internal.ir.VarNode;
-import jdk.nashorn.internal.ir.visitor.NodeOperatorVisitor;
-import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.runtime.DebugLogger;
-
-/**
- * Range analysis and narrowing of type where it can be proven
- * that there is no spillover, e.g.
- *
- *  function func(c) {
- *    var v = c & 0xfff;
- *    var w = c & 0xeee;
- *    var x = v * w;
- *    return x;
- *  }
- *
- *  Proves that the multiplication never exceeds 24 bits and can thus be an int
- */
-final class RangeAnalyzer extends NodeOperatorVisitor<LexicalContext> {
-    static final DebugLogger LOG = new DebugLogger("ranges");
-
-    private static final Range.Functionality RANGE = new Range.Functionality(LOG);
-
-    private final Map<LoopNode, Symbol> loopCounters = new HashMap<>();
-
-    RangeAnalyzer() {
-        super(new LexicalContext());
-    }
-
-    @Override
-    public boolean enterForNode(final ForNode forNode) {
-        //conservatively attempt to identify the loop counter. Null means that it wasn't
-        //properly identified and that no optimizations can be made with it - its range is
-        //simply unknown in that case, if it is assigned in the loop
-        final Symbol counter = findLoopCounter(forNode);
-        LOG.fine("Entering forNode " + forNode + " counter = " + counter);
-        if (counter != null && !assignedInLoop(forNode,  counter)) {
-            loopCounters.put(forNode, counter);
-        }
-        return true;
-    }
-
-    //destination visited
-    private Symbol setRange(final Expression dest, final Range range) {
-        if (range.isUnknown()) {
-            return null;
-        }
-
-        final Symbol symbol = dest.getSymbol();
-        assert symbol != null : dest + " " + dest.getClass() + " has no symbol";
-        assert symbol.getRange() != null : symbol + " has no range";
-        final Range symRange = RANGE.join(symbol.getRange(), range);
-
-        //anything assigned in the loop, not being the safe loop counter(s) invalidates its entire range
-        if (lc.inLoop() && !isLoopCounter(lc.getCurrentLoop(), symbol)) {
-            symbol.setRange(Range.createGenericRange());
-            return symbol;
-        }
-
-        if (!symRange.equals(symbol.getRange())) {
-            LOG.fine("Modify range for " + dest + " " + symbol + " from " + symbol.getRange() + " to " + symRange + " (in node = " + dest + ")" );
-            symbol.setRange(symRange);
-        }
-
-        return null;
-    }
-
-    @Override
-    public Node leaveADD(final BinaryNode node) {
-        setRange(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveSUB(final BinaryNode node) {
-        setRange(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveMUL(final BinaryNode node) {
-        setRange(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveDIV(final BinaryNode node) {
-        setRange(node, RANGE.div(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveMOD(final BinaryNode node) {
-        setRange(node, RANGE.mod(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveBIT_AND(final BinaryNode node) {
-        setRange(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveBIT_OR(final BinaryNode node) {
-        setRange(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveBIT_XOR(final BinaryNode node) {
-        setRange(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveSAR(final BinaryNode node) {
-        setRange(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveSHL(final BinaryNode node) {
-        setRange(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveSHR(final BinaryNode node) {
-        setRange(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    private Node leaveCmp(final BinaryNode node) {
-        setRange(node, Range.createTypeRange(Type.BOOLEAN));
-        return node;
-    }
-
-    @Override
-    public Node leaveEQ(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveEQ_STRICT(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveNE(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveNE_STRICT(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveLT(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveLE(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveGT(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveGE(final BinaryNode node) {
-        return leaveCmp(node);
-    }
-
-    @Override
-    public Node leaveASSIGN(final BinaryNode node) {
-        Range range = node.rhs().getSymbol().getRange();
-        if (range.isUnknown()) {
-            range = Range.createGenericRange();
-        }
-
-        setRange(node.lhs(), range);
-        setRange(node, range);
-
-        return node;
-    }
-
-    private Node leaveSelfModifyingAssign(final BinaryNode node, final Range range) {
-        setRange(node.lhs(), range);
-        setRange(node, range);
-        return node;
-    }
-
-    private Node leaveSelfModifyingAssign(final UnaryNode node, final Range range) {
-        setRange(node.rhs(), range);
-        setRange(node, range);
-        return node;
-    }
-
-    @Override
-    public Node leaveASSIGN_ADD(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.add(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_SUB(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.sub(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_MUL(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.mul(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_DIV(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
-    }
-
-    @Override
-    public Node leaveASSIGN_MOD(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, Range.createTypeRange(Type.NUMBER));
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_AND(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.and(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_OR(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.or(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_BIT_XOR(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.xor(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_SAR(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.sar(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_SHR(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.shr(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveASSIGN_SHL(final BinaryNode node) {
-        return leaveSelfModifyingAssign(node, RANGE.shl(node.lhs().getSymbol().getRange(), node.rhs().getSymbol().getRange()));
-    }
-
-    @Override
-    public Node leaveDECINC(final UnaryNode node) {
-        switch (node.tokenType()) {
-        case DECPREFIX:
-        case DECPOSTFIX:
-            return leaveSelfModifyingAssign(node, RANGE.sub(node.rhs().getSymbol().getRange(), Range.createRange(1)));
-        case INCPREFIX:
-        case INCPOSTFIX:
-            return leaveSelfModifyingAssign(node, RANGE.add(node.rhs().getSymbol().getRange(), Range.createRange(1)));
-        default:
-            assert false;
-            return node;
-        }
-    }
-
-    @Override
-    public Node leaveADD(final UnaryNode node) {
-        Range range = node.rhs().getSymbol().getRange();
-        if (!range.getType().isNumeric()) {
-           range = Range.createTypeRange(Type.NUMBER);
-        }
-        setRange(node, range);
-        return node;
-    }
-
-    @Override
-    public Node leaveBIT_NOT(final UnaryNode node) {
-        setRange(node, Range.createTypeRange(Type.INT));
-        return node;
-    }
-
-    @Override
-    public Node leaveNOT(final UnaryNode node) {
-        setRange(node, Range.createTypeRange(Type.BOOLEAN));
-        return node;
-    }
-
-    @Override
-    public Node leaveSUB(final UnaryNode node) {
-        setRange(node, RANGE.neg(node.rhs().getSymbol().getRange()));
-        return node;
-    }
-
-    @Override
-    public Node leaveVarNode(final VarNode node) {
-        if (node.isAssignment()) {
-            Range range = node.getInit().getSymbol().getRange();
-            range = range.isUnknown() ? Range.createGenericRange() : range;
-
-            setRange(node.getName(), range);
-        }
-
-        return node;
-    }
-
-    @SuppressWarnings("rawtypes")
-    @Override
-    public boolean enterLiteralNode(final LiteralNode node) {
-        // ignore array literals
-        return !(node instanceof ArrayLiteralNode);
-    }
-
-    @Override
-    public Node leaveLiteralNode(@SuppressWarnings("rawtypes") final LiteralNode node) {
-        if (node.getType().isInteger()) {
-            setRange(node, Range.createRange(node.getInt32()));
-        } else if (node.getType().isNumber()) {
-            setRange(node, Range.createRange(node.getNumber()));
-        } else if (node.getType().isLong()) {
-            setRange(node, Range.createRange(node.getLong()));
-        } else if (node.getType().isBoolean()) {
-            setRange(node, Range.createTypeRange(Type.BOOLEAN));
-        } else {
-            setRange(node, Range.createGenericRange());
-        }
-        return node;
-    }
-
-    @Override
-    public boolean enterRuntimeNode(final RuntimeNode node) {
-        // a runtime node that cannot be specialized is no point entering
-        return node.getRequest().canSpecialize();
-    }
-
-    /**
-     * Check whether a symbol is unsafely assigned in a loop - i.e. repeteadly assigned and
-     * not being identified as the loop counter. That means we don't really know anything
-     * about its range.
-     * @param loopNode loop node
-     * @param symbol   symbol
-     * @return true if assigned in loop
-     */
-    // TODO - this currently checks for nodes only - needs to be augmented for while nodes
-    // assignment analysis is also very conservative
-    private static boolean assignedInLoop(final LoopNode loopNode, final Symbol symbol) {
-        final HashSet<Node> skip = new HashSet<>();
-        final HashSet<Node> assignmentsInLoop = new HashSet<>();
-
-        loopNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
-            private boolean assigns(final Node node, final Symbol s) {
-                return node.isAssignment() && ((Assignment<?>)node).getAssignmentDest().getSymbol() == s;
-            }
-
-            @Override
-            public boolean enterForNode(final ForNode forNode) {
-                if (forNode.getInit() != null) {
-                    skip.add(forNode.getInit());
-                }
-                if (forNode.getModify() != null) {
-                    skip.add(forNode.getModify());
-                }
-                return true;
-            }
-
-            @Override
-            public Node leaveDefault(final Node node) {
-                //if this is an assignment to symbol
-                if (!skip.contains(node) && assigns(node, symbol)) {
-                    assignmentsInLoop.add(node);
-                }
-                return node;
-            }
-        });
-
-        return !assignmentsInLoop.isEmpty();
-    }
-
-    /**
-     * Check for a loop counter. This is currently quite conservative, in that it only handles
-     * x <= counter and x < counter.
-     *
-     * @param node loop node to check
-     * @return
-     */
-    private static Symbol findLoopCounter(final LoopNode node) {
-        final Expression test = node.getTest();
-
-        if (test != null && test.isComparison()) {
-            final BinaryNode binaryNode = (BinaryNode)test;
-            final Expression lhs = binaryNode.lhs();
-            final Expression rhs = binaryNode.rhs();
-
-            //detect ident cmp int_literal
-            if (lhs instanceof IdentNode && rhs instanceof LiteralNode && ((LiteralNode<?>)rhs).getType().isInteger()) {
-                final Symbol    symbol = lhs.getSymbol();
-                final int       margin = ((LiteralNode<?>)rhs).getInt32();
-                final TokenType op     = test.tokenType();
-
-                switch (op) {
-                case LT:
-                case LE:
-                    symbol.setRange(RANGE.join(symbol.getRange(), Range.createRange(op == TokenType.LT ? margin - 1 : margin)));
-                    return symbol;
-                case GT:
-                case GE:
-                    //setRange(lhs, Range.createRange(op == TokenType.GT ? margin + 1 : margin));
-                    //return symbol;
-                default:
-                    break;
-                }
-            }
-        }
-
-        return null;
-    }
-
-    private boolean isLoopCounter(final LoopNode loopNode, final Symbol symbol) {
-        //this only works if loop nodes aren't replaced by other ones during this transform, but they are not
-        return loopCounters.get(loopNode) == symbol;
-    }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java b/nashorn/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
index c9f3836..b4d2f2d 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/RuntimeCallSite.java
@@ -42,7 +42,6 @@
 import jdk.nashorn.internal.ir.RuntimeNode;
 import jdk.nashorn.internal.ir.RuntimeNode.Request;
 import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
@@ -59,7 +58,7 @@
 public final class RuntimeCallSite extends MutableCallSite {
     static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "runtimeBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
 
-    private static final MethodHandle NEXT = findOwnMH("next",  MethodHandle.class, String.class);
+    private static final MethodHandle NEXT = findOwnMH_V("next",  MethodHandle.class, String.class);
 
     private final RuntimeNode.Request request;
 
@@ -89,7 +88,7 @@
         }
 
         /**
-         * The first type to try to use for this genrated runtime node
+         * The first type to try to use for this generated runtime node
          *
          * @return a type
          */
@@ -351,19 +350,19 @@
     /** Unbox cache */
     private static final Map<Class<?>, MethodHandle> UNBOX;
 
-    private static final MethodHandle CHECKCAST  = findOwnMH("checkcast", boolean.class, Class.class, Object.class);
-    private static final MethodHandle CHECKCAST2 = findOwnMH("checkcast", boolean.class, Class.class, Object.class, Object.class);
-    private static final MethodHandle ADDCHECK   = findOwnMH("ADDcheck",  boolean.class, int.class, int.class);
+    private static final MethodHandle CHECKCAST  = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class);
+    private static final MethodHandle CHECKCAST2 = findOwnMH_S("checkcast", boolean.class, Class.class, Object.class, Object.class);
+    private static final MethodHandle ADDCHECK   = findOwnMH_S("ADDcheck",  boolean.class, int.class, int.class);
 
     /**
      * Build maps of correct boxing operations
      */
     static {
         UNBOX = new HashMap<>();
-        UNBOX.put(Boolean.class, findOwnMH("unboxZ", int.class, Object.class));
-        UNBOX.put(Integer.class, findOwnMH("unboxI", int.class, Object.class));
-        UNBOX.put(Long.class,    findOwnMH("unboxJ", long.class, Object.class));
-        UNBOX.put(Number.class,  findOwnMH("unboxD", double.class, Object.class));
+        UNBOX.put(Boolean.class, findOwnMH_S("unboxZ", int.class, Object.class));
+        UNBOX.put(Integer.class, findOwnMH_S("unboxI", int.class, Object.class));
+        UNBOX.put(Long.class,    findOwnMH_S("unboxJ", long.class, Object.class));
+        UNBOX.put(Number.class,  findOwnMH_S("unboxD", double.class, Object.class));
 
         METHODS = new HashMap<>();
 
@@ -375,9 +374,9 @@
 
                 final boolean isCmp = Request.isComparison(req);
 
-                METHODS.put(req.name() + "int",    findOwnMH(req.name(), (isCmp ? boolean.class : int.class),  int.class, int.class));
-                METHODS.put(req.name() + "long",   findOwnMH(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class));
-                METHODS.put(req.name() + "double", findOwnMH(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class));
+                METHODS.put(req.name() + "int",    findOwnMH_S(req.name(), (isCmp ? boolean.class : int.class),  int.class, int.class));
+                METHODS.put(req.name() + "long",   findOwnMH_S(req.name(), (isCmp ? boolean.class : long.class), long.class, long.class));
+                METHODS.put(req.name() + "double", findOwnMH_S(req.name(), (isCmp ? boolean.class : double.class), double.class, double.class));
             }
         }
 
@@ -674,12 +673,11 @@
         return ((Number)obj).doubleValue();
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        try {
-            return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
-        } catch (final MethodHandleFactory.LookupException e) {
-            return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
-        }
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
     }
 
+    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findVirtual(MethodHandles.lookup(), RuntimeCallSite.class, name, MH.type(rtype, types));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
index da29ac0..56da4e0 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SharedScopeCall.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.codegen;
 
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_OPTIMISTIC;
+
 import java.util.Arrays;
 import java.util.EnumSet;
 import jdk.nashorn.internal.codegen.types.Type;
@@ -81,6 +83,7 @@
         this.valueType = valueType;
         this.returnType = returnType;
         this.paramTypes = paramTypes;
+        assert (flags & CALLSITE_OPTIMISTIC) == 0;
         this.flags = flags;
         // If paramTypes is not null this is a call, otherwise it's just a get.
         this.isCall = paramTypes != null;
@@ -150,7 +153,10 @@
         method._goto(parentLoopStart);
         method.label(parentLoopDone);
 
-        method.dynamicGet(valueType, symbol.getName(), flags, isCall);
+        assert !isCall || valueType.isObject(); // Callables are always objects
+        // If flags are optimistic, but we're doing a call, remove optimistic flags from the getter, as they obviously
+        // only apply to the call.
+        method.dynamicGet(valueType, symbol.getName(), isCall ? CodeGenerator.nonOptimisticFlags(flags) : flags, isCall);
 
         // If this is a get we're done, otherwise call the value as function.
         if (isCall) {
@@ -159,11 +165,10 @@
             method.loadUndefined(Type.OBJECT);
             int slot = 2;
             for (final Type type : paramTypes) {
-                method.load(type, slot++);
-                if (type == Type.NUMBER || type == Type.LONG) {
-                    slot++;
-                }
+                method.load(type, slot);
+                slot += type.getSlots();
             }
+            // Shared scope calls disabled in optimistic world. TODO is this right?
             method.dynamicCall(returnType, 2 + paramTypes.length, flags);
         }
 
@@ -179,17 +184,16 @@
                 final Type[] params = new Type[paramTypes.length + 2];
                 params[0] = Type.typeFor(ScriptObject.class);
                 params[1] = Type.INT;
-                int i = 2;
-                for (Type type : paramTypes)  {
-                    if (type.isObject()) {
-                        type = Type.OBJECT;
-                    }
-                    params[i++] = type;
-                }
+                System.arraycopy(paramTypes, 0, params, 2, paramTypes.length);
                 staticSignature = Type.getMethodDescriptor(returnType, params);
             }
         }
         return staticSignature;
     }
 
+    @Override
+    public String toString() {
+        return methodName + " " + staticSignature;
+    }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java b/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
index 1339d87..4fa51091 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SpillObjectCreator.java
@@ -27,7 +27,7 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.constructorNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
-import static jdk.nashorn.internal.codegen.types.Type.OBJECT;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
 
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -35,10 +35,11 @@
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.LiteralNode;
-import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
 import jdk.nashorn.internal.scripts.JO;
@@ -46,21 +47,16 @@
 /**
  * An object creator that uses spill properties.
  */
-public class SpillObjectCreator extends ObjectCreator {
-
-    private final List<Expression> values;
+public final class SpillObjectCreator extends ObjectCreator<Expression> {
 
     /**
      * Constructor
      *
      * @param codegen  code generator
-     * @param keys     keys for fields in object
-     * @param symbols  symbols for fields in object
-     * @param values   list of values corresponding to keys
+     * @param tuples   tuples for key, symbol, value
      */
-    protected SpillObjectCreator(final CodeGenerator codegen, final List<String> keys, final List<Symbol> symbols, final List<Expression> values) {
-        super(codegen, keys, symbols, false, false);
-        this.values = values;
+    SpillObjectCreator(final CodeGenerator codegen, final List<MapTuple<Expression>> tuples) {
+        super(codegen, tuples, false, false);
         makeMap();
     }
 
@@ -68,82 +64,123 @@
     protected void makeObject(final MethodEmitter method) {
         assert !isScope() : "spill scope objects are not currently supported";
 
-        final int          length        = keys.size();
-        final Object[]     presetValues  = new Object[length];
+        final int          length        = tuples.size();
+        final long[]       jpresetValues = new long[ScriptObject.spillAllocationLength(length)];
+        final Object[]     opresetValues = new Object[ScriptObject.spillAllocationLength(length)];
         final Set<Integer> postsetValues = new LinkedHashSet<>();
         final int          callSiteFlags = codegen.getCallSiteFlags();
-        ArrayData          arrayData     = ArrayData.allocate(new Object[0]);
+        ArrayData          arrayData     = ArrayData.allocate(ScriptRuntime.EMPTY_ARRAY);
 
         // Compute constant property values
-        for (int i = 0; i < length; i++) {
-            final String key = keys.get(i);
-            final Expression value = values.get(i);
+        int pos = 0;
+        for (final MapTuple<Expression> tuple : tuples) {
+            final String     key   = tuple.key;
+            final Expression value = tuple.value;
 
-            if (value == null) {
-                continue; // getter or setter
-            }
+            //this is a nop of tuple.key isn't e.g. "apply" or another special name
+            method.invalidateSpecialName(tuple.key);
 
-            final Object constantValue = LiteralNode.objectAsConstant(value);
-            if (constantValue == LiteralNode.POSTSET_MARKER) {
-                postsetValues.add(i);
-                continue;
-            }
+            if (value != null) {
+                final Object constantValue = LiteralNode.objectAsConstant(value);
+                if (constantValue == LiteralNode.POSTSET_MARKER) {
+                    postsetValues.add(pos);
+                } else {
+                    final Property property = propertyMap.findProperty(key);
+                    if (property != null) {
+                        // normal property key
+                        property.setCurrentType(JSType.unboxedFieldType(constantValue));
+                        final int slot = property.getSlot();
+                        if (!OBJECT_FIELDS_ONLY && constantValue instanceof Number) {
+                            jpresetValues[slot] = ObjectClassGenerator.pack((Number)constantValue);
+                        } else {
+                            opresetValues[slot] = constantValue;
+                        }
+                    } else {
+                        // array index key
+                        final long oldLength = arrayData.length();
+                        final int  index     = ArrayIndex.getArrayIndex(key);
+                        final long longIndex = ArrayIndex.toLongIndex(index);
 
-            final Property property = propertyMap.findProperty(key);
-            if (property != null) {
-                // normal property key
-                presetValues[property.getSlot()] = constantValue;
-            } else {
-                // array index key
-                final long oldLength = arrayData.length();
-                final int index = ArrayIndex.getArrayIndex(key);
-                assert ArrayIndex.isValidArrayIndex(index);
-                final long longIndex =  ArrayIndex.toLongIndex(index);
-                if (longIndex >= oldLength) {
-                    arrayData = arrayData.ensure(longIndex);
-                }
-                arrayData = arrayData.set(index, constantValue, false);
-                if (longIndex > oldLength) {
-                    arrayData = arrayData.delete(oldLength, longIndex - 1);
+                        assert ArrayIndex.isValidArrayIndex(index);
+
+                        if (longIndex >= oldLength) {
+                            arrayData = arrayData.ensure(longIndex);
+                        }
+
+                        //avoid blowing up the array if we can
+                        if (constantValue instanceof Integer) {
+                            arrayData = arrayData.set(index, ((Integer)constantValue).intValue(), false);
+                        } else if (constantValue instanceof Long) {
+                            arrayData = arrayData.set(index, ((Long)constantValue).longValue(), false);
+                        } else if (constantValue instanceof Double) {
+                            arrayData = arrayData.set(index, ((Double)constantValue).doubleValue(), false);
+                        } else {
+                            arrayData = arrayData.set(index, constantValue, false);
+                        }
+
+                        if (longIndex > oldLength) {
+                            arrayData = arrayData.delete(oldLength, longIndex - 1);
+                        }
+                    }
                 }
             }
+            pos++;
         }
 
+        //assert postsetValues.isEmpty() : "test me " + postsetValues;
+
         // create object and invoke constructor
         method._new(JO.class).dup();
         codegen.loadConstant(propertyMap);
-        method.invoke(constructorNoLookup(JO.class, PropertyMap.class));
 
-        // Set spill array with preset values
-        method.dup();
-        codegen.loadConstant(presetValues);
-        method.putField(Type.getInternalName(ScriptObject.class), "spill", Type.OBJECT_ARRAY.getDescriptor());
+        //load primitive values to j spill array
+        codegen.loadConstant(jpresetValues);
+        for (final int i : postsetValues) {
+            final MapTuple<Expression> tuple    = tuples.get(i);
+            final Property                property = propertyMap.findProperty(tuple.key);
+            if (property != null && tuple.isPrimitive()) {
+                method.dup();
+                method.load(property.getSlot());
+                loadTuple(method, tuple);
+                method.arraystore();
+            }
+        }
 
-        // Set array data if any
+        //load object values to o spill array
+        codegen.loadConstant(opresetValues);
+        for (final int i : postsetValues) {
+            final MapTuple<Expression> tuple    = tuples.get(i);
+            final Property             property = propertyMap.findProperty(tuple.key);
+            if (property != null && !tuple.isPrimitive()) {
+                method.dup();
+                method.load(property.getSlot());
+                loadTuple(method, tuple);
+                method.arraystore();
+            }
+        }
+
+        //instantiate the script object with spill objects
+        method.invoke(constructorNoLookup(JO.class, PropertyMap.class, long[].class, Object[].class));
+
+        // Set prefix array data if any
         if (arrayData.length() > 0) {
             method.dup();
             codegen.loadConstant(arrayData);
-            method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray",void.class, ArrayData.class));
+            method.invoke(virtualCallNoLookup(ScriptObject.class, "setArray", void.class, ArrayData.class));
         }
 
-        // Create properties with non-constant values
-        for (int i : postsetValues) {
-            final String key = keys.get(i);
-            final Property property = propertyMap.findProperty(key);
-
+        // set postfix
+        for (final int i : postsetValues) {
+            final MapTuple<Expression> tuple    = tuples.get(i);
+            final Property             property = propertyMap.findProperty(tuple.key);
             if (property == null) {
-                final int index = ArrayIndex.getArrayIndex(key);
+                final int index = ArrayIndex.getArrayIndex(tuple.key);
                 assert ArrayIndex.isValidArrayIndex(index);
                 method.dup();
                 method.load(ArrayIndex.toLongIndex(index));
-                codegen.load(values.get(i));
+                //method.println("putting " + tuple + " into arraydata");
+                loadTuple(method, tuple);
                 method.dynamicSetIndex(callSiteFlags);
-            } else {
-                method.dup();
-                method.getField(Type.getInternalName(ScriptObject.class), "spill", Type.OBJECT_ARRAY.getDescriptor());
-                method.load(property.getSlot());
-                codegen.load(values.get(i), OBJECT);
-                method.arraystore();
             }
         }
     }
@@ -151,14 +188,12 @@
     @Override
     protected PropertyMap makeMap() {
         assert propertyMap == null : "property map already initialized";
-
-        propertyMap = new MapCreator(JO.class, keys, symbols) {
-            @Override
-            protected int getPropertyFlags(Symbol symbol, boolean hasArguments) {
-                return super.getPropertyFlags(symbol, hasArguments) | Property.IS_SPILL | Property.IS_ALWAYS_OBJECT;
-            }
-        }.makeSpillMap(false);
-
+        propertyMap = new MapCreator<>(JO.class, tuples).makeSpillMap(false);
         return propertyMap;
     }
+
+    @Override
+    protected void loadValue(final Expression expr, final Type type) {
+        codegen.loadExpressionAsType(expr, type);
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java b/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
index e689820..d5feac5 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/SplitMethodEmitter.java
@@ -25,13 +25,13 @@
 
 package jdk.nashorn.internal.codegen;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import static jdk.nashorn.internal.codegen.CompilerConstants.SCOPE;
 
+import java.util.ArrayList;
+import java.util.List;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.BreakableNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.runtime.Scope;
@@ -47,16 +47,23 @@
     private final SplitNode splitNode;
 
     private final List<Label> externalTargets = new ArrayList<>();
+    /**
+     * In addition to external target labels, we need to track the target breakables too as the code generator needs to
+     * be able to correctly pop the scopes to the target, see {@link CodeGenerator#leaveSplitNode(SplitNode)}. Note that
+     * this is only used within CodeGenerator, which doesn't mutate the AST, so keeping pointers to other nodes is not
+     * incorrect.
+     */
+    private final List<BreakableNode> externalTargetNodes = new ArrayList<>();
 
-    SplitMethodEmitter(final ClassEmitter classEmitter, final MethodVisitor mv, SplitNode splitNode) {
+    SplitMethodEmitter(final ClassEmitter classEmitter, final MethodVisitor mv, final SplitNode splitNode) {
         super(classEmitter, mv);
         this.splitNode = splitNode;
     }
 
     @Override
-    void splitAwareGoto(final LexicalContext lc, final Label label) {
+    void splitAwareGoto(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
         assert splitNode != null;
-        final int index = findExternalTarget(lc, label);
+        final int index = findExternalTarget(lc, label, targetNode);
         if (index >= 0) {
             loadCompilerConstant(SCOPE);
             checkcast(Scope.class);
@@ -66,18 +73,19 @@
             _return(functionNode.getReturnType());
             return;
         }
-        super.splitAwareGoto(lc, label);
+        super.splitAwareGoto(lc, label, targetNode);
     }
 
-    private int findExternalTarget(final LexicalContext lc, final Label label) {
+    private int findExternalTarget(final LexicalContext lc, final Label label, final BreakableNode targetNode) {
         final int index = externalTargets.indexOf(label);
 
         if (index >= 0) {
             return index;
         }
 
-        if (lc.isExternalTarget(splitNode, label)) {
+        if (lc.isExternalTarget(splitNode, targetNode)) {
             externalTargets.add(label);
+            externalTargetNodes.add(targetNode);
             return externalTargets.size() - 1;
         }
         return -1;
@@ -93,8 +101,11 @@
         return this;
     }
 
-    @Override
     final List<Label> getExternalTargets() {
         return externalTargets;
     }
+
+    final List<BreakableNode> getExternalTargetNodes() {
+        return externalTargetNodes;
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java
index 1933849..9405d06 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/Splitter.java
@@ -42,7 +42,7 @@
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -64,7 +64,7 @@
     /** Weight threshold for when to start a split. */
     public static final long SPLIT_THRESHOLD = Options.getIntProperty("nashorn.compiler.splitter.threshold", 32 * 1024);
 
-    private static final DebugLogger LOG = Compiler.LOG;
+    private final DebugLogger log;
 
     /**
      * Constructor.
@@ -78,30 +78,27 @@
         this.compiler             = compiler;
         this.outermost            = functionNode;
         this.outermostCompileUnit = outermostCompileUnit;
+        this.log                  = compiler.getLogger();
     }
 
     /**
-     * Execute the split
+     * Execute the split.
+     * @param fn the function to split
+     * @param top whether this is the topmost compiled function (it's either a program, or we're doing a recompilation).
      */
-    FunctionNode split(final FunctionNode fn) {
+    FunctionNode split(final FunctionNode fn, final boolean top) {
         FunctionNode functionNode = fn;
 
-        if (functionNode.isLazy()) {
-            LOG.finest("Postponing split of '", functionNode.getName(), "' as it's lazy");
-            return functionNode;
-        }
-
-        LOG.finest("Initiating split of '", functionNode.getName(), "'");
+        log.finest("Initiating split of '", functionNode.getName(), "'");
 
         long weight = WeighNodes.weigh(functionNode);
-        final boolean top = fn.isProgram(); //compiler.getFunctionNode() == outermost;
 
         // We know that our LexicalContext is empty outside the call to functionNode.accept(this) below,
         // so we can pass null to all methods expecting a LexicalContext parameter.
         assert lc.isEmpty() : "LexicalContext not empty";
 
         if (weight >= SPLIT_THRESHOLD) {
-            LOG.finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
+            log.finest("Splitting '", functionNode.getName(), "' as its weight ", weight, " exceeds split threshold ", SPLIT_THRESHOLD);
             functionNode = (FunctionNode)functionNode.accept(this);
 
             if (functionNode.isSplit()) {
@@ -138,7 +135,7 @@
 
             @Override
             public Node leaveFunctionNode(final FunctionNode nestedFunction) {
-                FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction);
+                final FunctionNode split = new Splitter(compiler, nestedFunction, outermostCompileUnit).split(nestedFunction, false);
                 lc.replace(nestedFunction, split);
                 return split;
             }
@@ -310,7 +307,7 @@
                 units.add(new ArrayUnit(unit, lo, postsets.length));
             }
 
-            arrayLiteralNode.setUnits(units);
+            return arrayLiteralNode.setUnits(lc, units);
         }
 
         return literal;
@@ -319,10 +316,7 @@
     @Override
     public boolean enterFunctionNode(final FunctionNode node) {
         //only go into the function node for this splitter. any subfunctions are rejected
-        if (node == outermost && !node.isLazy()) {
-            return true;
-        }
-        return false;
+        return node == outermost;
     }
 }
 
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/TypeEvaluator.java b/nashorn/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
new file mode 100644
index 0000000..c8dd5b3
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/TypeEvaluator.java
@@ -0,0 +1,208 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import static jdk.nashorn.internal.runtime.Property.NOT_CONFIGURABLE;
+import static jdk.nashorn.internal.runtime.Property.NOT_ENUMERABLE;
+import static jdk.nashorn.internal.runtime.Property.NOT_WRITABLE;
+
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.AccessNode;
+import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.IdentNode;
+import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.Optimistic;
+import jdk.nashorn.internal.objects.NativeArray;
+import jdk.nashorn.internal.runtime.FindProperty;
+import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.Property;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+
+/**
+ * Functionality for using a runtime scope to look up value types.
+ * Used during recompilation.
+ */
+final class TypeEvaluator {
+    private final Compiler compiler;
+    private final ScriptObject runtimeScope;
+
+    TypeEvaluator(final Compiler compiler, final ScriptObject runtimeScope) {
+        this.compiler = compiler;
+        this.runtimeScope = runtimeScope;
+    }
+
+    Type getOptimisticType(final Optimistic node) {
+        assert compiler.useOptimisticTypes();
+
+        final int  programPoint = node.getProgramPoint();
+        final Type validType    = compiler.getInvalidatedProgramPointType(programPoint);
+
+        if (validType != null) {
+            return validType;
+        }
+
+        final Type mostOptimisticType = node.getMostOptimisticType();
+        final Type evaluatedType      = getEvaluatedType(node);
+
+        if (evaluatedType != null) {
+            if (evaluatedType.widerThan(mostOptimisticType)) {
+                final Type newValidType = evaluatedType.isObject() || evaluatedType.isBoolean() ? Type.OBJECT : evaluatedType;
+                // Update invalidatedProgramPoints so we don't re-evaluate the expression next time. This is a heuristic
+                // as we're doing a tradeoff. Re-evaluating expressions on each recompile takes time, but it might
+                // notice a widening in the type of the expression and thus prevent an unnecessary deoptimization later.
+                // We'll presume though that the types of expressions are mostly stable, so if we evaluated it in one
+                // compilation, we'll keep to that and risk a low-probability deoptimization if its type gets widened
+                // in the future.
+                compiler.addInvalidatedProgramPoint(node.getProgramPoint(), newValidType);
+            }
+            return evaluatedType;
+        }
+        return mostOptimisticType;
+    }
+
+    private static Type getPropertyType(final ScriptObject sobj, final String name) {
+        final FindProperty find = sobj.findProperty(name, true);
+        if (find == null) {
+            return null;
+        }
+
+        final Property property      = find.getProperty();
+        final Class<?> propertyClass = property.getCurrentType();
+        if (propertyClass == null) {
+            // propertyClass == null means its value is Undefined. It is probably not initialized yet, so we won't make
+            // a type assumption yet.
+            return null;
+        } else if (propertyClass.isPrimitive()) {
+            return Type.typeFor(propertyClass);
+        }
+
+        final ScriptObject owner = find.getOwner();
+        if (property.hasGetterFunction(owner)) {
+            // Can have side effects, so we can't safely evaluate it; since !propertyClass.isPrimitive(), it's Object.
+            return Type.OBJECT;
+        }
+
+        // Safely evaluate the property, and return the narrowest type for the actual value (e.g. Type.INT for a boxed
+        // integer).
+        final Object value = property.getObjectValue(owner, owner);
+        if (value == ScriptRuntime.UNDEFINED) {
+            return null;
+        }
+        return Type.typeFor(JSType.unboxedFieldType(value));
+    }
+
+    /**
+     * Declares a symbol name as belonging to a non-scoped local variable during an on-demand compilation of a single
+     * function. This method will add an explicit Undefined binding for the local into the runtime scope if it's
+     * otherwise implicitly undefined so that when an expression is evaluated for the name, it won't accidentally find
+     * an unrelated value higher up the scope chain. It is only required to call this method when doing an optimistic
+     * on-demand compilation.
+     * @param symbolName the name of the symbol that is to be declared as being a non-scoped local variable.
+     */
+    void declareLocalSymbol(final String symbolName) {
+        assert
+            compiler.useOptimisticTypes() &&
+            compiler.isOnDemandCompilation() &&
+            runtimeScope != null :
+                "useOptimistic=" +
+                    compiler.useOptimisticTypes() +
+                    " isOnDemand=" +
+                    compiler.isOnDemandCompilation() +
+                    " scope="+runtimeScope;
+
+        if (runtimeScope.findProperty(symbolName, false) == null) {
+            runtimeScope.addOwnProperty(symbolName, NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE, ScriptRuntime.UNDEFINED);
+        }
+    }
+
+    private Object evaluateSafely(final Expression expr) {
+        if (expr instanceof IdentNode) {
+            return runtimeScope == null ? null : evaluatePropertySafely(runtimeScope, ((IdentNode)expr).getName());
+        }
+
+        if (expr instanceof AccessNode) {
+            final AccessNode accessNode = (AccessNode)expr;
+            final Object     base       = evaluateSafely(accessNode.getBase());
+            if (!(base instanceof ScriptObject)) {
+                return null;
+            }
+            return evaluatePropertySafely((ScriptObject)base, accessNode.getProperty());
+        }
+
+        return null;
+    }
+
+    private static Object evaluatePropertySafely(final ScriptObject sobj, final String name) {
+        final FindProperty find = sobj.findProperty(name, true);
+        if (find == null) {
+            return null;
+        }
+        final Property     property = find.getProperty();
+        final ScriptObject owner    = find.getOwner();
+        if (property.hasGetterFunction(owner)) {
+            // Possible side effects; can't evaluate safely
+            return null;
+        }
+        return property.getObjectValue(owner, owner);
+    }
+
+
+    private Type getEvaluatedType(final Optimistic expr) {
+        if (expr instanceof IdentNode) {
+            if (runtimeScope == null) {
+                return null;
+            }
+            return getPropertyType(runtimeScope, ((IdentNode)expr).getName());
+        }
+
+        if (expr instanceof AccessNode) {
+            final AccessNode accessNode = (AccessNode)expr;
+            final Object base = evaluateSafely(accessNode.getBase());
+            if (!(base instanceof ScriptObject)) {
+                return null;
+            }
+            return getPropertyType((ScriptObject)base, accessNode.getProperty());
+        }
+
+        if (expr instanceof IndexNode) {
+            final IndexNode indexNode = (IndexNode)expr;
+            final Object    base = evaluateSafely(indexNode.getBase());
+            if(!(base instanceof NativeArray)) {
+                // We only know how to deal with NativeArray. TODO: maybe manage buffers too
+                return null;
+            }
+            // NOTE: optimistic array getters throw UnwarrantedOptimismException based on the type of their underlying
+            // array storage, not based on values of individual elements. Thus, a LongArrayData will throw UOE for every
+            // optimistic int linkage attempt, even if the long value being returned in the first invocation would be
+            // representable as int. That way, we can presume that the array's optimistic type is the most optimistic
+            // type for which an element getter has a chance of executing successfully.
+            return ((NativeArray)base).getArray().getOptimisticType();
+        }
+
+        return null;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/TypeMap.java b/nashorn/src/jdk/nashorn/internal/codegen/TypeMap.java
new file mode 100644
index 0000000..11efce1
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/codegen/TypeMap.java
@@ -0,0 +1,166 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.codegen;
+
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.ScriptFunction;
+
+/**
+ * A data structure that maps one or several function nodes (by their unique id:s, not by
+ * the FunctionNode object itself, due to copy on write changing it several times through
+ * code generation.
+ */
+public class TypeMap {
+    private final Map<Integer, Type[]> paramTypeMap  = new HashMap<>();
+    private final Map<Integer, Type>   returnTypeMap = new HashMap<>();
+    private final boolean needsCallee;
+
+    /**
+     * Constructor
+     * @param functionNodeId function node id
+     * @param type           method type found at runtime corresponding to parameter guess
+     * @param needsCallee    does the function using this type map need a callee
+     */
+    public TypeMap(final int functionNodeId, final MethodType type, final boolean needsCallee) {
+        final Type[] types = new Type[type.parameterCount()];
+        int pos = 0;
+        for (final Class<?> p : type.parameterArray()) {
+            types[pos++] = Type.typeFor(p);
+        }
+        paramTypeMap.put(functionNodeId, types);
+        returnTypeMap.put(functionNodeId, Type.typeFor(type.returnType()));
+
+        this.needsCallee = needsCallee;
+    }
+
+    /**
+     * Returns the array of parameter types for a particular function node
+     * @param functionNodeId the ID of the function node
+     * @return an array of parameter types
+     * @throws NoSuchElementException if the type map has no mapping for the requested function
+     */
+    public Type[] getParameterTypes(final int functionNodeId) {
+        final Type[] paramTypes = paramTypeMap.get(functionNodeId);
+        if (paramTypes == null) {
+            throw new NoSuchElementException(Integer.toString(functionNodeId));
+        }
+        return paramTypes.clone();
+    }
+
+    MethodType getCallSiteType(final FunctionNode functionNode) {
+        final Type[] types = paramTypeMap.get(functionNode.getId());
+        if (types == null) {
+            return null;
+        }
+
+        MethodType mt = MethodType.methodType(returnTypeMap.get(functionNode.getId()).getTypeClass());
+        if (needsCallee) {
+            mt = mt.appendParameterTypes(ScriptFunction.class);
+        }
+
+        mt = mt.appendParameterTypes(Object.class); //this
+
+        for (final Type type : types) {
+            if (type == null) {
+                return null; // not all parameter information is supplied
+            }
+            mt = mt.appendParameterTypes(type.getTypeClass());
+        }
+
+        return mt;
+    }
+
+    /**
+     * Does the function using this TypeMap need a callee argument. This is used
+     * to compute correct param index offsets in {@link jdk.nashorn.internal.codegen.ApplySpecialization}
+     * @return true if a callee is needed, false otherwise
+     */
+    public boolean needsCallee() {
+        return needsCallee;
+    }
+
+    /**
+     * Get the parameter type for this parameter position, or
+     * null if now known
+     * @param functionNode functionNode
+     * @param pos position
+     * @return parameter type for this callsite if known
+     */
+    Type get(final FunctionNode functionNode, final int pos) {
+        final Type[] types = paramTypeMap.get(functionNode.getId());
+        assert types == null || pos < types.length : "fn = " + functionNode.getId() + " " + "types=" + Arrays.toString(types) + " || pos=" + pos + " >= length=" + types.length + " in " + this;
+        if (types != null && pos < types.length) {
+            return types[pos];
+        }
+        return null;
+    }
+
+    boolean has(final FunctionNode functionNode) {
+        final int id = functionNode.getId();
+        final Type[] paramTypes = paramTypeMap.get(id);
+        assert (paramTypes == null) == (returnTypeMap.get(id) == null) : "inconsistent param and return types in param map";
+        return paramTypes != null;
+    }
+
+    @Override
+    public String toString() {
+        return toString("");
+    }
+
+    String toString(final String prefix) {
+        final StringBuilder sb = new StringBuilder();
+
+        if (paramTypeMap.isEmpty()) {
+            sb.append(prefix).append("\t<empty>");
+            return sb.toString();
+        }
+
+        for (final Map.Entry<Integer, Type[]> entry : paramTypeMap.entrySet()) {
+            final int id = entry.getKey();
+            sb.append(prefix).append('\t');
+            sb.append("function ").append(id).append('\n');
+            sb.append(prefix).append("\t\tparamTypes=");
+            if (entry.getValue() == null) {
+                sb.append("[]");
+            } else {
+                sb.append(Arrays.toString(entry.getValue()));
+            }
+            sb.append('\n');
+            sb.append(prefix).append("\t\treturnType=");
+            final Type ret = returnTypeMap.get(id);
+            sb.append(ret == null ? "N/A" : ret);
+            sb.append('\n');
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java
index f594048..26660a3 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/WeighNodes.java
@@ -27,7 +27,6 @@
 
 import java.util.List;
 import java.util.Map;
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
@@ -69,24 +68,25 @@
      * Weight constants.
      */
     static final long FUNCTION_WEIGHT  = 40;
-    static final long AASTORE_WEIGHT   = 2;
-    static final long ACCESS_WEIGHT    = 4;
+    static final long AASTORE_WEIGHT   =  2;
+    static final long ACCESS_WEIGHT    =  4;
     static final long ADD_WEIGHT       = 10;
-    static final long BREAK_WEIGHT     = 1;
+    static final long BREAK_WEIGHT     =  1;
     static final long CALL_WEIGHT      = 10;
     static final long CATCH_WEIGHT     = 10;
-    static final long CONTINUE_WEIGHT  = 1;
-    static final long IF_WEIGHT        = 2;
+    static final long COMPARE_WEIGHT   =  6;
+    static final long CONTINUE_WEIGHT  =  1;
+    static final long IF_WEIGHT        =  2;
     static final long LITERAL_WEIGHT   = 10;
-    static final long LOOP_WEIGHT      = 4;
-    static final long NEW_WEIGHT       = 6;
+    static final long LOOP_WEIGHT      =  4;
+    static final long NEW_WEIGHT       =  6;
     static final long FUNC_EXPR_WEIGHT = 20;
-    static final long RETURN_WEIGHT    = 2;
+    static final long RETURN_WEIGHT    =  2;
     static final long SPLIT_WEIGHT     = 40;
-    static final long SWITCH_WEIGHT    = 8;
-    static final long THROW_WEIGHT     = 2;
+    static final long SWITCH_WEIGHT    =  8;
+    static final long THROW_WEIGHT     =  2;
     static final long VAR_WEIGHT       = 40;
-    static final long WITH_WEIGHT      = 8;
+    static final long WITH_WEIGHT      =  8;
 
     /** Accumulated weight. */
     private long weight;
@@ -101,7 +101,7 @@
      *
      * @param weightCache cache of already calculated block weights
      */
-    private WeighNodes(FunctionNode topFunction, final Map<Node, Long> weightCache) {
+    private WeighNodes(final FunctionNode topFunction, final Map<Node, Long> weightCache) {
         super(new LexicalContext());
         this.topFunction = topFunction;
         this.weightCache = weightCache;
@@ -173,7 +173,6 @@
         if (functionNode == topFunction) {
             // the function being weighted; descend into its statements
             return true;
-//            functionNode.visitStatements(this);
         }
         // just a reference to inner function from outer function
         weight += FUNC_EXPR_WEIGHT;
@@ -307,11 +306,6 @@
     }
 
     @Override
-    public Node leaveDISCARD(final UnaryNode unaryNode) {
-        return unaryNodeWeight(unaryNode);
-    }
-
-    @Override
     public Node leaveNEW(final UnaryNode unaryNode) {
         weight += NEW_WEIGHT;
         return unaryNode;
@@ -446,22 +440,22 @@
 
     @Override
     public Node leaveEQ(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
     public Node leaveEQ_STRICT(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
     public Node leaveGE(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
     public Node leaveGT(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
@@ -478,12 +472,12 @@
 
     @Override
     public Node leaveLE(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
     public Node leaveLT(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
@@ -498,12 +492,12 @@
 
     @Override
     public Node leaveNE(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
     public Node leaveNE_STRICT(final BinaryNode binaryNode) {
-        return runtimeNodeWeight(binaryNode);
+        return compareWeight(binaryNode);
     }
 
     @Override
@@ -546,8 +540,8 @@
         return unaryNode;
     }
 
-    private Node runtimeNodeWeight(final BinaryNode binaryNode) {
-        weight += Type.widest(binaryNode.lhs().getType(), binaryNode.rhs().getType()).isObject() ? CALL_WEIGHT : 1;
+    private Node compareWeight(final BinaryNode binaryNode) {
+        weight += COMPARE_WEIGHT;
         return binaryNode;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/BooleanType.java b/nashorn/src/jdk/nashorn/internal/codegen/types/BooleanType.java
index 840b291..4510102 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/BooleanType.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/BooleanType.java
@@ -50,17 +50,20 @@
 
 package jdk.nashorn.internal.codegen.types;
 
+import static jdk.internal.org.objectweb.asm.Opcodes.I2D;
+import static jdk.internal.org.objectweb.asm.Opcodes.I2L;
+import static jdk.internal.org.objectweb.asm.Opcodes.IADD;
 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_0;
 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_1;
 import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
 import static jdk.internal.org.objectweb.asm.Opcodes.ISTORE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
-import jdk.nashorn.internal.runtime.JSType;
 
 /**
  * The boolean type class
@@ -68,6 +71,7 @@
 public final class BooleanType extends Type {
 
     private static final CompilerConstants.Call VALUE_OF = staticCallNoLookup(Boolean.class, "valueOf", Boolean.class, boolean.class);
+    private static final CompilerConstants.Call TO_STRING = staticCallNoLookup(Boolean.class, "toString", String.class, boolean.class);
 
     /**
      * Constructor
@@ -87,8 +91,19 @@
     }
 
     @Override
+    public char getBytecodeStackType() {
+        return 'I';
+    }
+
+    @Override
     public Type loadUndefined(final MethodVisitor method) {
-        method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_INT);
+        method.visitLdcInsn(UNDEFINED_INT);
+        return BOOLEAN;
+    }
+
+    @Override
+    public Type loadForcedInitializer(final MethodVisitor method) {
+        method.visitInsn(ICONST_0);
         return BOOLEAN;
     }
 
@@ -124,31 +139,30 @@
         }
 
         if (to.isNumber()) {
-            convert(method, OBJECT);
-            invokeStatic(method, JSType.TO_NUMBER);
+            method.visitInsn(I2D);
+        } else if (to.isLong()) {
+            method.visitInsn(I2L);
         } else if (to.isInteger()) {
-            return to; // do nothing.
-        } else if (to.isLong()) {
-            convert(method, OBJECT);
-            invokeStatic(method, JSType.TO_UINT32);
-        } else if (to.isLong()) {
-            convert(method, OBJECT);
-            invokeStatic(method, JSType.TO_LONG);
+            //nop
         } else if (to.isString()) {
-            invokeStatic(method, VALUE_OF);
-            invokeStatic(method, JSType.TO_PRIMITIVE_TO_STRING);
+            invokestatic(method, TO_STRING);
         } else if (to.isObject()) {
-            invokeStatic(method, VALUE_OF);
+            invokestatic(method, VALUE_OF);
         } else {
-            assert false : "Illegal conversion " + this + " -> " + to;
+            throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
         }
 
         return to;
     }
 
     @Override
-    public Type add(final MethodVisitor method) {
-        assert false : "unsupported operation";
-        return null;
+    public Type add(final MethodVisitor method, final int programPoint) {
+        // Adding booleans in JavaScript is perfectly valid, they add as if false=0 and true=1
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(IADD);
+        } else {
+            method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint);
+        }
+        return INT;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java b/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java
index ae53028..91209c2 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeNumericOps.java
@@ -36,50 +36,55 @@
      * Pop and negate the value on top of the stack and push the result
      *
      * @param method method visitor
-     *
+     * @param programPoint program point id
      * @return result type
      */
-    Type neg(MethodVisitor method);
+    Type neg(MethodVisitor method, int programPoint);
 
     /**
      * Pop two values on top of the stack and subtract the first from the
      * second, pushing the result on the stack
      *
      * @param method method visitor
-     *
+     * @param programPoint program point id
      * @return result type
      */
-    Type sub(MethodVisitor method);
+    Type sub(MethodVisitor method, int programPoint);
 
     /**
      * Pop and multiply the two values on top of the stack and push the result
      * on the stack
      *
      * @param method method visitor
-     *
+     * @param programPoint program point id
      * @return result type
      */
-    Type mul(MethodVisitor method);
+    Type mul(MethodVisitor method, int programPoint);
 
     /**
      * Pop two values on top of the stack and divide the first with the second,
      * pushing the result on the stack
      *
      * @param method method visitor
-     *
+     * @param programPoint program point id
      * @return result type
      */
-    Type div(MethodVisitor method);
+    Type div(MethodVisitor method, int programPoint);
 
     /**
      * Pop two values on top of the stack and compute the modulo of the first
      * with the second, pushing the result on the stack
      *
-     * @param method method visitor
+     * Note that the rem method never takes a program point, because it
+     * can never be more optimistic than its widest operand - an int/int
+     * rem operation or a long/long rem operation can never return a
+     * winder remainder than the int or the long
      *
+     * @param method method visitor
+     * @param programPoint program point id
      * @return result type
      */
-    Type rem(MethodVisitor method);
+    Type rem(MethodVisitor method, int programPoint);
 
     /**
      * Comparison with int return value, e.g. LCMP, DCMP.
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java b/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
index bbbddf9..1cfb757 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/BytecodeOps.java
@@ -85,9 +85,10 @@
      * first to the second, pushing the result on the stack
      *
      * @param method  method visitor
+     * @param programPoint program point id
      * @return result type
      */
-    Type add(MethodVisitor method);
+    Type add(MethodVisitor method, int programPoint);
 
     /**
      * Load a variable from a local slot to the stack
@@ -129,6 +130,17 @@
     Type loadUndefined(MethodVisitor method);
 
     /**
+     * Load the "forced initializer" value to the stack, used to ensure that a local variable has a value when it is
+     * read by the unwarranted optimism catch block.
+     *
+     * @param  method  method visitor.
+     *
+     * @return the forced initialization type at the top of the stack
+     */
+    Type loadForcedInitializer(MethodVisitor method);
+
+
+    /**
      * Load the "empty" value to the stack.
      *
      * @param  method  method visitor.
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/IntType.java b/nashorn/src/jdk/nashorn/internal/codegen/types/IntType.java
index c282d10..b642186 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/IntType.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/IntType.java
@@ -37,12 +37,10 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_4;
 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_5;
 import static jdk.internal.org.objectweb.asm.Opcodes.ICONST_M1;
-import static jdk.internal.org.objectweb.asm.Opcodes.IDIV;
 import static jdk.internal.org.objectweb.asm.Opcodes.ILOAD;
 import static jdk.internal.org.objectweb.asm.Opcodes.IMUL;
 import static jdk.internal.org.objectweb.asm.Opcodes.INEG;
 import static jdk.internal.org.objectweb.asm.Opcodes.IOR;
-import static jdk.internal.org.objectweb.asm.Opcodes.IREM;
 import static jdk.internal.org.objectweb.asm.Opcodes.IRETURN;
 import static jdk.internal.org.objectweb.asm.Opcodes.ISHL;
 import static jdk.internal.org.objectweb.asm.Opcodes.ISHR;
@@ -52,10 +50,11 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.IXOR;
 import static jdk.internal.org.objectweb.asm.Opcodes.SIPUSH;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 
 /**
  * Type class: INT
@@ -80,42 +79,47 @@
     }
 
     @Override
+    public char getBytecodeStackType() {
+        return 'I';
+    }
+
+    @Override
     public Type ldc(final MethodVisitor method, final Object c) {
         assert c instanceof Integer;
 
         final int value = ((Integer) c).intValue();
 
         switch (value) {
-            case -1:
-                method.visitInsn(ICONST_M1);
-                break;
-            case 0:
-                method.visitInsn(ICONST_0);
-                break;
-            case 1:
-                method.visitInsn(ICONST_1);
-                break;
-            case 2:
-                method.visitInsn(ICONST_2);
-                break;
-            case 3:
-                method.visitInsn(ICONST_3);
-                break;
-            case 4:
-                method.visitInsn(ICONST_4);
-                break;
-            case 5:
-                method.visitInsn(ICONST_5);
-                break;
-            default:
-                if (value == (byte) value) {
-                    method.visitIntInsn(BIPUSH, value);
-                } else if (value == (short) value) {
-                    method.visitIntInsn(SIPUSH, value);
-                } else {
-                    method.visitLdcInsn(c);
-                }
-                break;
+        case -1:
+            method.visitInsn(ICONST_M1);
+            break;
+        case 0:
+            method.visitInsn(ICONST_0);
+            break;
+        case 1:
+            method.visitInsn(ICONST_1);
+            break;
+        case 2:
+            method.visitInsn(ICONST_2);
+            break;
+        case 3:
+            method.visitInsn(ICONST_3);
+            break;
+        case 4:
+            method.visitInsn(ICONST_4);
+            break;
+        case 5:
+            method.visitInsn(ICONST_5);
+            break;
+        default:
+            if (value == (byte) value) {
+                method.visitIntInsn(BIPUSH, value);
+            } else if (value == (short) value) {
+                method.visitIntInsn(SIPUSH, value);
+            } else {
+                method.visitLdcInsn(c);
+            }
+            break;
         }
 
         return Type.INT;
@@ -134,19 +138,23 @@
         } else if (to.isBoolean()) {
             //nop
         } else if (to.isString()) {
-            invokeStatic(method, TO_STRING);
+            invokestatic(method, TO_STRING);
         } else if (to.isObject()) {
-            invokeStatic(method, VALUE_OF);
+            invokestatic(method, VALUE_OF);
         } else {
-            assert false : "Illegal conversion " + this + " -> " + to;
+            throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
         }
 
         return to;
     }
 
     @Override
-    public Type add(final MethodVisitor method) {
-        method.visitInsn(IADD);
+    public Type add(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(IADD);
+        } else {
+            method.visitInvokeDynamicInsn("iadd", "(II)I", MATHBOOTSTRAP, programPoint);
+        }
         return INT;
     }
 
@@ -200,32 +208,50 @@
     }
 
     @Override
-    public Type sub(final MethodVisitor method) {
-        method.visitInsn(ISUB);
+    public Type sub(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(ISUB);
+        } else {
+            method.visitInvokeDynamicInsn("isub", "(II)I", MATHBOOTSTRAP, programPoint);
+        }
         return INT;
     }
 
     @Override
-    public Type mul(final MethodVisitor method) {
-        method.visitInsn(IMUL);
+    public Type mul(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(IMUL);
+        } else {
+            method.visitInvokeDynamicInsn("imul", "(II)I", MATHBOOTSTRAP, programPoint);
+        }
         return INT;
     }
 
     @Override
-    public Type div(final MethodVisitor method) {
-        method.visitInsn(IDIV);
+    public Type div(final MethodVisitor method, final int programPoint) {
+        // Never perform non-optimistic integer division in JavaScript.
+        assert programPoint != INVALID_PROGRAM_POINT;
+
+        method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
         return INT;
     }
 
     @Override
-    public Type rem(final MethodVisitor method) {
-        method.visitInsn(IREM);
+    public Type rem(final MethodVisitor method, final int programPoint) {
+        // Never perform non-optimistic integer remainder in JavaScript.
+        assert programPoint != INVALID_PROGRAM_POINT;
+
+        method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
         return INT;
     }
 
     @Override
-    public Type neg(final MethodVisitor method) {
-        method.visitInsn(INEG);
+    public Type neg(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(INEG);
+        } else {
+            method.visitInvokeDynamicInsn("ineg", "(I)I", MATHBOOTSTRAP, programPoint);
+        }
         return INT;
     }
 
@@ -236,19 +262,24 @@
 
     @Override
     public Type loadUndefined(final MethodVisitor method) {
-        method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_INT);
+        method.visitLdcInsn(UNDEFINED_INT);
+        return INT;
+    }
+
+    @Override
+    public Type loadForcedInitializer(final MethodVisitor method) {
+        method.visitInsn(ICONST_0);
         return INT;
     }
 
     @Override
     public Type cmp(final MethodVisitor method, final boolean isCmpG) {
-        assert false : "unsupported operation";
-        return null;
+        throw new UnsupportedOperationException("cmp" + (isCmpG ? 'g' : 'l'));
     }
 
     @Override
     public Type cmp(final MethodVisitor method) {
-        assert false : "unsupported operation";
-        return null;
+        throw new UnsupportedOperationException("cmp");
     }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/LongType.java b/nashorn/src/jdk/nashorn/internal/codegen/types/LongType.java
index b57ea6d..107a279 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/LongType.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/LongType.java
@@ -32,12 +32,9 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.LCMP;
 import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_0;
 import static jdk.internal.org.objectweb.asm.Opcodes.LCONST_1;
-import static jdk.internal.org.objectweb.asm.Opcodes.LDIV;
 import static jdk.internal.org.objectweb.asm.Opcodes.LLOAD;
 import static jdk.internal.org.objectweb.asm.Opcodes.LMUL;
-import static jdk.internal.org.objectweb.asm.Opcodes.LNEG;
 import static jdk.internal.org.objectweb.asm.Opcodes.LOR;
-import static jdk.internal.org.objectweb.asm.Opcodes.LREM;
 import static jdk.internal.org.objectweb.asm.Opcodes.LRETURN;
 import static jdk.internal.org.objectweb.asm.Opcodes.LSHL;
 import static jdk.internal.org.objectweb.asm.Opcodes.LSHR;
@@ -46,10 +43,12 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.LUSHR;
 import static jdk.internal.org.objectweb.asm.Opcodes.LXOR;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.runtime.JSType;
 
 /**
  * Type class: LONG
@@ -77,6 +76,11 @@
     }
 
     @Override
+    public char getBytecodeStackType() {
+        return 'J';
+    }
+
+    @Override
     public Type cmp(final MethodVisitor method) {
         method.visitInsn(LCMP);
         return INT;
@@ -121,11 +125,11 @@
         if (to.isNumber()) {
             method.visitInsn(L2D);
         } else if (to.isInteger()) {
-            method.visitInsn(L2I);
+            invokestatic(method, JSType.TO_INT32_L);
         } else if (to.isBoolean()) {
             method.visitInsn(L2I);
         } else if (to.isObject()) {
-            invokeStatic(method, VALUE_OF);
+            invokestatic(method, VALUE_OF);
         } else {
             assert false : "Illegal conversion " + this + " -> " + to;
         }
@@ -134,32 +138,50 @@
     }
 
     @Override
-    public Type add(final MethodVisitor method) {
-        method.visitInsn(LADD);
+    public Type add(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(LADD);
+        } else {
+            method.visitInvokeDynamicInsn("ladd", "(JJ)J", MATHBOOTSTRAP, programPoint);
+        }
         return LONG;
     }
 
     @Override
-    public Type sub(final MethodVisitor method) {
-        method.visitInsn(LSUB);
+    public Type sub(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(LSUB);
+        } else {
+            method.visitInvokeDynamicInsn("lsub", "(JJ)J", MATHBOOTSTRAP, programPoint);
+        }
         return LONG;
     }
 
     @Override
-    public Type mul(final MethodVisitor method) {
-        method.visitInsn(LMUL);
+    public Type mul(final MethodVisitor method, final int programPoint) {
+        if(programPoint == INVALID_PROGRAM_POINT) {
+            method.visitInsn(LMUL);
+        } else {
+            method.visitInvokeDynamicInsn("lmul", "(JJ)J", MATHBOOTSTRAP, programPoint);
+        }
         return LONG;
     }
 
     @Override
-    public Type div(final MethodVisitor method) {
-        method.visitInsn(LDIV);
+    public Type div(final MethodVisitor method, final int programPoint) {
+        // Never perform non-optimistic integer division in JavaScript.
+        assert programPoint != INVALID_PROGRAM_POINT;
+
+        method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint);
         return LONG;
     }
 
     @Override
-    public Type rem(final MethodVisitor method) {
-        method.visitInsn(LREM);
+    public Type rem(final MethodVisitor method, final int programPoint) {
+        // Never perform non-optimistic integer remainder in JavaScript.
+        assert programPoint != INVALID_PROGRAM_POINT;
+
+        method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
         return LONG;
     }
 
@@ -200,8 +222,8 @@
     }
 
     @Override
-    public Type neg(final MethodVisitor method) {
-        method.visitInsn(LNEG);
+    public Type neg(final MethodVisitor method, final int programPoint) {
+        method.visitInvokeDynamicInsn("lneg", "(J)J", MATHBOOTSTRAP, programPoint);
         return LONG;
     }
 
@@ -212,7 +234,13 @@
 
     @Override
     public Type loadUndefined(final MethodVisitor method) {
-        method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_LONG);
+        method.visitLdcInsn(UNDEFINED_LONG);
+        return LONG;
+    }
+
+    @Override
+    public Type loadForcedInitializer(final MethodVisitor method) {
+        method.visitInsn(LCONST_0);
         return LONG;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/NumberType.java b/nashorn/src/jdk/nashorn/internal/codegen/types/NumberType.java
index 6a280b7..e5f1432 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/NumberType.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/NumberType.java
@@ -39,10 +39,10 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.DSTORE;
 import static jdk.internal.org.objectweb.asm.Opcodes.DSUB;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
 
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants;
-import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.runtime.JSType;
 
 class NumberType extends NumericType {
@@ -64,6 +64,11 @@
     }
 
     @Override
+    public char getBytecodeStackType() {
+        return 'D';
+    }
+
+    @Override
     public Type cmp(final MethodVisitor method, final boolean isCmpG) {
         method.visitInsn(isCmpG ? DCMPG : DCMPL);
         return INT;
@@ -84,7 +89,13 @@
 
     @Override
     public Type loadUndefined(final MethodVisitor method) {
-        method.visitLdcInsn(ObjectClassGenerator.UNDEFINED_DOUBLE);
+        method.visitLdcInsn(UNDEFINED_DOUBLE);
+        return NUMBER;
+    }
+
+    @Override
+    public Type loadForcedInitializer(final MethodVisitor method) {
+        method.visitInsn(DCONST_0);
         return NUMBER;
     }
 
@@ -112,54 +123,54 @@
         }
 
         if (to.isInteger()) {
-            invokeStatic(method, JSType.TO_INT32_D);
+            invokestatic(method, JSType.TO_INT32_D);
         } else if (to.isLong()) {
-            invokeStatic(method, JSType.TO_INT64_D);
+            invokestatic(method, JSType.TO_LONG_D);
         } else if (to.isBoolean()) {
-            invokeStatic(method, JSType.TO_BOOLEAN_D);
+            invokestatic(method, JSType.TO_BOOLEAN_D);
         } else if (to.isString()) {
-            invokeStatic(method, JSType.TO_STRING_D);
+            invokestatic(method, JSType.TO_STRING_D);
         } else if (to.isObject()) {
-            invokeStatic(method, VALUE_OF);
+            invokestatic(method, VALUE_OF);
         } else {
-            assert false : "Illegal conversion " + this + " -> " + to;
+            throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to);
         }
 
         return to;
     }
 
     @Override
-    public Type add(final MethodVisitor method) {
+    public Type add(final MethodVisitor method, final int programPoint) {
         method.visitInsn(DADD);
         return NUMBER;
     }
 
     @Override
-    public Type sub(final MethodVisitor method) {
+    public Type sub(final MethodVisitor method, final int programPoint) {
         method.visitInsn(DSUB);
         return NUMBER;
     }
 
     @Override
-    public Type mul(final MethodVisitor method) {
+    public Type mul(final MethodVisitor method, final int programPoint) {
         method.visitInsn(DMUL);
         return NUMBER;
     }
 
     @Override
-    public Type div(final MethodVisitor method) {
+    public Type div(final MethodVisitor method, final int programPoint) {
         method.visitInsn(DDIV);
         return NUMBER;
     }
 
     @Override
-    public Type rem(final MethodVisitor method) {
+    public Type rem(final MethodVisitor method, final int programPoint) {
         method.visitInsn(DREM);
         return NUMBER;
     }
 
     @Override
-    public Type neg(final MethodVisitor method) {
+    public Type neg(final MethodVisitor method, final int programPoint) {
         method.visitInsn(DNEG);
         return NUMBER;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/ObjectType.java b/nashorn/src/jdk/nashorn/internal/codegen/types/ObjectType.java
index 1f7a022..0ccf664 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/ObjectType.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/ObjectType.java
@@ -65,8 +65,13 @@
     }
 
     @Override
-    public Type add(final MethodVisitor method) {
-        invokeStatic(method, ScriptRuntime.ADD);
+    public String getShortDescriptor() {
+        return getTypeClass() == Object.class ? "Object" : getTypeClass().getSimpleName();
+    }
+
+    @Override
+    public Type add(final MethodVisitor method, final int programPoint) {
+        invokestatic(method, ScriptRuntime.ADD);
         return Type.OBJECT;
     }
 
@@ -74,7 +79,7 @@
     public Type load(final MethodVisitor method, final int slot) {
         assert slot != -1;
         method.visitVarInsn(ALOAD, slot);
-        return Type.OBJECT;
+        return this;
     }
 
     @Override
@@ -86,13 +91,21 @@
     @Override
     public Type loadUndefined(final MethodVisitor method) {
         method.visitFieldInsn(GETSTATIC, className(ScriptRuntime.class), "UNDEFINED", typeDescriptor(Undefined.class));
+        return UNDEFINED;
+    }
+
+    @Override
+    public Type loadForcedInitializer(final MethodVisitor method) {
+        method.visitInsn(ACONST_NULL);
+        // TODO: do we need a special type for null, e.g. Type.NULL? It should be assignable to any other object type
+        // without a checkast in convert.
         return OBJECT;
     }
 
     @Override
     public Type loadEmpty(final MethodVisitor method) {
         method.visitFieldInsn(GETSTATIC, className(ScriptRuntime.class), "EMPTY", typeDescriptor(Undefined.class));
-        return OBJECT;
+        return UNDEFINED;
     }
 
     @Override
@@ -108,10 +121,10 @@
             method.visitLdcInsn(c);
             return Type.typeFor(MethodHandle.class);
         } else {
-            assert false : "implementation missing for class " + c.getClass() + " value=" + c;
+            throw new UnsupportedOperationException("implementation missing for class " + c.getClass() + " value=" + c);
         }
 
-        return OBJECT;
+        return Type.OBJECT;
     }
 
     @Override
@@ -138,6 +151,10 @@
                 }
                 return to;
             } else if (to.isObject()) {
+                final Class<?> toClass = to.getTypeClass();
+                if(!toClass.isAssignableFrom(getTypeClass())) {
+                    method.visitTypeInsn(CHECKCAST, CompilerConstants.className(toClass));
+                }
                 return to;
             }
         } else if (isString()) {
@@ -145,17 +162,19 @@
         }
 
         if (to.isInteger()) {
-            invokeStatic(method, JSType.TO_INT32);
+            invokestatic(method, JSType.TO_INT32);
         } else if (to.isNumber()) {
-            invokeStatic(method, JSType.TO_NUMBER);
+            invokestatic(method, JSType.TO_NUMBER);
         } else if (to.isLong()) {
-            invokeStatic(method, JSType.TO_INT64);
+            invokestatic(method, JSType.TO_LONG);
         } else if (to.isBoolean()) {
-            invokeStatic(method, JSType.TO_BOOLEAN);
+            invokestatic(method, JSType.TO_BOOLEAN);
         } else if (to.isString()) {
-            invokeStatic(method, JSType.TO_PRIMITIVE_TO_STRING);
+            invokestatic(method, JSType.TO_PRIMITIVE_TO_STRING);
+        } else if (to.isCharSequence()) {
+            invokestatic(method, JSType.TO_PRIMITIVE_TO_CHARSEQUENCE);
         } else {
-            assert false : "Illegal conversion " + this + " -> " + to + " " + isString() + " " + toString;
+            throw new UnsupportedOperationException("Illegal conversion " + this + " -> " + to + " " + isString() + " " + toString);
         }
 
         return to;
@@ -165,4 +184,9 @@
     public void _return(final MethodVisitor method) {
         method.visitInsn(ARETURN);
     }
+
+    @Override
+    public char getBytecodeStackType() {
+        return 'A';
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java b/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java
deleted file mode 100644
index 2845d90..0000000
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/Range.java
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.codegen.types;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import jdk.nashorn.internal.runtime.DebugLogger;
-import jdk.nashorn.internal.runtime.JSType;
-
-/**
- * Represents the value range of a symbol.
- */
-public abstract class Range {
-
-    private static final Range GENERIC_RANGE = new Range() {
-        @Override
-        public Type getType() {
-            return Type.OBJECT;
-        }
-    };
-
-    private static final Range NUMBER_RANGE = new Range() {
-        @Override
-        public Type getType() {
-            return Type.NUMBER;
-        }
-    };
-
-    private static final Range UNKNOWN_RANGE = new Range() {
-        @Override
-        public Type getType() {
-            return Type.UNKNOWN;
-        }
-
-        @Override
-        public boolean isUnknown() {
-            return true;
-        }
-    };
-
-    private static class IntegerRange extends Range {
-        private final long min;
-        private final long max;
-        private final Type type;
-
-        private IntegerRange(final long min, final long max) {
-            assert min <= max;
-            this.min  = min;
-            this.max  = max;
-            this.type = typeFromRange(min, max);
-        }
-
-        private static Type typeFromRange(final long from, final long to) {
-            if (from >= Integer.MIN_VALUE && to <= Integer.MAX_VALUE) {
-                return Type.INT;
-            }
-            return Type.LONG;
-        }
-
-        @Override
-        public Type getType() {
-            return type;
-        }
-
-        public long getMin() {
-            return min;
-        }
-
-        public long getMax() {
-            return max;
-        }
-
-        @Override
-        public boolean isIntegerConst() {
-            return getMin() == getMax();
-        }
-
-        private long getBitMask() {
-            if (min == max) {
-                return min;
-            }
-
-            if (min < 0) {
-                return ~0L;
-            }
-
-            long mask = 1;
-            while (mask < max) {
-                mask = (mask << 1) | 1;
-            }
-            return mask;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (obj instanceof IntegerRange) {
-                final IntegerRange other = (IntegerRange)obj;
-                return this.type == other.type && this.min == other.min && this.max == other.max;
-            }
-            return false;
-        }
-
-        @Override
-        public int hashCode() {
-            return Long.hashCode(min) ^ Long.hashCode(max);
-        }
-
-        @Override
-        public String toString() {
-            return super.toString() + "[" + min +", " + max + "]";
-        }
-    }
-
-    /**
-     * Get narrowest type for this range
-     * @return type
-     */
-    public abstract Type getType();
-
-    /**
-     * Is this range unknown
-     * @return true if unknown
-     */
-    public boolean isUnknown() {
-        return false;
-    }
-
-    /**
-     * Check if an integer is enough to span this range
-     * @return true if integer is enough
-     */
-    public boolean isIntegerType() {
-        return this instanceof IntegerRange;
-    }
-
-    /**
-     * Check if an integer is enough to span this range
-     * @return true if integer is enough
-     */
-    public boolean isIntegerConst() {
-        return false;
-    }
-
-    /**
-     * Create an unknown range - this is most likely a singleton object
-     * and it represents "we have no known range information"
-     * @return the range
-     */
-    public static Range createUnknownRange() {
-        return UNKNOWN_RANGE;
-    }
-
-    /**
-     * Create a constant range: [value, value]
-     * @param value value
-     * @return the range
-     */
-    public static Range createRange(final int value) {
-        return createIntegerRange(value, value);
-    }
-
-    /**
-     * Create a constant range: [value, value]
-     * @param value value
-     * @return the range
-     */
-    public static Range createRange(final long value) {
-        return createIntegerRange(value, value);
-    }
-
-    /**
-     * Create a constant range: [value, value]
-     * @param value value
-     * @return the range
-     */
-    public static Range createRange(final double value) {
-        if (isRepresentableAsLong(value)) {
-            return createIntegerRange((long) value, (long) value);
-        }
-        return createNumberRange();
-    }
-
-    /**
-     * Create a constant range: [value, value]
-     * @param value value
-     * @return the range
-     */
-    public static Range createRange(final Object value) {
-        if (value instanceof Integer) {
-            return createRange((int)value);
-        } else if (value instanceof Long) {
-            return createRange((long)value);
-        } else if (value instanceof Double) {
-            return createRange((double)value);
-        }
-
-        return createGenericRange();
-    }
-
-    /**
-     * Create a generic range - object symbol that carries no range
-     * information
-     * @return the range
-     */
-    public static Range createGenericRange() {
-        return GENERIC_RANGE;
-    }
-
-    /**
-     * Create a number range - number symbol that carries no range
-     * information
-     * @return the range
-     */
-    public static Range createNumberRange() {
-        return NUMBER_RANGE;
-    }
-
-    /**
-     * Create an integer range [min, max]
-     * @param min minimum value, inclusive
-     * @param max maximum value, inclusive
-     * @return the range
-     */
-    public static IntegerRange createIntegerRange(final long min, final long max) {
-        return new IntegerRange(min, max);
-    }
-
-    /**
-     * Create an integer range of maximum type width for the given type
-     * @param type the type
-     * @return the range
-     */
-    public static IntegerRange createIntegerRange(final Type type) {
-        assert type.isNumeric() && !type.isNumber();
-        final long min;
-        final long max;
-        if (type.isInteger()) {
-            min = Integer.MIN_VALUE;
-            max = Integer.MAX_VALUE;
-        } else if (type.isLong()) {
-            min = Long.MIN_VALUE;
-            max = Long.MAX_VALUE;
-        } else {
-            throw new AssertionError(); //type incompatible with integer range
-        }
-        return new IntegerRange(min, max);
-    }
-
-    /**
-     * Create an range of maximum type width for the given type
-     * @param type the type
-     * @return the range
-     */
-    public static Range createTypeRange(final Type type) {
-        if (type.isNumber()) {
-            return createNumberRange();
-        } else if (type.isNumeric()) {
-            return createIntegerRange(type);
-        } else {
-            return createGenericRange();
-        }
-    }
-
-    // check that add doesn't overflow
-    private static boolean checkAdd(final long a, final long b) {
-        final long result = a + b;
-        return ((a ^ result) & (b ^ result)) >= 0;
-    }
-
-    // check that sub doesn't overflow
-    private static boolean checkSub(final long a, final long b) {
-        final long result = a - b;
-        return ((a ^ result) & (b ^ result)) >= 0;
-    }
-
-    private static boolean checkMul(final long a, final long b) {
-        // TODO correct overflow check
-        return a >= Integer.MIN_VALUE && a <= Integer.MAX_VALUE && b >= Integer.MIN_VALUE && b <= Integer.MAX_VALUE;
-    }
-
-    /**
-     * The range functionality class responsible for merging ranges and drawing
-     * range conclusions from operations executed
-     */
-    public static class Functionality {
-        /** logger */
-        protected final DebugLogger log;
-
-        /**
-         * Constructor
-         * @param log logger
-         */
-        public Functionality(final DebugLogger log) {
-            this.log = log;
-        }
-
-        /**
-         * Join two ranges
-         * @param a first range
-         * @param b second range
-         * @return the joined range
-         */
-        public Range join(final Range a, final Range b) {
-            if (a.equals(b)) {
-                return a;
-            }
-
-            Type joinedType = a.getType();
-            if (a.getType() != b.getType()) {
-                if (a.isUnknown()) {
-                    return b;
-                }
-                if (b.isUnknown()) {
-                    return a;
-                }
-
-                joinedType = Type.widest(a.getType(), b.getType());
-            }
-
-            if (joinedType.isInteger() || joinedType.isLong()) {
-                return createIntegerRange(
-                        Math.min(((IntegerRange) a).getMin(), ((IntegerRange) b).getMin()),
-                        Math.max(((IntegerRange) a).getMax(), ((IntegerRange) b).getMax()));
-            }
-
-            return createTypeRange(joinedType);
-        }
-
-        /**
-         * Add operation
-         * @param a range of first symbol to be added
-         * @param b range of second symbol to be added
-         * @return resulting range representing the value range after add
-         */
-        public Range add(final Range a, final Range b) {
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final IntegerRange lhs = (IntegerRange)a;
-                final IntegerRange rhs = (IntegerRange)b;
-                if (checkAdd(lhs.getMin(), rhs.getMin()) && checkAdd(lhs.getMax(), rhs.getMax())) {
-                    return createIntegerRange(lhs.getMin() + rhs.getMin(), lhs.getMax() + rhs.getMax());
-                }
-            }
-
-            if (a.getType().isNumeric() && b.getType().isNumeric()) {
-                return createNumberRange();
-            }
-
-            return createGenericRange();
-        }
-
-        /**
-         * Sub operation
-         * @param a range of first symbol to be subtracted
-         * @param b range of second symbol to be subtracted
-         * @return resulting range representing the value range after subtraction
-         */
-        public Range sub(final Range a, final Range b) {
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final IntegerRange lhs = (IntegerRange)a;
-                final IntegerRange rhs = (IntegerRange)b;
-                if (checkSub(lhs.getMin(), rhs.getMax()) && checkSub(lhs.getMax(), rhs.getMin())) {
-                    return createIntegerRange(lhs.getMin() - rhs.getMax(), lhs.getMax() - rhs.getMin());
-                }
-            }
-
-            if (a.getType().isNumeric() && b.getType().isNumeric()) {
-                return createNumberRange();
-            }
-
-            return createGenericRange();
-        }
-
-        /**
-         * Mul operation
-         * @param a range of first symbol to be multiplied
-         * @param b range of second symbol to be multiplied
-         * @return resulting range representing the value range after multiplication
-         */
-        public Range mul(final Range a, final Range b) {
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final IntegerRange lhs = (IntegerRange)a;
-                final IntegerRange rhs = (IntegerRange)b;
-
-                //ensure that nothing ever overflows or underflows
-                if (checkMul(lhs.getMin(), rhs.getMin()) &&
-                    checkMul(lhs.getMax(), rhs.getMax()) &&
-                    checkMul(lhs.getMin(), rhs.getMax()) &&
-                    checkMul(lhs.getMax(), rhs.getMin())) {
-
-                    final List<Long> results =
-                        Arrays.asList(
-                            lhs.getMin() * rhs.getMin(),
-                            lhs.getMin() * rhs.getMax(),
-                            lhs.getMax() * rhs.getMin(),
-                            lhs.getMax() * rhs.getMax());
-                    return createIntegerRange(Collections.min(results), Collections.max(results));
-                }
-            }
-
-            if (a.getType().isNumeric() && b.getType().isNumeric()) {
-                return createNumberRange();
-            }
-
-            return createGenericRange();
-        }
-
-        /**
-         * Neg operation
-         * @param a range of value symbol to be negated
-         * @return resulting range representing the value range after neg
-         */
-        public Range neg(final Range a) {
-            if (a.isIntegerType()) {
-                final IntegerRange rhs = (IntegerRange)a;
-                if (rhs.getMin() != Long.MIN_VALUE && rhs.getMax() != Long.MIN_VALUE) {
-                    return createIntegerRange(-rhs.getMax(), -rhs.getMin());
-                }
-            }
-
-            if (a.getType().isNumeric()) {
-                return createNumberRange();
-            }
-
-            return createGenericRange();
-        }
-
-        /**
-         * Bitwise and operation
-         * @param a range of first symbol to be and:ed
-         * @param b range of second symbol to be and:ed
-         * @return resulting range representing the value range after and
-         */
-        public Range and(final Range a, final Range b) {
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final int resultMask = (int) (((IntegerRange)a).getBitMask() & ((IntegerRange)b).getBitMask());
-                if (resultMask >= 0) {
-                    return createIntegerRange(0, resultMask);
-                }
-            } else if (a.isUnknown() && b.isIntegerType()) {
-                final long operandMask = ((IntegerRange)b).getBitMask();
-                if (operandMask >= 0) {
-                    return createIntegerRange(0, operandMask);
-                }
-            } else if (a.isIntegerType() && b.isUnknown()) {
-                final long operandMask = ((IntegerRange)a).getBitMask();
-                if (operandMask >= 0) {
-                    return createIntegerRange(0, operandMask);
-                }
-            }
-
-            return createTypeRange(Type.INT);
-        }
-
-        /**
-         * Bitwise or operation
-         * @param a range of first symbol to be or:ed
-         * @param b range of second symbol to be or:ed
-         * @return resulting range representing the value range after or
-         */
-        public Range or(final Range a, final Range b) {
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
-                if (resultMask >= 0) {
-                    return createIntegerRange(0, resultMask);
-                }
-            }
-
-            return createTypeRange(Type.INT);
-        }
-
-        /**
-         * Bitwise xor operation
-         * @param a range of first symbol to be xor:ed
-         * @param b range of second symbol to be xor:ed
-         * @return resulting range representing the value range after and
-         */
-        public Range xor(final Range a, final Range b) {
-            if (a.isIntegerConst() && b.isIntegerConst()) {
-                return createRange(((IntegerRange)a).getMin() ^ ((IntegerRange)b).getMin());
-            }
-
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final int resultMask = (int)(((IntegerRange)a).getBitMask() | ((IntegerRange)b).getBitMask());
-                if (resultMask >= 0) {
-                    return createIntegerRange(0, createIntegerRange(0, resultMask).getBitMask());
-                }
-            }
-            return createTypeRange(Type.INT);
-        }
-
-        /**
-         * Bitwise shl operation
-         * @param a range of first symbol to be shl:ed
-         * @param b range of second symbol to be shl:ed
-         * @return resulting range representing the value range after shl
-         */
-        public Range shl(final Range a, final Range b) {
-            if (b.isIntegerType() && b.isIntegerConst()) {
-                final IntegerRange left  = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
-                final int          shift = (int)((IntegerRange) b).getMin() & 0x1f;
-                final int          min   = (int)left.getMin() << shift;
-                final int          max   = (int)left.getMax() << shift;
-                if (min >> shift == left.getMin() && max >> shift == left.getMax()) {
-                    return createIntegerRange(min, max);
-                }
-            }
-
-            return createTypeRange(Type.INT);
-        }
-
-        /**
-         * Bitwise shr operation
-         * @param a range of first symbol to be shr:ed
-         * @param b range of second symbol to be shr:ed
-         * @return resulting range representing the value range after shr
-         */
-        public Range shr(final Range a, final Range b) {
-            if (b.isIntegerType() && b.isIntegerConst()) {
-                final long         shift = ((IntegerRange) b).getMin() & 0x1f;
-                final IntegerRange left  = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
-                if (left.getMin() >= 0) {
-                    long min = left.getMin() >>> shift;
-                    long max = left.getMax() >>> shift;
-                    return createIntegerRange(min, max);
-                } else if (shift >= 1) {
-                    return createIntegerRange(0, JSType.MAX_UINT >>> shift);
-                }
-            }
-
-            return createTypeRange(Type.INT);
-        }
-
-        /**
-         * Bitwise sar operation
-         * @param a range of first symbol to be sar:ed
-         * @param b range of second symbol to be sar:ed
-         * @return resulting range representing the value range after sar
-         */
-        public Range sar(final Range a, final Range b) {
-            if (b.isIntegerType() && b.isIntegerConst()) {
-                final IntegerRange left  = (IntegerRange)(a.isIntegerType() ? a : createTypeRange(Type.INT));
-                final long         shift = ((IntegerRange) b).getMin() & 0x1f;
-                final long         min   = left.getMin() >> shift;
-                final long         max   = left.getMax() >> shift;
-                return createIntegerRange(min, max);
-            }
-
-            return createTypeRange(Type.INT);
-        }
-
-        /**
-         * Modulo operation
-         * @param a range of first symbol to the mod operation
-         * @param b range of second symbol to be mod operation
-         * @return resulting range representing the value range after mod
-         */
-        public Range mod(final Range a, final Range b) {
-            if (a.isIntegerType() && b.isIntegerType()) {
-                final IntegerRange rhs = (IntegerRange) b;
-                if (rhs.getMin() > 0 || rhs.getMax() < 0) { // divisor range must not include 0
-                    final long absmax = Math.max(Math.abs(rhs.getMin()), Math.abs(rhs.getMax())) - 1;
-                    return createIntegerRange(rhs.getMin() > 0 ? 0 : -absmax, rhs.getMax() < 0 ? 0 : +absmax);
-                }
-            }
-            return createTypeRange(Type.NUMBER);
-        }
-
-        /**
-         * Division operation
-         * @param a range of first symbol to the division
-         * @param b range of second symbol to be division
-         * @return resulting range representing the value range after division
-         */
-        public Range div(final Range a, final Range b) {
-            // TODO
-            return createTypeRange(Type.NUMBER);
-        }
-    }
-
-    /**
-     * Simple trace functionality that will log range creation
-     */
-    public static class TraceFunctionality extends Functionality {
-        TraceFunctionality(final DebugLogger log) {
-            super(log);
-        }
-
-        private Range trace(final Range result, final String operation, final Range... operands) {
-            log.fine("range::" + operation + Arrays.toString(operands) + " => " + result);
-            return result;
-        }
-
-        @Override
-        public Range join(final Range a, final Range b) {
-            final Range result = super.join(a, b);
-            if (!a.equals(b)) {
-                trace(result, "join", a, b);
-            }
-            return result;
-        }
-
-        @Override
-        public Range add(final Range a, final Range b) {
-            return trace(super.add(a, b), "add", a, b);
-        }
-
-        @Override
-        public Range sub(final Range a, final Range b) {
-            return trace(super.sub(a, b), "sub", a, b);
-        }
-
-        @Override
-        public Range mul(final Range a, final Range b) {
-            return trace(super.mul(a, b), "mul", a, b);
-        }
-
-        @Override
-        public Range neg(final Range a) {
-            return trace(super.neg(a), "neg", a);
-        }
-
-        @Override
-        public Range and(final Range a, final Range b) {
-            return trace(super.and(a, b), "and", a, b);
-        }
-
-        @Override
-        public Range or(final Range a, final Range b) {
-            return trace(super.or(a, b), "or", a, b);
-        }
-
-        @Override
-        public Range xor(final Range a, final Range b) {
-            return trace(super.xor(a, b), "xor", a, b);
-        }
-
-        @Override
-        public Range shl(final Range a, final Range b) {
-            return trace(super.shl(a, b), "shl", a, b);
-        }
-
-        @Override
-        public Range shr(final Range a, final Range b) {
-            return trace(super.shr(a, b), "shr", a, b);
-        }
-
-        @Override
-        public Range sar(final Range a, final Range b) {
-            return trace(super.sar(a, b), "sar", a, b);
-        }
-
-        @Override
-        public Range mod(final Range a, final Range b) {
-            return trace(super.mod(a, b), "mod", a, b);
-        }
-
-        @Override
-        public Range div(final Range a, final Range b) {
-            return trace(super.div(a, b), "div", a, b);
-        }
-    }
-
-    @Override
-    public String toString() {
-        return String.valueOf(getType());
-    }
-
-    @SuppressWarnings("unused")
-    private static boolean isRepresentableAsInt(final double number) {
-        return (int)number == number && !isNegativeZero(number);
-    }
-
-    private static boolean isRepresentableAsLong(final double number) {
-        return (long)number == number && !isNegativeZero(number);
-    }
-
-    private static boolean isNegativeZero(final double number) {
-        return Double.doubleToLongBits(number) == Double.doubleToLongBits(-0.0);
-    }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
index 4799c26..a1db3b7 100644
--- a/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
+++ b/nashorn/src/jdk/nashorn/internal/codegen/types/Type.java
@@ -33,6 +33,7 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.DUP2_X2;
 import static jdk.internal.org.objectweb.asm.Opcodes.DUP_X1;
 import static jdk.internal.org.objectweb.asm.Opcodes.DUP_X2;
+import static jdk.internal.org.objectweb.asm.Opcodes.H_INVOKESTATIC;
 import static jdk.internal.org.objectweb.asm.Opcodes.IALOAD;
 import static jdk.internal.org.objectweb.asm.Opcodes.IASTORE;
 import static jdk.internal.org.objectweb.asm.Opcodes.INVOKESTATIC;
@@ -45,13 +46,25 @@
 import static jdk.internal.org.objectweb.asm.Opcodes.T_DOUBLE;
 import static jdk.internal.org.objectweb.asm.Opcodes.T_INT;
 import static jdk.internal.org.objectweb.asm.Opcodes.T_LONG;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
 
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.lang.invoke.CallSite;
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Map;
+import java.util.TreeMap;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import jdk.internal.org.objectweb.asm.Handle;
 import jdk.internal.org.objectweb.asm.MethodVisitor;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.Undefined;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
 /**
  * This is the representation of a JavaScript type, disassociated from java
@@ -97,6 +110,10 @@
     /** Set way below Integer.MAX_VALUE to prevent overflow when adding weights. Objects are still heaviest. */
     protected static final int MAX_WEIGHT = 20;
 
+    static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "mathBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class, int.class);
+
+    static final Handle MATHBOOTSTRAP = new Handle(H_INVOKESTATIC, BOOTSTRAP.className(), "mathBootstrap", BOOTSTRAP.descriptor());
+
     /**
      * Constructor
      *
@@ -149,6 +166,17 @@
     }
 
     /**
+     * Returns the character describing the bytecode type for this value on the stack or local variable, identical to
+     * what would be used as the prefix for a bytecode {@code LOAD} or {@code STORE} instruction, therefore it must be
+     * one of {@code A, F, D, I, L}. Also, the special value {@code U} is used for local variable slots that haven't
+     * been initialized yet (it can't appear for a value pushed to the operand stack, those always have known values).
+     * Note that while we allow all JVM internal types, Nashorn doesn't necessarily use them all - currently we don't
+     * have floats, only doubles, but that might change in the future.
+     * @return the character describing the bytecode type for this value on the stack.
+     */
+    public abstract char getBytecodeStackType();
+
+    /**
      * Generate a method descriptor given a return type and a param array
      *
      * @param returnType return type
@@ -181,6 +209,20 @@
     }
 
     /**
+     * Return a character representing {@code type} in a method signature.
+     *
+     * @param type parameter type
+     * @return descriptor character
+     */
+    public static char getShortSignatureDescriptor(final Type type) {
+        // Use 'Z' for boolean parameters as we need to distinguish from int
+        if (type instanceof BooleanType) {
+            return 'Z';
+        }
+        return type.getBytecodeStackType();
+    }
+
+    /**
      * Return the type for an internal type, package private - do not use
      * outside code gen
      *
@@ -199,7 +241,11 @@
         case jdk.internal.org.objectweb.asm.Type.DOUBLE:
             return NUMBER;
         case jdk.internal.org.objectweb.asm.Type.OBJECT:
-            return OBJECT;
+            try {
+                return Type.typeFor(Class.forName(itype.getClassName()));
+            } catch(final ClassNotFoundException e) {
+                throw new AssertionError(e);
+            }
         case jdk.internal.org.objectweb.asm.Type.VOID:
             return null;
         case jdk.internal.org.objectweb.asm.Type.ARRAY:
@@ -248,6 +294,64 @@
         return types;
     }
 
+    /**
+     * Write a map of {@code int} to {@code Type} to an output stream. This is used to store deoptimization state.
+     *
+     * @param typeMap the type map
+     * @param output data output
+     * @throws IOException
+     */
+    public static void writeTypeMap(final Map<Integer, Type> typeMap, final DataOutput output) throws IOException {
+        if (typeMap == null) {
+            output.writeInt(0);
+        } else {
+            output.writeInt(typeMap.size());
+            for(final Map.Entry<Integer, Type> e: typeMap.entrySet()) {
+                output.writeInt(e.getKey());
+                final byte typeChar;
+                final Type type = e.getValue();
+                if(type == Type.OBJECT) {
+                    typeChar = 'L';
+                } else if (type == Type.NUMBER) {
+                    typeChar = 'D';
+                } else if (type == Type.LONG) {
+                    typeChar = 'J';
+                } else {
+                    throw new AssertionError();
+                }
+                output.writeByte(typeChar);
+            }
+        }
+    }
+
+    /**
+     * Read a map of {@code int} to {@code Type} from an input stream. This is used to store deoptimization state.
+     *
+     * @param input data input
+     * @return type map
+     * @throws IOException
+     */
+    public static Map<Integer, Type> readTypeMap(final DataInput input) throws IOException {
+        final int size = input.readInt();
+        if (size == 0) {
+            return null;
+        }
+        final Map<Integer, Type> map = new TreeMap<>();
+        for(int i = 0; i < size; ++i) {
+            final int pp = input.readInt();
+            final int typeChar = input.readByte();
+            final Type type;
+            switch(typeChar) {
+                case 'L': type = Type.OBJECT; break;
+                case 'D': type = Type.NUMBER; break;
+                case 'J': type = Type.LONG; break;
+                default: throw new AssertionError();
+            }
+            map.put(pp, type);
+        }
+        return map;
+    }
+
     static jdk.internal.org.objectweb.asm.Type getInternalType(final String className) {
         return jdk.internal.org.objectweb.asm.Type.getType(className);
     }
@@ -260,7 +364,7 @@
         return jdk.internal.org.objectweb.asm.Type.getType(type);
     }
 
-    static void invokeStatic(final MethodVisitor method, final Call call) {
+    static void invokestatic(final MethodVisitor method, final Call call) {
         method.visitMethodInsn(INVOKESTATIC, call.className(), call.name(), call.descriptor(), false);
     }
 
@@ -373,6 +477,14 @@
     }
 
     /**
+     * Is this a primitive type (e.g int, long, double, boolean)
+     * @return true if primitive
+     */
+    public boolean isPrimitive() {
+        return !isObject();
+    }
+
+    /**
      * Determines whether a type is a STRING type
      *
      * @return true if object type, false otherwise
@@ -382,6 +494,15 @@
     }
 
     /**
+     * Determines whether a type is a CHARSEQUENCE type used internally strings
+     *
+     * @return true if CharSequence (internal string) type, false otherwise
+     */
+    public boolean isCharSequence() {
+        return this.equals(Type.CHARSEQUENCE);
+    }
+
+    /**
      * Determine if two types are equivalent, i.e. need no conversion
      *
      * @param type the second type to check
@@ -389,7 +510,7 @@
      * @return true if types are equivalent, false otherwise
      */
     public boolean isEquivalentTo(final Type type) {
-        return this.weight() == type.weight() || (isObject() && type.isObject());
+        return this.weight() == type.weight() || isObject() && type.isObject();
     }
 
     /**
@@ -462,6 +583,37 @@
     }
 
     /**
+     * When doing widening for return types of a function or a ternary operator, it is not valid to widen a boolean to
+     * anything other than object. Note that this wouldn't be necessary if {@code Type.widest} did not allow
+     * boolean-to-number widening. Eventually, we should address it there, but it affects too many other parts of the
+     * system and is sometimes legitimate (e.g. whenever a boolean value would undergo ToNumber conversion anyway).
+     * @param t1 type 1
+     * @param t2 type 2
+     * @return wider of t1 and t2, except if one is boolean and the other is neither boolean nor unknown, in which case
+     * {@code Type.OBJECT} is returned.
+     */
+    public static Type widestReturnType(final Type t1, final Type t2) {
+        if (t1.isUnknown()) {
+            return t2;
+        } else if (t2.isUnknown()) {
+            return t1;
+        } else if(t1.isBoolean() != t2.isBoolean() || t1.isNumeric() != t2.isNumeric()) {
+            return Type.OBJECT;
+        }
+        return Type.widest(t1, t2);
+    }
+
+    /**
+     * Returns a generic version of the type. Basically, if the type {@link #isObject()}, returns {@link #OBJECT},
+     * otherwise returns the type unchanged.
+     * @param type the type to generify
+     * @return the generified type
+     */
+    public static Type generic(final Type type) {
+        return type.isObject() ? Type.OBJECT : type;
+    }
+
+    /**
      * Returns the narrowest or least common of two types
      *
      * @param type0 type one
@@ -470,7 +622,25 @@
      * @return the widest type
      */
     public static Type narrowest(final Type type0, final Type type1) {
-        return type0.weight() < type1.weight() ? type0 : type1;
+        return type0.narrowerThan(type1) ? type0 : type1;
+    }
+
+    /**
+     * Check whether this type is strictly narrower than another one
+     * @param type type to check against
+     * @return true if this type is strictly narrower
+     */
+    public boolean narrowerThan(final Type type) {
+        return weight() < type.weight();
+    }
+
+    /**
+     * Check whether this type is strictly wider than another one
+     * @param type type to check against
+     * @return true if this type is strictly wider
+     */
+    public boolean widerThan(final Type type) {
+        return weight() > type.weight();
     }
 
     /**
@@ -549,6 +719,16 @@
         return descriptor;
     }
 
+    /**
+     * Return the descriptor of a type, short version
+     * Used mainly for debugging purposes
+     *
+     * @return the short descriptor
+     */
+    public String getShortDescriptor() {
+        return descriptor;
+    }
+
     @Override
     public String toString() {
         return name;
@@ -688,17 +868,17 @@
     /**
      * This is an integer type, i.e INT, INT32.
      */
-    public static final Type INT = putInCache(new IntType());
+    public static final BitwiseType INT = putInCache(new IntType());
 
     /**
      * This is the number singleton, used for all number types
      */
-    public static final Type NUMBER = putInCache(new NumberType());
+    public static final NumericType NUMBER = putInCache(new NumberType());
 
     /**
      * This is the long singleton, used for all long types
      */
-    public static final Type LONG = putInCache(new LongType());
+    public static final BitwiseType LONG = putInCache(new LongType());
 
     /**
      * A string singleton
@@ -706,11 +886,28 @@
     public static final Type STRING = putInCache(new ObjectType(String.class));
 
     /**
+     * This is the CharSequence singleton used to represent JS strings internally
+     * (either a {@code java.lang.String} or {@code jdk.nashorn.internal.runtime.ConsString}.
+     */
+    public static final Type CHARSEQUENCE = putInCache(new ObjectType(CharSequence.class));
+
+
+    /**
      * This is the object singleton, used for all object types
      */
     public static final Type OBJECT = putInCache(new ObjectType());
 
     /**
+     * A undefined singleton
+     */
+    public static final Type UNDEFINED = putInCache(new ObjectType(Undefined.class));
+
+    /**
+     * This is the singleton for ScriptObjects
+     */
+    public static final Type SCRIPT_OBJECT = putInCache(new ObjectType(ScriptObject.class));
+
+    /**
      * This is the singleton for integer arrays
      */
     public static final ArrayType INT_ARRAY = new ArrayType(int[].class) {
@@ -820,59 +1017,87 @@
         // EMPTY - used as a class that is absolutely not compatible with a type to represent "unknown"
     }
 
+    private abstract static class ValueLessType extends Type {
+
+        ValueLessType(final String name) {
+            super(name, Unknown.class, MIN_WEIGHT, 1);
+        }
+
+        @Override
+        public Type load(final MethodVisitor method, final int slot) {
+            throw new UnsupportedOperationException("load " + slot);
+        }
+
+        @Override
+        public void store(final MethodVisitor method, final int slot) {
+            throw new UnsupportedOperationException("store " + slot);
+        }
+
+        @Override
+        public Type ldc(final MethodVisitor method, final Object c) {
+            throw new UnsupportedOperationException("ldc " + c);
+        }
+
+        @Override
+        public Type loadUndefined(final MethodVisitor method) {
+            throw new UnsupportedOperationException("load undefined");
+        }
+
+        @Override
+        public Type loadForcedInitializer(final MethodVisitor method) {
+            throw new UnsupportedOperationException("load forced initializer");
+        }
+
+        @Override
+        public Type convert(final MethodVisitor method, final Type to) {
+            throw new UnsupportedOperationException("convert => " + to);
+        }
+
+        @Override
+        public void _return(final MethodVisitor method) {
+            throw new UnsupportedOperationException("return");
+       }
+
+        @Override
+        public Type add(final MethodVisitor method, final int programPoint) {
+            throw new UnsupportedOperationException("add");
+        }
+    }
+
     /**
      * This is the unknown type which is used as initial type for type
      * inference. It has the minimum type width
      */
-    public static final Type UNKNOWN = new Type("<unknown>", Unknown.class, MIN_WEIGHT, 1) {
-
+    public static final Type UNKNOWN = new ValueLessType("<unknown>") {
         @Override
         public String getDescriptor() {
             return "<unknown>";
         }
 
         @Override
-        public Type load(final MethodVisitor method, final int slot) {
-            assert false : "unsupported operation";
-            return null;
-        }
-
-        @Override
-        public void store(final MethodVisitor method, final int slot) {
-            assert false : "unsupported operation";
-        }
-
-        @Override
-        public Type ldc(final MethodVisitor method, final Object c) {
-            assert false : "unsupported operation";
-            return null;
-        }
-
-        @Override
-        public Type loadUndefined(final MethodVisitor method) {
-            assert false : "unsupported operation";
-            return null;
-        }
-
-        @Override
-        public Type convert(final MethodVisitor method, final Type to) {
-            assert false : "unsupported operation";
-            return null;
-        }
-
-        @Override
-        public void _return(final MethodVisitor method) {
-            assert false : "unsupported operation";
-        }
-
-        @Override
-        public Type add(final MethodVisitor method) {
-            assert false : "unsupported operation";
-            return null;
+        public char getBytecodeStackType() {
+            return 'U';
         }
     };
 
-    private static <T extends Type> T putInCache(T type) {
+    /**
+     * This is the unknown type which is used as initial type for type
+     * inference. It has the minimum type width
+     */
+    public static final Type SLOT_2 = new ValueLessType("<slot_2>") {
+
+        @Override
+        public String getDescriptor() {
+            return "<slot_2>";
+        }
+
+        @Override
+        public char getBytecodeStackType() {
+            throw new UnsupportedOperationException("getBytecodeStackType");
+        }
+    };
+
+    private static <T extends Type> T putInCache(final T type) {
         cache.put(type.getTypeClass(), type);
         return type;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java
index 957adf6..b354c1f 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/AccessNode.java
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.ir;
 
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -33,8 +34,8 @@
  */
 @Immutable
 public final class AccessNode extends BaseNode {
-    /** Property ident. */
-    private final IdentNode property;
+    /** Property name. */
+    private final String property;
 
     /**
      * Constructor
@@ -44,13 +45,13 @@
      * @param base      base node
      * @param property  property
      */
-    public AccessNode(final long token, final int finish, final Expression base, final IdentNode property) {
+    public AccessNode(final long token, final int finish, final Expression base, final String property) {
         super(token, finish, base, false);
-        this.property = property.setIsPropertyName();
+        this.property = property;
     }
 
-    private AccessNode(final AccessNode accessNode, final Expression base, final IdentNode property, final boolean isFunction) {
-        super(accessNode, base, isFunction);
+    private AccessNode(final AccessNode accessNode, final Expression base, final String property, final boolean isFunction, final Type type, final int id) {
+        super(accessNode, base, isFunction, type, id);
         this.property = property;
     }
 
@@ -62,36 +63,39 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterAccessNode(this)) {
             return visitor.leaveAccessNode(
-                setBase((Expression)base.accept(visitor)).
-                setProperty((IdentNode)property.accept(visitor)));
+                setBase((Expression)base.accept(visitor)));
         }
         return this;
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         final boolean needsParen = tokenType().needsParens(getBase().tokenType(), true);
 
+        if (printType) {
+            optimisticTypeToString(sb);
+        }
+
         if (needsParen) {
             sb.append('(');
         }
 
-        base.toString(sb);
+        base.toString(sb, printType);
 
         if (needsParen) {
             sb.append(')');
         }
         sb.append('.');
 
-        sb.append(property.getName());
+        sb.append(property);
     }
 
     /**
-     * Get the property
+     * Get the property name
      *
-     * @return the property IdentNode
+     * @return the property name
      */
-    public IdentNode getProperty() {
+    public String getProperty() {
         return property;
     }
 
@@ -99,22 +103,30 @@
         if (this.base == base) {
             return this;
         }
-        return new AccessNode(this, base, property, isFunction());
-    }
-
-    private AccessNode setProperty(final IdentNode property) {
-        if (this.property == property) {
-            return this;
-        }
-        return new AccessNode(this, base, property, isFunction());
+        return new AccessNode(this, base, property, isFunction(), type, programPoint);
     }
 
     @Override
-    public BaseNode setIsFunction() {
+    public AccessNode setType(final Type type) {
+        if (this.type == type) {
+            return this;
+        }
+        return new AccessNode(this, base, property, isFunction(), type, programPoint);
+    }
+
+    @Override
+    public AccessNode setProgramPoint(final int programPoint) {
+        if (this.programPoint == programPoint) {
+            return this;
+        }
+        return new AccessNode(this, base, property, isFunction(), type, programPoint);
+    }
+
+    @Override
+    public AccessNode setIsFunction() {
         if (isFunction()) {
             return this;
         }
-        return new AccessNode(this, base, property, true);
+        return new AccessNode(this, base, property, true, type, programPoint);
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java b/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java
index 96f155d..160833e 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BaseNode.java
@@ -25,6 +25,10 @@
 
 package jdk.nashorn.internal.ir;
 
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 
 /**
@@ -34,13 +38,19 @@
  * @see IndexNode
  */
 @Immutable
-public abstract class BaseNode extends Expression implements FunctionCall {
+public abstract class BaseNode extends Expression implements FunctionCall, Optimistic {
 
     /** Base Node. */
     protected final Expression base;
 
     private final boolean isFunction;
 
+    /** Callsite type for this node, if overridden optimistically or conservatively depending on coercion */
+    protected final Type type;
+
+    /** Program point id */
+    protected final int programPoint;
+
     /**
      * Constructor
      *
@@ -51,8 +61,10 @@
      */
     public BaseNode(final long token, final int finish, final Expression base, final boolean isFunction) {
         super(token, base.getStart(), finish);
-        this.base            = base;
-        this.isFunction      = isFunction;
+        this.base           = base;
+        this.isFunction     = isFunction;
+        this.type = null;
+        this.programPoint   = INVALID_PROGRAM_POINT;
     }
 
     /**
@@ -60,11 +72,15 @@
      * @param baseNode node to inherit from
      * @param base base
      * @param isFunction is this a function
+     * @param callSiteType  the callsite type for this base node, either optimistic or conservative
+     * @param programPoint  program point id
      */
-    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction) {
+    protected BaseNode(final BaseNode baseNode, final Expression base, final boolean isFunction, final Type callSiteType, final int programPoint) {
         super(baseNode);
-        this.base            = base;
-        this.isFunction      = isFunction;
+        this.base           = base;
+        this.isFunction     = isFunction;
+        this.type = callSiteType;
+        this.programPoint   = programPoint;
     }
 
     /**
@@ -80,6 +96,31 @@
         return isFunction;
     }
 
+    @Override
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        return type == null ? getMostPessimisticType() : type;
+    }
+
+    @Override
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    @Override
+    public Type getMostOptimisticType() {
+        return Type.INT;
+    }
+
+    @Override
+    public Type getMostPessimisticType() {
+        return Type.OBJECT;
+    }
+
+    @Override
+    public boolean canBeOptimistic() {
+        return true;
+    }
+
     /**
      * Mark this node as being the callee operand of a {@link CallNode}.
      * @return a base node identical to this one in all aspects except with its function flag set.
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
index 0a1d1bf..f32f632 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BinaryNode.java
@@ -25,7 +25,15 @@
 
 package jdk.nashorn.internal.ir;
 
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.TokenType;
@@ -34,12 +42,38 @@
  * BinaryNode nodes represent two operand operations.
  */
 @Immutable
-public final class BinaryNode extends Expression implements Assignment<Expression> {
+public final class BinaryNode extends Expression implements Assignment<Expression>, Optimistic {
+    // Placeholder for "undecided optimistic ADD type". Unfortunately, we can't decide the type of ADD during optimistic
+    // type calculation as it can have local variables as its operands that will decide its ultimate type.
+    private static final Type OPTIMISTIC_UNDECIDED_TYPE = Type.typeFor(new Object(){/*empty*/}.getClass());
+
     /** Left hand side argument. */
     private final Expression lhs;
 
     private final Expression rhs;
 
+    private final int programPoint;
+
+    private final Type type;
+
+    private Type cachedType;
+    private Object cachedTypeFunction;
+
+    @Ignore
+    private static final Set<TokenType> CAN_OVERFLOW =
+        Collections.unmodifiableSet(new HashSet<>(Arrays.asList(new TokenType[] {
+                TokenType.ADD,
+                TokenType.DIV,
+                TokenType.MOD,
+                TokenType.MUL,
+                TokenType.SUB,
+                TokenType.ASSIGN_ADD,
+                TokenType.ASSIGN_DIV,
+                TokenType.ASSIGN_MOD,
+                TokenType.ASSIGN_MUL,
+                TokenType.ASSIGN_SUB
+            })));
+
     /**
      * Constructor
      *
@@ -49,17 +83,25 @@
      */
     public BinaryNode(final long token, final Expression lhs, final Expression rhs) {
         super(token, lhs.getStart(), rhs.getFinish());
+        assert !(isTokenType(TokenType.AND) || isTokenType(TokenType.OR)) || lhs instanceof JoinPredecessorExpression;
         this.lhs   = lhs;
         this.rhs   = rhs;
+        this.programPoint = INVALID_PROGRAM_POINT;
+        this.type = null;
     }
 
-    private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs) {
+    private BinaryNode(final BinaryNode binaryNode, final Expression lhs, final Expression rhs, final Type type, final int programPoint) {
         super(binaryNode);
         this.lhs = lhs;
         this.rhs = rhs;
+        this.programPoint = programPoint;
+        this.type = type;
     }
 
-    @Override
+    /**
+     * Returns true if the node is a comparison operation.
+     * @return true if the node is a comparison operation.
+     */
     public boolean isComparison() {
         switch (tokenType()) {
         case EQ:
@@ -77,6 +119,36 @@
     }
 
     /**
+     * Returns true if the node is a logical operation.
+     * @return true if the node is a logical operation.
+     */
+    public boolean isLogical() {
+        return isLogical(tokenType());
+    }
+
+    /**
+     * Returns true if the token type represents a logical operation.
+     * @param tokenType the token type
+     * @return true if the token type represents a logical operation.
+     */
+    public static boolean isLogical(final TokenType tokenType) {
+        switch (tokenType) {
+        case AND:
+        case OR:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
+        @Override
+        public Type apply(final Symbol t) {
+            return null;
+        }
+    };
+
+    /**
      * Return the widest possible type for this operation. This is used for compile time
      * static type inference
      *
@@ -84,9 +156,62 @@
      */
     @Override
     public Type getWidestOperationType() {
+        return getWidestOperationType(UNKNOWN_LOCALS);
+    }
+
+    /**
+     * Return the widest possible operand type for this operation.
+     *
+     * @return Type
+     */
+    public Type getWidestOperandType() {
         switch (tokenType()) {
         case SHR:
         case ASSIGN_SHR:
+            return Type.INT;
+        case INSTANCEOF:
+            return Type.OBJECT;
+        default:
+            if (isComparison()) {
+                return Type.OBJECT;
+            }
+            return getWidestOperationType();
+        }
+    }
+
+    private Type getWidestOperationType(final Function<Symbol, Type> localVariableTypes) {
+        switch (tokenType()) {
+        case ADD:
+        case ASSIGN_ADD: {
+            // Compare this logic to decideType(Type, Type); it's similar, but it handles the optimistic type
+            // calculation case while this handles the conservative case.
+            final Type lhsType = lhs.getType(localVariableTypes);
+            final Type rhsType = rhs.getType(localVariableTypes);
+            if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) {
+                // Will always fit in an int, as the value range is [0, 1, 2]. If we didn't treat them specially here,
+                // they'd end up being treated as generic INT operands and their sum would be conservatively considered
+                // to be a LONG in the generic case below; we can do better here.
+                return Type.INT;
+            } else if(isString(lhsType) || isString(rhsType)) {
+                // We can statically figure out that this is a string if either operand is a string. In this case, use
+                // CHARSEQUENCE to prevent it from being proactively flattened.
+                return Type.CHARSEQUENCE;
+            }
+            final Type widestOperandType = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
+            if(widestOperandType == Type.INT) {
+                return Type.LONG;
+            } else if (widestOperandType.isNumeric()) {
+                return Type.NUMBER;
+            }
+            // We pretty much can't know what it will be statically. Must presume OBJECT conservatively, as we can end
+            // up getting either a string or an object when adding something + object, e.g.:
+            // 1 + {} == "1[object Object]", but
+            // 1 + {valueOf: function() { return 2 }} == 3. Also:
+            // 1 + {valueOf: function() { return "2" }} == "12".
+            return Type.OBJECT;
+        }
+        case SHR:
+        case ASSIGN_SHR:
             return Type.LONG;
         case ASSIGN_SAR:
         case ASSIGN_SHL:
@@ -101,20 +226,64 @@
             return Type.INT;
         case DIV:
         case MOD:
+        case ASSIGN_DIV:
+        case ASSIGN_MOD: {
+            // Naively, one might think MOD has the same type as the widest of its operands, this is unfortunately not
+            // true when denominator is zero, so even type(int % int) == double.
+            return Type.NUMBER;
+        }
         case MUL:
         case SUB:
-        case ASSIGN_DIV:
-        case ASSIGN_MOD:
         case ASSIGN_MUL:
-        case ASSIGN_SUB:
+        case ASSIGN_SUB: {
+            final Type lhsType = lhs.getType(localVariableTypes);
+            final Type rhsType = rhs.getType(localVariableTypes);
+            if(lhsType == Type.BOOLEAN && rhsType == Type.BOOLEAN) {
+                return Type.INT;
+            }
+            final Type widestOperandType = Type.widest(booleanToInt(lhsType), booleanToInt(rhsType));
+            if(widestOperandType == Type.INT) {
+                return Type.LONG;
+            }
             return Type.NUMBER;
+        }
+        case VOID: {
+            return Type.UNDEFINED;
+        }
+        case ASSIGN: {
+            return rhs.getType(localVariableTypes);
+        }
+        case INSTANCEOF: {
+            return Type.BOOLEAN;
+        }
+        case COMMALEFT: {
+            return lhs.getType(localVariableTypes);
+        }
+        case COMMARIGHT: {
+            return rhs.getType(localVariableTypes);
+        }
         default:
+            if (isComparison()) {
+                return Type.BOOLEAN;
+            }
             return Type.OBJECT;
         }
     }
 
+    private static boolean isString(final Type type) {
+        return type == Type.STRING || type == Type.CHARSEQUENCE;
+    }
+
+    private static Type booleanToInt(final Type type) {
+        return type == Type.BOOLEAN ? Type.INT : type;
+    }
+
+    private static Type undefinedToNumber(final Type type) {
+        return type == Type.UNDEFINED ? Type.NUMBER : type;
+    }
+
     /**
-     * Check if this node is an assigment
+     * Check if this node is an assignment
      *
      * @return true if this node assigns a value
      */
@@ -150,7 +319,7 @@
     }
 
     @Override
-    public BinaryNode setAssignmentDest(Expression n) {
+    public BinaryNode setAssignmentDest(final Expression n) {
         return setLHS(n);
     }
 
@@ -166,7 +335,10 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBinaryNode(this)) {
-            return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor)));
+            if(tokenType().isLeftAssociative()) {
+                return visitor.leaveBinaryNode(setLHS((Expression)lhs.accept(visitor)).setRHS((Expression)rhs.accept(visitor)));
+            }
+            return visitor.leaveBinaryNode(setRHS((Expression)rhs.accept(visitor)).setLHS((Expression)lhs.accept(visitor)));
         }
 
         return this;
@@ -209,17 +381,41 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        final TokenType type = tokenType();
+    public boolean isAlwaysFalse() {
+        switch (tokenType()) {
+        case COMMALEFT:
+            return lhs.isAlwaysFalse();
+        case COMMARIGHT:
+            return rhs.isAlwaysFalse();
+        default:
+            return false;
+        }
+    }
 
-        final boolean lhsParen = type.needsParens(lhs().tokenType(), true);
-        final boolean rhsParen = type.needsParens(rhs().tokenType(), false);
+    @Override
+    public boolean isAlwaysTrue() {
+        switch (tokenType()) {
+        case COMMALEFT:
+            return lhs.isAlwaysTrue();
+        case COMMARIGHT:
+            return rhs.isAlwaysTrue();
+        default:
+            return false;
+        }
+    }
+
+    @Override
+    public void toString(final StringBuilder sb, final boolean printType) {
+        final TokenType tokenType = tokenType();
+
+        final boolean lhsParen = tokenType.needsParens(lhs().tokenType(), true);
+        final boolean rhsParen = tokenType.needsParens(rhs().tokenType(), false);
 
         if (lhsParen) {
             sb.append('(');
         }
 
-        lhs().toString(sb);
+        lhs().toString(sb, printType);
 
         if (lhsParen) {
             sb.append(')');
@@ -227,7 +423,7 @@
 
         sb.append(' ');
 
-        switch (type) {
+        switch (tokenType) {
         case COMMALEFT:
             sb.append(",<");
             break;
@@ -239,16 +435,20 @@
             sb.append("++");
             break;
         default:
-            sb.append(type.getName());
+            sb.append(tokenType.getName());
             break;
         }
 
+        if (isOptimistic()) {
+            sb.append(Expression.OPT_IDENTIFIER);
+        }
+
         sb.append(' ');
 
         if (rhsParen) {
             sb.append('(');
         }
-        rhs().toString(sb);
+        rhs().toString(sb, printType);
         if (rhsParen) {
             sb.append(')');
         }
@@ -279,7 +479,7 @@
         if (this.lhs == lhs) {
             return this;
         }
-        return new BinaryNode(this, lhs, rhs);
+        return new BinaryNode(this, lhs, rhs, type, programPoint);
     }
 
     /**
@@ -291,7 +491,104 @@
         if (this.rhs == rhs) {
             return this;
         }
-        return new BinaryNode(this, lhs, rhs);
+        return new BinaryNode(this, lhs, rhs, type, programPoint);
     }
 
+    @Override
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    @Override
+    public boolean canBeOptimistic() {
+        return isTokenType(TokenType.ADD) || (getMostOptimisticType() != getMostPessimisticType());
+    }
+
+    @Override
+    public BinaryNode setProgramPoint(final int programPoint) {
+        if (this.programPoint == programPoint) {
+            return this;
+        }
+        return new BinaryNode(this, lhs, rhs, type, programPoint);
+    }
+
+    @Override
+    public Type getMostOptimisticType() {
+        final TokenType tokenType = tokenType();
+        if(tokenType == TokenType.ADD || tokenType == TokenType.ASSIGN_ADD) {
+            return OPTIMISTIC_UNDECIDED_TYPE;
+        } else if (CAN_OVERFLOW.contains(tokenType())) {
+            return Type.INT;
+        }
+        return getMostPessimisticType();
+    }
+
+    @Override
+    public Type getMostPessimisticType() {
+        return getWidestOperationType();
+    }
+
+    /**
+     * Returns true if the node has the optimistic type of the node is not yet decided. Optimistic ADD nodes start out
+     * as undecided until we can figure out if they're numeric or not.
+     * @return true if the node has the optimistic type of the node is not yet decided.
+     */
+    public boolean isOptimisticUndecidedType() {
+        return type == OPTIMISTIC_UNDECIDED_TYPE;
+    }
+
+    @Override
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        if(localVariableTypes == cachedTypeFunction) {
+            return cachedType;
+        }
+        cachedType = getTypeUncached(localVariableTypes);
+        cachedTypeFunction = localVariableTypes;
+        return cachedType;
+    }
+
+    private Type getTypeUncached(final Function<Symbol, Type> localVariableTypes) {
+        if(type == OPTIMISTIC_UNDECIDED_TYPE) {
+            return decideType(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes));
+        }
+        final Type widest = getWidestOperationType(localVariableTypes);
+        if(type == null) {
+            return widest;
+        }
+        return Type.narrowest(widest, Type.widest(type, Type.widest(lhs.getType(localVariableTypes), rhs.getType(localVariableTypes))));
+    }
+
+    private static Type decideType(final Type lhsType, final Type rhsType) {
+        // Compare this to getWidestOperationType() for ADD and ASSIGN_ADD cases. There's some similar logic, but these
+        // are optimistic decisions, meaning that we don't have to treat boolean addition separately (as it'll become
+        // int addition in the general case anyway), and that we also don't conservatively widen sums of ints to
+        // longs, or sums of longs to doubles.
+        if(isString(lhsType) || isString(rhsType)) {
+            return Type.CHARSEQUENCE;
+        }
+        // NOTE: We don't have optimistic object-to-(int, long) conversions. Therefore, if any operand is an Object, we
+        // bail out of optimism here and presume a conservative Object return value, as the object's ToPrimitive() can
+        // end up returning either a number or a string, and their common supertype is Object, for better or worse.
+        final Type widest = Type.widest(undefinedToNumber(booleanToInt(lhsType)), undefinedToNumber(booleanToInt(rhsType)));
+        return widest.isObject() ? Type.OBJECT : widest;
+    }
+
+    /**
+     * If the node is a node representing an add operation and has {@link #isOptimisticUndecidedType() optimistic
+     * undecided type}, decides its type. Should be invoked after its operands types have been finalized.
+     * @return returns a new node similar to this node, but with its type set to the type decided from the type of its
+     * operands.
+     */
+    public BinaryNode decideType() {
+        assert type == OPTIMISTIC_UNDECIDED_TYPE;
+        return setType(decideType(lhs.getType(), rhs.getType()));
+    }
+
+    @Override
+    public BinaryNode setType(final Type type) {
+        if (this.type == type) {
+            return this;
+        }
+        return new BinaryNode(this, lhs, rhs, type, programPoint);
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Block.java b/nashorn/src/jdk/nashorn/internal/ir/Block.java
index f262d8d..c157626 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Block.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Block.java
@@ -33,19 +33,15 @@
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-
 import jdk.nashorn.internal.codegen.Label;
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-
 /**
  * IR representation for a list of statements.
  */
 @Immutable
-public class Block extends Node implements BreakableNode, Flags<Block> {
+public class Block extends Node implements BreakableNode, Terminal, Flags<Block> {
     /** List of statements */
     protected final List<Statement> statements;
 
@@ -53,7 +49,7 @@
     protected final Map<String, Symbol> symbols;
 
     /** Entry label. */
-    protected final Label entryLabel;
+    private final Label entryLabel;
 
     /** Break label. */
     private final Label breakLabel;
@@ -61,25 +57,27 @@
     /** Does the block/function need a new scope? */
     protected final int flags;
 
+    /**
+     * @see JoinPredecessor
+     */
+    private final LocalVariableConversion conversion;
+
     /** Flag indicating that this block needs scope */
     public static final int NEEDS_SCOPE = 1 << 0;
 
     /**
-     * Flag indicating whether this block needs
-     * self symbol assignment at the start. This is used only for
-     * blocks that are the bodies of function nodes who refer to themselves
-     * by name. It causes codegen to insert a var [fn_name] = __callee__
-     * at the start of the body
-     */
-    public static final int NEEDS_SELF_SYMBOL = 1 << 1;
-
-    /**
      * Is this block tagged as terminal based on its contents
      * (usually the last statement)
      */
     public static final int IS_TERMINAL = 1 << 2;
 
     /**
+     * Is this block the eager global scope - i.e. the original program. This isn't true for the
+     * outermost level of recompiles
+     */
+    public static final int IS_GLOBAL_SCOPE = 1 << 3;
+
+    /**
      * Constructor
      *
      * @param token      token
@@ -94,7 +92,8 @@
         this.entryLabel = new Label("block_entry");
         this.breakLabel = new Label("block_break");
         final int len = statements.length;
-        this.flags = (len > 0 && statements[len - 1].hasTerminalFlags()) ? IS_TERMINAL : 0;
+        this.flags = len > 0 && statements[len - 1].hasTerminalFlags() ? IS_TERMINAL : 0;
+        this.conversion = null;
     }
 
     /**
@@ -108,7 +107,7 @@
         this(token, finish, statements.toArray(new Statement[statements.size()]));
     }
 
-    private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols) {
+    private Block(final Block block, final int finish, final List<Statement> statements, final int flags, final Map<String, Symbol> symbols, final LocalVariableConversion conversion) {
         super(block);
         this.statements = statements;
         this.flags      = flags;
@@ -116,11 +115,21 @@
         this.entryLabel = new Label(block.entryLabel);
         this.breakLabel = new Label(block.breakLabel);
         this.finish     = finish;
+        this.conversion = conversion;
     }
 
     /**
-     * Clear the symbols in a block
-     * TODO: make this immutable
+     * Is this block the outermost eager global scope - i.e. the primordial program?
+     * Used for global anchor point for scope depth computation for recompilation code
+     * @return true if outermost eager global scope
+     */
+    public boolean isGlobalScope() {
+        return getFlag(IS_GLOBAL_SCOPE);
+    }
+
+    /**
+     * Clear the symbols in the block.
+     * TODO: make this immutable.
      */
     public void clearSymbols() {
         symbols.clear();
@@ -128,7 +137,7 @@
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
-        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols));
+        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion));
     }
 
     /**
@@ -140,14 +149,14 @@
     @Override
     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBlock(this)) {
-            return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, Statement.class, statements)));
+            return visitor.leaveBlock(setStatements(lc, Node.accept(visitor, statements)));
         }
 
         return this;
     }
 
     /**
-     * Get an iterator for all the symbols defined in this block
+     * Get a copy of the list for all the symbols defined in this block
      * @return symbol iterator
      */
     public List<Symbol> getSymbols() {
@@ -175,9 +184,9 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         for (final Node statement : statements) {
-            statement.toString(sb);
+            statement.toString(sb, printType);
             sb.append(';');
         }
     }
@@ -217,19 +226,16 @@
         return isTerminal ? setFlag(lc, IS_TERMINAL) : clearFlag(lc, IS_TERMINAL);
     }
 
-    /**
-     * Set the type of the return symbol in this block if present.
-     * @param returnType the new type
-     * @return this block
-     */
-    public Block setReturnType(final Type returnType) {
-        final Symbol symbol = getExistingSymbol(RETURN.symbolName());
-        if (symbol != null) {
-            symbol.setTypeOverride(returnType);
-        }
-        return this;
+    @Override
+    public int getFlags() {
+        return flags;
     }
 
+    /**
+     * Is this a terminal block, i.e. does it end control flow like ending with a throw or return?
+     *
+     * @return true if this node statement is terminal
+     */
     @Override
     public boolean isTerminal() {
         return getFlag(IS_TERMINAL);
@@ -248,6 +254,19 @@
         return breakLabel;
     }
 
+    @Override
+    public Block setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion));
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
+    }
+
     /**
      * Get the list of statements in this block
      *
@@ -258,6 +277,17 @@
     }
 
     /**
+     * Returns the line number of the first statement in the block.
+     * @return the line number of the first statement in the block, or -1 if the block has no statements.
+     */
+    public int getFirstStatementLineNumber() {
+        if(statements == null || statements.isEmpty()) {
+            return -1;
+        }
+        return statements.get(0).getLineNumber();
+    }
+
+    /**
      * Reset the statement list for this block
      *
      * @param lc lexical context
@@ -272,7 +302,7 @@
         if (!statements.isEmpty()) {
             lastFinish = statements.get(statements.size() - 1).getFinish();
         }
-        return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols));
+        return Node.replaceInLexicalContext(lc, this, new Block(this, Math.max(finish, lastFinish), statements, flags, symbols, conversion));
     }
 
     /**
@@ -295,20 +325,20 @@
     }
 
     @Override
-    public Block setFlags(final LexicalContext lc, int flags) {
+    public Block setFlags(final LexicalContext lc, final int flags) {
         if (this.flags == flags) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols));
+        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags, symbols, conversion));
     }
 
     @Override
-    public Block clearFlag(final LexicalContext lc, int flag) {
+    public Block clearFlag(final LexicalContext lc, final int flag) {
         return setFlags(lc, flags & ~flag);
     }
 
     @Override
-    public Block setFlag(final LexicalContext lc, int flag) {
+    public Block setFlag(final LexicalContext lc, final int flag) {
         return setFlags(lc, flags | flag);
     }
 
@@ -327,7 +357,7 @@
             return this;
         }
 
-        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags | NEEDS_SCOPE, symbols));
+        return Node.replaceInLexicalContext(lc, this, new Block(this, finish, statements, flags | NEEDS_SCOPE, symbols, conversion));
     }
 
     /**
@@ -353,11 +383,11 @@
 
     @Override
     public List<Label> getLabels() {
-        return Collections.singletonList(breakLabel);
+        return Collections.unmodifiableList(Arrays.asList(entryLabel, breakLabel));
     }
 
     @Override
-    public Node accept(NodeVisitor<? extends LexicalContext> visitor) {
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         return Acceptor.accept(this, visitor);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java b/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
index 8fecddd..d437069 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BlockLexicalContext.java
@@ -40,14 +40,14 @@
 public class BlockLexicalContext extends LexicalContext {
     /** statement stack, each block on the lexical context maintains one of these, which is
      *  committed to the block on pop */
-    private Deque<List<Statement>> sstack = new ArrayDeque<>();
+    private final Deque<List<Statement>> sstack = new ArrayDeque<>();
 
     /** Last non debug statement emitted in this context */
     protected Statement lastStatement;
 
     @Override
     public <T extends LexicalContextNode> T push(final T node) {
-        T pushed = super.push(node);
+        final T pushed = super.push(node);
         if (node instanceof Block) {
             sstack.push(new ArrayList<Statement>());
         }
@@ -68,7 +68,7 @@
      * @param block the block to operate on
      * @return a modified block.
      */
-    protected Block afterSetStatements(Block block) {
+    protected Block afterSetStatements(final Block block) {
         return block;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java b/nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java
index e790cf4..6b1c155 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BlockStatement.java
@@ -58,7 +58,7 @@
      * @return a block statement with the new statements. It will have the line number, token, and finish of the
      * original statement.
      */
-    public static Statement createReplacement(final Statement stmt, final List<Statement> newStmts) {
+    public static BlockStatement createReplacement(final Statement stmt, final List<Statement> newStmts) {
         return createReplacement(stmt, stmt.getFinish(), newStmts);
     }
 
@@ -70,7 +70,7 @@
      * @return a block statement with the new statements. It will have the line number, and token of the
      * original statement.
      */
-    public static Statement createReplacement(final Statement stmt, int finish, final List<Statement> newStmts) {
+    public static BlockStatement createReplacement(final Statement stmt, final int finish, final List<Statement> newStmts) {
         return new BlockStatement(stmt.getLineNumber(), new Block(stmt.getToken(), finish, newStmts));
     }
 
@@ -89,8 +89,8 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        block.toString(sb);
+    public void toString(final StringBuilder sb, final boolean printType) {
+        block.toString(sb, printType);
     }
 
     /**
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java b/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java
index 2b8fbd8..c127b1a 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakNode.java
@@ -32,9 +32,7 @@
  * IR representation for {@code break} statements.
  */
 @Immutable
-public final class BreakNode extends Statement {
-
-    private final IdentNode label;
+public final class BreakNode extends JumpStatement {
 
     /**
      * Constructor
@@ -42,22 +40,16 @@
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param label      label for break or null if none
+     * @param labelName  label name for break or null if none
      */
-    public BreakNode(final int lineNumber, final long token, final int finish, final IdentNode label) {
-        super(lineNumber, token, finish);
-        this.label = label;
+    public BreakNode(final int lineNumber, final long token, final int finish, final String labelName) {
+        super(lineNumber, token, finish, labelName);
     }
 
-    @Override
-    public boolean hasGoto() {
-        return true;
+    private BreakNode(final BreakNode breakNode, final LocalVariableConversion conversion) {
+        super(breakNode, conversion);
     }
 
-    /**
-     * Assist in IR navigation.
-     * @param visitor IR navigating visitor.
-     */
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterBreakNode(this)) {
@@ -67,21 +59,13 @@
         return this;
     }
 
-    /**
-     * Get the label for this break node
-     * @return label, or null if none
-     */
-    public IdentNode getLabel() {
-        return label;
+    @Override
+    JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+        return new BreakNode(this, conversion);
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        sb.append("break");
-
-        if (label != null) {
-            sb.append(' ');
-            label.toString(sb);
-        }
+    String getStatementName() {
+        return "break";
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java b/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java
index 0d12b7c..160a1f6 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakableNode.java
@@ -25,14 +25,13 @@
 
 package jdk.nashorn.internal.ir;
 
-import java.util.List;
 import jdk.nashorn.internal.codegen.Label;
 
 /**
  * This class represents a node from which control flow can execute
  * a {@code break} statement
  */
-public interface BreakableNode extends LexicalContextNode {
+public interface BreakableNode extends LexicalContextNode, JoinPredecessor, Labels {
     /**
      * Ensure that any labels in this breakable node are unique so
      * that new jumps won't go to old parts of the tree. Used for
@@ -56,11 +55,4 @@
      */
     public Label getBreakLabel();
 
-    /**
-     * Return the labels associated with this node. Breakable nodes that
-     * aren't LoopNodes only have a break label - the location immediately
-     * afterwards the node in code
-     * @return list of labels representing locations around this node
-     */
-    public List<Label> getLabels();
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java b/nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java
index fa74454..e0a67b1 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/BreakableStatement.java
@@ -36,6 +36,8 @@
     /** break label. */
     protected final Label breakLabel;
 
+    final LocalVariableConversion conversion;
+
     /**
      * Constructor
      *
@@ -47,16 +49,19 @@
     protected BreakableStatement(final int lineNumber, final long token, final int finish, final Label breakLabel) {
         super(lineNumber, token, finish);
         this.breakLabel = breakLabel;
+        this.conversion = null;
     }
 
     /**
      * Copy constructor
      *
      * @param breakableNode source node
+     * @param conversion the potentially new local variable conversion
      */
-    protected BreakableStatement(final BreakableStatement breakableNode) {
+    protected BreakableStatement(final BreakableStatement breakableNode, final LocalVariableConversion conversion) {
         super(breakableNode);
         this.breakLabel = new Label(breakableNode.getBreakLabel());
+        this.conversion = conversion;
     }
 
     /**
@@ -86,6 +91,21 @@
      */
     @Override
     public List<Label> getLabels() {
-        return Collections.singletonList(breakLabel);
+        return Collections.unmodifiableList(Collections.singletonList(breakLabel));
     }
+
+    @Override
+    public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return setLocalVariableConversionChanged(lc, conversion);
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
+    }
+
+    abstract JoinPredecessor setLocalVariableConversionChanged(LexicalContext lc, LocalVariableConversion conversion);
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java
index 0d38f24..189a419 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/CallNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/CallNode.java
@@ -25,8 +25,11 @@
 
 package jdk.nashorn.internal.ir;
 
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
 import java.util.Collections;
 import java.util.List;
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
@@ -36,7 +39,7 @@
  * IR representation for a function call.
  */
 @Immutable
-public final class CallNode extends LexicalContextExpression {
+public final class CallNode extends LexicalContextExpression implements Optimistic {
 
     /** Function identifier or function body. */
     private final Expression function;
@@ -45,71 +48,52 @@
     private final List<Expression> args;
 
     /** Is this a "new" operation */
-    public static final int IS_NEW        = 0x1;
+    private static final int IS_NEW = 1 << 0;
+
+    /** Can this be a Function.call? */
+    private static final int IS_APPLY_TO_CALL = 1 << 1;
 
     private final int flags;
 
     private final int lineNumber;
 
+    private final int programPoint;
+
+    private final Type optimisticType;
+
     /**
      * Arguments to be passed to builtin {@code eval} function
      */
     public static class EvalArgs {
-        /** evaluated code */
-        private final Expression code;
-
-        /** 'this' passed to evaluated code */
-        private final IdentNode evalThis;
+        private final List<Expression> args;
 
         /** location string for the eval call */
         private final String location;
 
-        /** is this call from a strict context? */
-        private final boolean strictMode;
-
         /**
          * Constructor
          *
-         * @param code       code to evaluate
-         * @param evalThis   this node
-         * @param location   location for the eval call
-         * @param strictMode is this a call from a strict context?
+         * @param args     arguments to eval
+         * @param location location for the eval call
          */
-        public EvalArgs(final Expression code, final IdentNode evalThis, final String location, final boolean strictMode) {
-            this.code = code;
-            this.evalThis = evalThis;
+        public EvalArgs(final List<Expression> args, final String location) {
+            this.args = args;
             this.location = location;
-            this.strictMode = strictMode;
         }
 
         /**
          * Return the code that is to be eval:ed by this eval function
          * @return code as an AST node
          */
-        public Expression getCode() {
-            return code;
+        public List<Expression> getArgs() {
+            return Collections.unmodifiableList(args);
         }
 
-        private EvalArgs setCode(final Expression code) {
-            if (this.code == code) {
+        private EvalArgs setArgs(final List<Expression> args) {
+            if (this.args == args) {
                 return this;
             }
-            return new EvalArgs(code, evalThis, location, strictMode);
-        }
-
-        /**
-         * Get the {@code this} symbol used to invoke this eval call
-         * @return the {@code this} symbol
-         */
-        public IdentNode getThis() {
-            return this.evalThis;
-        }
-
-        private EvalArgs setThis(final IdentNode evalThis) {
-            if (this.evalThis == evalThis) {
-                return this;
-            }
-            return new EvalArgs(code, evalThis, location, strictMode);
+            return new EvalArgs(args, location);
         }
 
         /**
@@ -119,14 +103,6 @@
         public String getLocation() {
             return this.location;
         }
-
-        /**
-         * Check whether this eval call is executed in strict mode
-         * @return true if executed in strict mode, false otherwise
-         */
-        public boolean getStrictMode() {
-            return this.strictMode;
-        }
     }
 
     /** arguments for 'eval' call. Non-null only if this call node is 'eval' */
@@ -141,24 +117,29 @@
      * @param finish     finish
      * @param function   the function to call
      * @param args       args to the call
+     * @param isNew      true if this is a constructor call with the "new" keyword
      */
-    public CallNode(final int lineNumber, final long token, final int finish, final Expression function, final List<Expression> args) {
+    public CallNode(final int lineNumber, final long token, final int finish, final Expression function, final List<Expression> args, final boolean isNew) {
         super(token, finish);
 
-        this.function   = function;
-        this.args       = args;
-        this.flags      = 0;
-        this.evalArgs   = null;
-        this.lineNumber = lineNumber;
+        this.function       = function;
+        this.args           = args;
+        this.flags          = isNew ? IS_NEW : 0;
+        this.evalArgs       = null;
+        this.lineNumber     = lineNumber;
+        this.programPoint   = INVALID_PROGRAM_POINT;
+        this.optimisticType = null;
     }
 
-    private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final EvalArgs evalArgs) {
+    private CallNode(final CallNode callNode, final Expression function, final List<Expression> args, final int flags, final Type optimisticType, final EvalArgs evalArgs, final int programPoint) {
         super(callNode);
         this.lineNumber = callNode.lineNumber;
         this.function = function;
         this.args = args;
         this.flags = flags;
         this.evalArgs = evalArgs;
+        this.programPoint = programPoint;
+        this.optimisticType = optimisticType;
     }
 
     /**
@@ -170,8 +151,16 @@
     }
 
     @Override
-    public Type getType() {
-        return function instanceof FunctionNode ? ((FunctionNode)function).getReturnType() : Type.OBJECT;
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        return optimisticType == null ? Type.OBJECT : optimisticType;
+    }
+
+    @Override
+    public Optimistic setType(final Type optimisticType) {
+        if (this.optimisticType == optimisticType) {
+            return this;
+        }
+        return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
     }
 
     /**
@@ -186,15 +175,13 @@
         if (visitor.enterCallNode(this)) {
             final CallNode newCallNode = (CallNode)visitor.leaveCallNode(
                     setFunction((Expression)function.accept(visitor)).
-                    setArgs(Node.accept(visitor, Expression.class, args)).
-                    setFlags(flags).
+                    setArgs(Node.accept(visitor, args)).
                     setEvalArgs(evalArgs == null ?
                             null :
-                            evalArgs.setCode((Expression)evalArgs.getCode().accept(visitor)).
-                                setThis((IdentNode)evalArgs.getThis().accept(visitor))));
+                            evalArgs.setArgs(Node.accept(visitor, evalArgs.getArgs()))));
             // Theoretically, we'd need to instead pass lc to every setter and do a replacement on each. In practice,
             // setType from TypeOverride can't accept a lc, and we don't necessarily want to go there now.
-            if(this != newCallNode) {
+            if (this != newCallNode) {
                 return Node.replaceInLexicalContext(lc, this, newCallNode);
             }
         }
@@ -203,8 +190,19 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        function.toString(sb);
+    public void toString(final StringBuilder sb, final boolean printType) {
+        if (printType) {
+            optimisticTypeToString(sb);
+        }
+
+        final StringBuilder fsb = new StringBuilder();
+        function.toString(fsb, printType);
+
+        if (isApplyToCall()) {
+            sb.append(fsb.toString().replace("apply", "[apply => call]"));
+        } else {
+            sb.append(fsb);
+        }
 
         sb.append('(');
 
@@ -217,7 +215,7 @@
                 first = false;
             }
 
-            arg.toString(sb);
+            arg.toString(sb, printType);
         }
 
         sb.append(')');
@@ -234,12 +232,13 @@
     /**
      * Reset the arguments for the call
      * @param args new arguments list
+     * @return new callnode, or same if unchanged
      */
-    private CallNode setArgs(final List<Expression> args) {
+    public CallNode setArgs(final List<Expression> args) {
         if (this.args == args) {
             return this;
         }
-        return new CallNode(this, function, args, flags, evalArgs);
+        return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
     }
 
     /**
@@ -261,7 +260,7 @@
         if (this.evalArgs == evalArgs) {
             return this;
         }
-        return new CallNode(this, function, args, flags, evalArgs);
+        return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
     }
 
     /**
@@ -273,6 +272,23 @@
     }
 
     /**
+     * Is this an apply call that we optimistically should try to turn into
+     * a call instead
+     * @return true if apply to call
+     */
+    public boolean isApplyToCall() {
+        return (flags & IS_APPLY_TO_CALL) != 0;
+    }
+
+    /**
+     * Flag this call node as one that tries to call call instead of apply
+     * @return new call node with changed flags, if not already flagged as apply to call, then the same node
+     */
+    public CallNode setIsApplyToCall() {
+        return setFlags(flags | IS_APPLY_TO_CALL);
+    }
+
+    /**
      * Return the function expression that this call invokes
      * @return the function
      */
@@ -289,7 +305,7 @@
         if (this.function == function) {
             return this;
         }
-        return new CallNode(this, function, args, flags, evalArgs);
+        return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
     }
 
     /**
@@ -297,21 +313,41 @@
      * @return true if this a new operation
      */
     public boolean isNew() {
-        return (flags & IS_NEW) == IS_NEW;
-    }
-
-    /**
-     * Flag this call as a new operation
-     * @return same node or new one on state change
-     */
-    public CallNode setIsNew() {
-        return setFlags(IS_NEW);
+        return (flags & IS_NEW) != 0;
     }
 
     private CallNode setFlags(final int flags) {
         if (this.flags == flags) {
             return this;
         }
-        return new CallNode(this, function, args, flags, evalArgs);
+        return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
+    }
+
+    @Override
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    @Override
+    public CallNode setProgramPoint(final int programPoint) {
+        if (this.programPoint == programPoint) {
+            return this;
+        }
+        return new CallNode(this, function, args, flags, optimisticType, evalArgs, programPoint);
+    }
+
+    @Override
+    public Type getMostOptimisticType() {
+        return Type.INT;
+    }
+
+    @Override
+    public Type getMostPessimisticType() {
+        return Type.OBJECT;
+    }
+
+    @Override
+    public boolean canBeOptimistic() {
+        return true;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java b/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java
index c809058..aae6d71 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/CaseNode.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.ir;
 
+import java.util.Collections;
+import java.util.List;
 import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -34,7 +36,7 @@
  * Case nodes are not BreakableNodes, but the SwitchNode is
  */
 @Immutable
-public final class CaseNode extends Node {
+public final class CaseNode extends Node implements JoinPredecessor, Labels, Terminal {
     /** Test expression. */
     private final Expression test;
 
@@ -45,6 +47,11 @@
     private final Label entry;
 
     /**
+     * @see JoinPredecessor
+     */
+    private final LocalVariableConversion conversion;
+
+    /**
      * Constructors
      *
      * @param token    token
@@ -58,16 +65,23 @@
         this.test  = test;
         this.body  = body;
         this.entry = new Label("entry");
+        this.conversion = null;
     }
 
-    CaseNode(final CaseNode caseNode, final Expression test, final Block body) {
+    CaseNode(final CaseNode caseNode, final Expression test, final Block body, final LocalVariableConversion conversion) {
         super(caseNode);
 
         this.test  = test;
         this.body  = body;
         this.entry = new Label(caseNode.entry);
+        this.conversion = conversion;
     }
 
+    /**
+     * Is this a terminal case node, i.e. does it end control flow like having a throw or return?
+     *
+     * @return true if this node statement is terminal
+     */
     @Override
     public boolean isTerminal() {
         return body.isTerminal();
@@ -90,10 +104,10 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printTypes) {
         if (test != null) {
             sb.append("case ");
-            test.toString(sb);
+            test.toString(sb, printTypes);
             sb.append(':');
         } else {
             sb.append("default:");
@@ -133,13 +147,31 @@
         if (this.test == test) {
             return this;
         }
-        return new CaseNode(this, test, body);
+        return new CaseNode(this, test, body, conversion);
+    }
+
+    @Override
+    public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return new CaseNode(this, test, body, conversion);
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
     }
 
     private CaseNode setBody(final Block body) {
         if (this.body == body) {
             return this;
         }
-        return new CaseNode(this, test, body);
+        return new CaseNode(this, test, body, conversion);
+    }
+
+    @Override
+    public List<Label> getLabels() {
+        return Collections.unmodifiableList(Collections.singletonList(entry));
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java b/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java
index ba640a5..1a496dd 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/CatchNode.java
@@ -42,10 +42,7 @@
     /** Catch body. */
     private final Block body;
 
-    private final int flags;
-
-    /** Is this block a synthethic rethrow created by finally inlining? */
-    public static final int IS_SYNTHETIC_RETHROW = 1;
+    private final boolean isSyntheticRethrow;
 
     /**
      * Constructors
@@ -56,22 +53,24 @@
      * @param exception          variable name of exception
      * @param exceptionCondition exception condition
      * @param body               catch body
-     * @param flags              flags
+     * @param isSyntheticRethrow true if this node is a synthetically generated rethrow node.
      */
-    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception, final Expression exceptionCondition, final Block body, final int flags) {
+    public CatchNode(final int lineNumber, final long token, final int finish, final IdentNode exception,
+            final Expression exceptionCondition, final Block body, final boolean isSyntheticRethrow) {
         super(lineNumber, token, finish);
-        this.exception          = exception;
+        this.exception          = exception == null ? null : exception.setIsInitializedHere();
         this.exceptionCondition = exceptionCondition;
         this.body               = body;
-        this.flags              = flags;
+        this.isSyntheticRethrow = isSyntheticRethrow;
     }
 
-    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition, final Block body, final int flags) {
+    private CatchNode(final CatchNode catchNode, final IdentNode exception, final Expression exceptionCondition,
+            final Block body, final boolean isSyntheticRethrow) {
         super(catchNode);
         this.exception          = exception;
         this.exceptionCondition = exceptionCondition;
         this.body               = body;
-        this.flags              = flags;
+        this.isSyntheticRethrow = isSyntheticRethrow;
     }
 
     /**
@@ -96,13 +95,13 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printTypes) {
         sb.append(" catch (");
-        exception.toString(sb);
+        exception.toString(sb, printTypes);
 
         if (exceptionCondition != null) {
             sb.append(" if ");
-            exceptionCondition.toString(sb);
+            exceptionCondition.toString(sb, printTypes);
         }
         sb.append(')');
     }
@@ -132,7 +131,7 @@
         if (this.exceptionCondition == exceptionCondition) {
             return this;
         }
-        return new CatchNode(this, exception, exceptionCondition, body, flags);
+        return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
     }
 
     /**
@@ -152,14 +151,14 @@
         if (this.exception == exception) {
             return this;
         }
-        return new CatchNode(this, exception, exceptionCondition, body, flags);
+        return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
     }
 
     private CatchNode setBody(final Block body) {
         if (this.body == body) {
             return this;
         }
-        return new CatchNode(this, exception, exceptionCondition, body, flags);
+        return new CatchNode(this, exception, exceptionCondition, body, isSyntheticRethrow);
     }
 
     /**
@@ -170,7 +169,6 @@
      * @return true if a finally synthetic rethrow
      */
     public boolean isSyntheticRethrow() {
-        return (flags & IS_SYNTHETIC_RETHROW) == IS_SYNTHETIC_RETHROW;
+        return isSyntheticRethrow;
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java b/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java
index 579414a..d5177db 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/ContinueNode.java
@@ -32,26 +32,21 @@
  * IR representation for CONTINUE statements.
  */
 @Immutable
-public class ContinueNode extends Statement {
-
-    private IdentNode label;
-
+public class ContinueNode extends JumpStatement {
     /**
      * Constructor
      *
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param label      label for break or null if none
+     * @param labelName  label name for continue or null if none
      */
-    public ContinueNode(final int lineNumber, final long token, final int finish, final IdentNode label) {
-        super(lineNumber, token, finish);
-        this.label = label;
+    public ContinueNode(final int lineNumber, final long token, final int finish, final String labelName) {
+        super(lineNumber, token, finish, labelName);
     }
 
-    @Override
-    public boolean hasGoto() {
-        return true;
+    private ContinueNode(final ContinueNode continueNode, final LocalVariableConversion conversion) {
+        super(continueNode, conversion);
     }
 
     @Override
@@ -63,22 +58,14 @@
         return this;
     }
 
-    /**
-     * Get the label for this break node
-     * @return label, or null if none
-     */
-    public IdentNode getLabel() {
-        return label;
+    @Override
+    JumpStatement createNewJumpStatement(final LocalVariableConversion conversion) {
+        return new ContinueNode(this, conversion);
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        sb.append("continue");
-
-        if (label != null) {
-            sb.append(' ');
-            label.toString(sb);
-        }
+    String getStatementName() {
+        return "continue";
     }
 }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java b/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java
index aa86f2f..c0e3c2c 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/EmptyNode.java
@@ -64,7 +64,7 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printTypes) {
         sb.append(';');
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Expression.java b/nashorn/src/jdk/nashorn/internal/ir/Expression.java
index f8074fe..c6b2276 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Expression.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Expression.java
@@ -25,7 +25,9 @@
 
 package jdk.nashorn.internal.ir;
 
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
 /**
  * Common superclass for all expression nodes. Expression nodes can have
@@ -33,69 +35,44 @@
  *
  */
 public abstract class Expression extends Node {
-    private Symbol symbol;
+    static final String OPT_IDENTIFIER = "%";
 
-    Expression(long token, int start, int finish) {
+    private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
+        @Override
+        public Type apply(final Symbol t) {
+            return null;
+        }
+    };
+
+    Expression(final long token, final int start, final int finish) {
         super(token, start, finish);
     }
 
-    Expression(long token, int finish) {
+    Expression(final long token, final int finish) {
         super(token, finish);
     }
 
-    Expression(Expression expr) {
+    Expression(final Expression expr) {
         super(expr);
-        this.symbol = expr.symbol;
     }
 
     /**
-     * Return the Symbol the compiler has assigned to this Node. The symbol
-     * is the place where it's expression value is stored after evaluation
+     * Returns the type of the expression.
      *
-     * @return the symbol
+     * @return the type of the expression.
      */
-    public Symbol getSymbol() {
-        return symbol;
+    public final Type getType() {
+        return getType(UNKNOWN_LOCALS);
     }
 
     /**
-     * Assign a symbol to this node. See {@link Expression#getSymbol()} for explanation
-     * of what a symbol is
-     *
-     * @param lc lexical context
-     * @param symbol the symbol
-     * @return new node
+     * Returns the type of the expression under the specified symbol-to-type mapping. By default delegates to
+     * {@link #getType()} but expressions whose type depends on their subexpressions' types and expressions whose type
+     * depends on symbol type ({@link IdentNode}) will have a special implementation.
+     * @param localVariableTypes a mapping from symbols to their types, used for type calculation.
+     * @return the type of the expression under the specified symbol-to-type mapping.
      */
-    public Expression setSymbol(final LexicalContext lc, final Symbol symbol) {
-        if (this.symbol == symbol) {
-            return this;
-        }
-        final Expression newExpr = (Expression)clone();
-        newExpr.symbol = symbol;
-        return newExpr;
-    }
-
-    /**
-     * Check if the expression has a type. The default behavior is to go into the symbol
-     * and check the symbol type, but there may be overrides, for example in
-     * getters that require a different type than the internal representation
-     *
-     * @return true if a type exists
-     */
-    public boolean hasType() {
-        return getSymbol() != null;
-    }
-
-    /**
-     * Returns the type of the expression. Typically this is the symbol type. No types
-     * are stored in the expression itself, unless it implements TypeOverride.
-     *
-     * @return the type of the node.
-     */
-    public Type getType() {
-        assert hasType() : this + " has no type";
-        return symbol.getSymbolType();
-    }
+    public abstract Type getType(final Function<Symbol, Type> localVariableTypes);
 
     /**
      * Returns {@code true} if this expression depends exclusively on state that is constant
@@ -108,4 +85,88 @@
     public boolean isLocal() {
         return false;
     }
+
+    /**
+     * Is this a self modifying assignment?
+     * @return true if self modifying, e.g. a++, or a*= 17
+     */
+    public boolean isSelfModifying() {
+        return false;
+    }
+
+    /**
+     * Returns widest operation type of this operation.
+     *
+     * @return the widest type for this operation
+     */
+    public Type getWidestOperationType() {
+        return Type.OBJECT;
+    }
+
+    /**
+     * Returns true if the type of this expression is narrower than its widest operation type (thus, it is
+     * optimistically typed).
+     * @return true if this expression is optimistically typed.
+     */
+    public final boolean isOptimistic() {
+        return getType().narrowerThan(getWidestOperationType());
+    }
+
+    void optimisticTypeToString(final StringBuilder sb) {
+        optimisticTypeToString(sb, isOptimistic());
+    }
+
+    void optimisticTypeToString(final StringBuilder sb, final boolean optimistic) {
+        sb.append('{');
+        final Type type = getType();
+        final String desc = type == Type.UNDEFINED ? "U" : type.getDescriptor();
+
+        sb.append(desc.charAt(desc.length() - 1) == ';' ? "O" : desc);
+        if (isOptimistic() && optimistic) {
+            sb.append(OPT_IDENTIFIER);
+            final int pp = ((Optimistic)this).getProgramPoint();
+            if (UnwarrantedOptimismException.isValid(pp)) {
+                sb.append('_').append(pp);
+            }
+        }
+        sb.append('}');
+    }
+
+    /**
+     * Returns true if the runtime value of this expression is always false when converted to boolean as per ECMAScript
+     * ToBoolean conversion. Used in control flow calculations.
+     * @return true if this expression's runtime value converted to boolean is always false.
+     */
+    public boolean isAlwaysFalse() {
+        return false;
+    }
+
+    /**
+     * Returns true if the runtime value of this expression is always true when converted to boolean as per ECMAScript
+     * ToBoolean conversion. Used in control flow calculations.
+     * @return true if this expression's runtime value converted to boolean is always true.
+     */
+    public boolean isAlwaysTrue() {
+        return false;
+    }
+
+    /**
+     * Returns true if the expression is not null and {@link #isAlwaysFalse()}.
+     * @param test a test expression used as a predicate of a branch or a loop.
+     * @return true if the expression is not null and {@link #isAlwaysFalse()}.
+     */
+    public static boolean isAlwaysFalse(final Expression test) {
+        return test != null && test.isAlwaysFalse();
+    }
+
+
+    /**
+     * Returns true if the expression is null or {@link #isAlwaysTrue()}. Null is considered to be always true as a
+     * for loop with no test is equivalent to a for loop with always-true test.
+     * @param test a test expression used as a predicate of a branch or a loop.
+     * @return true if the expression is null or {@link #isAlwaysFalse()}.
+     */
+    public static boolean isAlwaysTrue(final Expression test) {
+        return test == null || test.isAlwaysTrue();
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java b/nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java
index 8b118a2..45870ff 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/ExpressionStatement.java
@@ -57,11 +57,6 @@
     }
 
     @Override
-    public boolean isTerminal() {
-        return expression.isTerminal();
-    }
-
-    @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterExpressionStatement(this)) {
             return visitor.leaveExpressionStatement(setExpression((Expression)expression.accept(visitor)));
@@ -71,8 +66,8 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        expression.toString(sb);
+    public void toString(final StringBuilder sb, final boolean printTypes) {
+        expression.toString(sb, printTypes);
     }
 
     /**
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Flags.java b/nashorn/src/jdk/nashorn/internal/ir/Flags.java
index 94a2109..fb4b5de 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Flags.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Flags.java
@@ -37,6 +37,12 @@
 public interface Flags<T extends LexicalContextNode> {
 
     /**
+     * Get all flags of a LexicalContextNode
+     * @return flags
+     */
+    public int getFlags();
+
+    /**
      * Check if a flag is set in a lexical context node
      * @param flag flag to check
      * @return flags
diff --git a/nashorn/src/jdk/nashorn/internal/ir/ForNode.java b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java
index 8130e23..9b4cb6d 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/ForNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/ForNode.java
@@ -33,11 +33,12 @@
  */
 @Immutable
 public final class ForNode extends LoopNode {
-    /** Initialize expression. */
+    /** Initialize expression for an ordinary for statement, or the LHS expression receiving iterated-over values in a
+     * for-in statement. */
     private final Expression init;
 
-    /** Test expression. */
-    private final Expression modify;
+    /** Modify expression for an ordinary statement, or the source of the iterator in the for-in statement. */
+    private final JoinPredecessorExpression modify;
 
     /** Iterator symbol. */
     private Symbol iterator;
@@ -59,30 +60,30 @@
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param init       initialization expression
-     * @param test       test
      * @param body       body
-     * @param modify     modify
      * @param flags      flags
      */
-    public ForNode(final int lineNumber, final long token, final int finish, final Expression init, final Expression test, final Block body, final Expression modify, final int flags) {
-        super(lineNumber, token, finish, test, body, false);
-        this.init   = init;
-        this.modify = modify;
+    public ForNode(final int lineNumber, final long token, final int finish, final Block body, final int flags) {
+        super(lineNumber, token, finish, body, false);
         this.flags  = flags;
+        this.init = null;
+        this.modify = null;
     }
 
-    private ForNode(final ForNode forNode, final Expression init, final Expression test, final Block body, final Expression modify, final int flags, final boolean controlFlowEscapes) {
-        super(forNode, test, body, controlFlowEscapes);
+    private ForNode(final ForNode forNode, final Expression init, final JoinPredecessorExpression test,
+            final Block body, final JoinPredecessorExpression modify, final int flags, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+        super(forNode, test, body, controlFlowEscapes, conversion);
         this.init   = init;
         this.modify = modify;
         this.flags  = flags;
-        this.iterator = forNode.iterator; //TODO is this acceptable? symbols are never cloned, just copied as references
+        // Even if the for node gets cloned in try/finally, the symbol can be shared as only one branch of the finally
+        // is executed.
+        this.iterator = forNode.iterator;
     }
 
     @Override
-    public Node ensureUniqueLabels(LexicalContext lc) {
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+    public Node ensureUniqueLabels(final LexicalContext lc) {
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -90,8 +91,8 @@
         if (visitor.enterForNode(this)) {
             return visitor.leaveForNode(
                 setInit(lc, init == null ? null : (Expression)init.accept(visitor)).
-                setTest(lc, test == null ? null : (Expression)test.accept(visitor)).
-                setModify(lc, modify == null ? null : (Expression)modify.accept(visitor)).
+                setTest(lc, test == null ? null : (JoinPredecessorExpression)test.accept(visitor)).
+                setModify(lc, modify == null ? null : (JoinPredecessorExpression)modify.accept(visitor)).
                 setBody(lc, (Block)body.accept(visitor)));
         }
 
@@ -99,24 +100,25 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        sb.append("for (");
+    public void toString(final StringBuilder sb, final boolean printTypes) {
+        sb.append("for");
+        LocalVariableConversion.toString(conversion, sb).append(' ');
 
         if (isForIn()) {
-            init.toString(sb);
+            init.toString(sb, printTypes);
             sb.append(" in ");
-            modify.toString(sb);
+            modify.toString(sb, printTypes);
         } else {
             if (init != null) {
-                init.toString(sb);
+                init.toString(sb, printTypes);
             }
             sb.append("; ");
             if (test != null) {
-                test.toString(sb);
+                test.toString(sb, printTypes);
             }
             sb.append("; ");
             if (modify != null) {
-                modify.toString(sb);
+                modify.toString(sb, printTypes);
             }
         }
 
@@ -154,7 +156,7 @@
         if (this.init == init) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     /**
@@ -212,7 +214,7 @@
      * Get the modification expression for this ForNode
      * @return the modification expression
      */
-    public Expression getModify() {
+    public JoinPredecessorExpression getModify() {
         return modify;
     }
 
@@ -222,24 +224,19 @@
      * @param modify new modification expression
      * @return new for node if changed or existing if not
      */
-    public ForNode setModify(final LexicalContext lc, final Expression modify) {
+    public ForNode setModify(final LexicalContext lc, final JoinPredecessorExpression modify) {
         if (this.modify == modify) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
-    public Expression getTest() {
-        return test;
-    }
-
-    @Override
-    public ForNode setTest(final LexicalContext lc, final Expression test) {
+    public ForNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) {
         if (this.test == test) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -252,7 +249,7 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -260,14 +257,18 @@
         if (this.controlFlowEscapes == controlFlowEscapes) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
     private ForNode setFlags(final LexicalContext lc, final int flags) {
         if (this.flags == flags) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
     }
 
+    @Override
+    JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+        return Node.replaceInLexicalContext(lc, this, new ForNode(this, init, test, body, modify, flags, controlFlowEscapes, conversion));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/FunctionCall.java b/nashorn/src/jdk/nashorn/internal/ir/FunctionCall.java
index 73a6c62..22bf37d 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionCall.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionCall.java
@@ -26,14 +26,18 @@
 package jdk.nashorn.internal.ir;
 
 /**
- * Interface used by AccessNodes, IndexNodes and IdentNodes to signal
- * that they are function calls
+ * Interface used by AccessNodes, IndexNodes and IdentNodes to signal that when evaluated, their value will be treated
+ * as a function and immediately invoked, e.g. {@code foo()}, {@code foo.bar()} or {@code foo[bar]()}. Used to customize
+ * the priority of composite dynamic operations when emitting {@code INVOKEDYNAMIC} instructions that implement them,
+ * namely prioritize {@code getMethod} over {@code getElem} or {@code getProp}. An access or ident node with isFunction
+ * set to true will be emitted as {@code dyn:getMethod|getProp|getElem} while one with it set to false will be emitted
+ * as {@code dyn:getProp|getElem|getMethod}. Similarly, an index node with isFunction set to true will be emitted as
+ * {@code dyn:getMethod|getElem|getProp} while the one set to false will be emitted as {@code dyn:getElem|getProp|getMethod}.
  */
 public interface FunctionCall {
     /**
-     * Return true if this function call implementor is a function
-     *
-     * @return true if implements a function call
+     * Returns true if the value of this expression will be treated as a function and immediately invoked.
+     * @return true if the value of this expression will be treated as a function and immediately invoked.
      */
     public boolean isFunction();
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
index a0f6a78..a67ab81 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/FunctionNode.java
@@ -25,12 +25,21 @@
 
 package jdk.nashorn.internal.ir;
 
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROFILE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_STRICT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_ENTEREXIT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_MISSES;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
+
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
-import java.util.Objects;
 import java.util.Set;
+import java.util.function.Function;
+import jdk.nashorn.internal.AssertsEnabled;
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.codegen.Compiler;
 import jdk.nashorn.internal.codegen.CompilerConstants;
@@ -49,7 +58,6 @@
  */
 @Immutable
 public final class FunctionNode extends LexicalContextExpression implements Flags<FunctionNode> {
-
     /** Type used for all FunctionNodes */
     public static final Type FUNCTION_TYPE = Type.typeFor(ScriptFunction.class);
 
@@ -77,26 +85,38 @@
         CONSTANT_FOLDED,
         /** method has been lowered */
         LOWERED,
-        /** method hass been attributed */
-        ATTR,
+        /** program points have been assigned to unique locations */
+        PROGRAM_POINTS_ASSIGNED,
+        /** any transformations of builtins have taken place, e.g. apply=&gt;call */
+        BUILTINS_TRANSFORMED,
         /** method has been split */
         SPLIT,
-        /** method has had its types finalized */
-        FINALIZED,
+        /** method has had symbols assigned */
+        SYMBOLS_ASSIGNED,
+        /** computed scope depths for symbols */
+        SCOPE_DEPTHS_COMPUTED,
+        /** method has had types calculated*/
+        OPTIMISTIC_TYPES_ASSIGNED,
+        /** method has had types calculated */
+        LOCAL_VARIABLE_TYPES_CALCULATED,
+        /** compile units reused (optional) */
+        COMPILE_UNITS_REUSED,
         /** method has been emitted to bytecode */
-        EMITTED
+        BYTECODE_GENERATED,
+        /** method has been installed */
+        BYTECODE_INSTALLED
     }
+
     /** Source of entity. */
     private final Source source;
 
+    /** Unique ID used for recompilation among other things */
+    private final int id;
+
     /** External function identifier. */
     @Ignore
     private final IdentNode ident;
 
-    /** Parsed version of functionNode */
-    @Ignore
-    private final FunctionNode snapshot;
-
     /** The body of the function node */
     private final Block body;
 
@@ -129,21 +149,19 @@
     @Ignore
     private final EnumSet<CompilationState> compilationState;
 
+    /** Number of properties of "this" object assigned in this function */
     @Ignore
-    private final Compiler.Hints hints;
-
-    /** Properties of this object assigned in this function */
-    @Ignore
-    private HashSet<String> thisProperties;
+    private final int thisProperties;
 
     /** Function flags. */
     private final int flags;
 
-    /** //@ sourceURL or //# sourceURL for program function nodes */
-    private final String sourceURL;
-
+    /** Line number of function start */
     private final int lineNumber;
 
+    /** Root class for function */
+    private final Class<?> rootClass;
+
     /** Is anonymous function flag. */
     public static final int IS_ANONYMOUS                = 1 << 0;
 
@@ -156,7 +174,7 @@
     /** Does the function use the "arguments" identifier ? */
     public static final int USES_ARGUMENTS              = 1 << 3;
 
-    /** Has this node been split because it was too large? */
+    /** Has this function been split because it was too large? */
     public static final int IS_SPLIT                    = 1 << 4;
 
     /** Does the function call eval? If it does, then all variables in this function might be get/set by it and it can
@@ -182,36 +200,90 @@
     /** Does this function or any of its descendants use variables from an ancestor function's scope (incl. globals)? */
     public static final int USES_ANCESTOR_SCOPE         = 1 << 9;
 
-    /** Is this function lazily compiled? */
-    public static final int IS_LAZY                     = 1 << 10;
-
-    /** Does this function have lazy, yet uncompiled children */
-    public static final int HAS_LAZY_CHILDREN           = 1 << 11;
-
-    /** Does this function have lazy, yet uncompiled children */
-    public static final int IS_PROGRAM                  = 1 << 12;
-
     /** Does this function have nested declarations? */
-    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 13;
+    public static final int HAS_FUNCTION_DECLARATIONS   = 1 << 10;
 
-    /** Can this function be specialized? */
-    public static final int CAN_SPECIALIZE              = 1 << 14;
+    /** Does this function have optimistic expressions? (If it does, it can undergo deoptimizing recompilation.) */
+    public static final int IS_DEOPTIMIZABLE            = 1 << 11;
+
+    /** Are we vararg, but do we just pass the arguments along to apply or call */
+    public static final int HAS_APPLY_TO_CALL_SPECIALIZATION = 1 << 12;
+
+    /** Does this function explicitly use the {@link CompilerConstants#RETURN} symbol? Some functions are known to
+     * always use the return symbol, namely a function that is a program (as it must track its last executed expression
+     * statement's value) as well as functions that are split (to communicate return values from inner to outer
+     * partitions). Other functions normally don't use the return symbol (so we optimize away its slot), except in some
+     * very special cases, e.g. when containing a return statement in a finally block. These special cases set this
+     * flag. */
+    public static final int USES_RETURN_SYMBOL = 1 << 13;
+
+    /**
+     * Is this function the top-level program?
+     */
+    public static final int IS_PROGRAM = 1 << 14;
+
+    /**
+     * Flag indicating whether this function uses the local variable symbol for itself. Only named function expressions
+     * can have this flag set if they reference themselves (e.g. "(function f() { return f })". Declared functions will
+     * use the symbol in their parent scope instead when they reference themselves by name.
+     */
+    public static final int USES_SELF_SYMBOL = 1 << 15;
 
     /** Does this function use the "this" keyword? */
-    public static final int USES_THIS                   = 1 << 15;
+    public static final int USES_THIS = 1 << 16;
+
+    /** Is this declared in a dynamic context */
+    public static final int IN_DYNAMIC_CONTEXT = 1 << 17;
+
+    /**
+     * The following flags are derived from directive comments within this function.
+     * Note that even IS_STRICT is one such flag but that requires special handling.
+     */
+
+    // parser, lower debugging this function
+    public static final int IS_PRINT_PARSE       = 1 << 18;
+    public static final int IS_PRINT_LOWER_PARSE = 1 << 19;
+    public static final int IS_PRINT_AST         = 1 << 20;
+    public static final int IS_PRINT_LOWER_AST   = 1 << 21;
+    public static final int IS_PRINT_SYMBOLS     = 1 << 22;
+
+    /** profile callsites in this function? */
+    public static final int IS_PROFILE         = 1 << 23;
+
+    // callsite tracing, profiling within this function
+    /** trace callsite enterexit in this function? */
+    public static final int IS_TRACE_ENTEREXIT = 1 << 24;
+
+    /** trace callsite misses in this function? */
+    public static final int IS_TRACE_MISSES    = 1 << 25;
+
+    /** trace callsite values in this function? */
+    public static final int IS_TRACE_VALUES    = 1 << 26;
+
+    /** extension callsite flags mask */
+    public static final int EXTENSION_CALLSITE_FLAGS = IS_PRINT_PARSE |
+        IS_PRINT_LOWER_PARSE | IS_PRINT_AST | IS_PRINT_LOWER_AST |
+        IS_PRINT_SYMBOLS | IS_PROFILE | IS_TRACE_ENTEREXIT |
+        IS_TRACE_MISSES | IS_TRACE_VALUES;
 
     /** Does this function or any nested functions contain an eval? */
     private static final int HAS_DEEP_EVAL = HAS_EVAL | HAS_NESTED_EVAL;
 
     /** Does this function need to store all its variables in scope? */
-    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL | IS_SPLIT | HAS_LAZY_CHILDREN;
+    private static final int HAS_ALL_VARS_IN_SCOPE = HAS_DEEP_EVAL;
 
     /** Does this function potentially need "arguments"? Note that this is not a full test, as further negative check of REDEFINES_ARGS is needed. */
     private static final int MAYBE_NEEDS_ARGUMENTS = USES_ARGUMENTS | HAS_EVAL;
 
     /** Does this function need the parent scope? It needs it if either it or its descendants use variables from it, or have a deep eval.
      *  We also pessimistically need a parent scope if we have lazy children that have not yet been compiled */
-    private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL | HAS_LAZY_CHILDREN;
+    private static final int NEEDS_PARENT_SCOPE = USES_ANCESTOR_SCOPE | HAS_DEEP_EVAL;
+
+    /** Used to signify "null", e.g. if someone asks for the parent of the program node */
+    public static final int NO_FUNCTION_ID = 0;
+
+    /** Where to start assigning global and unique function node ids */
+    public static final int FIRST_FUNCTION_ID = NO_FUNCTION_ID + 1;
 
     /** What is the return type of this function? */
     private Type returnType = Type.UNKNOWN;
@@ -220,6 +292,7 @@
      * Constructor
      *
      * @param source     the source
+     * @param id         unique id
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
@@ -230,10 +303,10 @@
      * @param parameters parameter list
      * @param kind       kind of function as in {@link FunctionNode.Kind}
      * @param flags      initial flags
-     * @param sourceURL  sourceURL specified in script (optional)
      */
     public FunctionNode(
         final Source source,
+        final int id,
         final int lineNumber,
         final long token,
         final int finish,
@@ -243,11 +316,11 @@
         final String name,
         final List<IdentNode> parameters,
         final FunctionNode.Kind kind,
-        final int flags,
-        final String sourceURL) {
+        final int flags) {
         super(token, finish);
 
         this.source           = source;
+        this.id               = id;
         this.lineNumber       = lineNumber;
         this.ident            = ident;
         this.name             = name;
@@ -259,30 +332,28 @@
         this.compilationState = EnumSet.of(CompilationState.INITIALIZED);
         this.declaredSymbols  = new HashSet<>();
         this.flags            = flags;
-        this.sourceURL        = sourceURL;
         this.compileUnit      = null;
         this.body             = null;
-        this.snapshot         = null;
-        this.hints            = null;
+        this.thisProperties   = 0;
+        this.rootClass        = null;
     }
 
     private FunctionNode(
         final FunctionNode functionNode,
         final long lastToken,
         final int flags,
-        final String sourceURL,
         final String name,
         final Type returnType,
         final CompileUnit compileUnit,
         final EnumSet<CompilationState> compilationState,
         final Block body,
         final List<IdentNode> parameters,
-        final FunctionNode snapshot,
-        final Compiler.Hints hints) {
+        final int thisProperties,
+        final Class<?> rootClass) {
         super(functionNode);
+
         this.lineNumber       = functionNode.lineNumber;
         this.flags            = flags;
-        this.sourceURL        = sourceURL;
         this.name             = name;
         this.returnType       = returnType;
         this.compileUnit      = compileUnit;
@@ -290,17 +361,17 @@
         this.compilationState = compilationState;
         this.body             = body;
         this.parameters       = parameters;
-        this.snapshot         = snapshot;
-        this.hints            = hints;
+        this.thisProperties   = thisProperties;
+        this.rootClass        = rootClass;
 
         // the fields below never change - they are final and assigned in constructor
         this.source          = functionNode.source;
+        this.id              = functionNode.id;
         this.ident           = functionNode.ident;
         this.namespace       = functionNode.namespace;
         this.declaredSymbols = functionNode.declaredSymbols;
         this.kind            = functionNode.kind;
         this.firstToken      = functionNode.firstToken;
-        this.thisProperties  = functionNode.thisProperties;
     }
 
     @Override
@@ -312,6 +383,50 @@
     }
 
     /**
+     * Visits the parameter nodes of this function. Parameters are normally not visited automatically.
+     * @param visitor the visitor to apply to the nodes.
+     * @return a list of parameter nodes, potentially modified from original ones by the visitor.
+     */
+    public List<IdentNode> visitParameters(final NodeVisitor<? extends LexicalContext> visitor) {
+        return Node.accept(visitor, parameters);
+    }
+
+    /**
+     * Get additional callsite flags to be used specific to this function.
+     *
+     * @return callsite flags
+     */
+    public int getCallSiteFlags() {
+        int callsiteFlags = 0;
+        if (getFlag(IS_STRICT)) {
+            callsiteFlags |= CALLSITE_STRICT;
+        }
+
+        // quick check for extension callsite flags turned on by directives.
+        if ((flags & EXTENSION_CALLSITE_FLAGS) == 0) {
+            return callsiteFlags;
+        }
+
+        if (getFlag(IS_PROFILE)) {
+            callsiteFlags |= CALLSITE_PROFILE;
+        }
+
+        if (getFlag(IS_TRACE_MISSES)) {
+            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_MISSES;
+        }
+
+        if (getFlag(IS_TRACE_VALUES)) {
+            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT | CALLSITE_TRACE_VALUES;
+        }
+
+        if (getFlag(IS_TRACE_ENTEREXIT)) {
+            callsiteFlags |= CALLSITE_TRACE | CALLSITE_TRACE_ENTEREXIT;
+        }
+
+        return callsiteFlags;
+    }
+
+    /**
      * Get the source for this function
      * @return the source
      */
@@ -320,35 +435,63 @@
     }
 
     /**
+     * Get the unique ID for this function
+     * @return the id
+     */
+    public int getId() {
+        return id;
+    }
+
+    /**
      * get source name - sourceURL or name derived from Source.
      *
      * @return name for the script source
      */
     public String getSourceName() {
-        return (sourceURL != null)? sourceURL : source.getName();
+        return getSourceName(source);
     }
 
     /**
-     * get the sourceURL
-     * @return the sourceURL
-     */
-    public String getSourceURL() {
-        return sourceURL;
-    }
-
-    /**
-     * Set the sourceURL
+     * Static source name getter
      *
-     * @param lc lexical context
-     * @param newSourceURL source url string to set
-     * @return function node or a new one if state was changed
+     * @param source the source
+     * @return source name
      */
-    public FunctionNode setSourceURL(final LexicalContext lc, final String newSourceURL) {
-        if (Objects.equals(sourceURL, newSourceURL)) {
-            return this;
-        }
+    public static String getSourceName(final Source source) {
+        final String explicitURL = source.getExplicitURL();
+        return explicitURL != null ? explicitURL : source.getName();
+    }
 
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, newSourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
+    /**
+     * Function to parse nashorn per-function extension directive comments.
+     *
+     * @param directive nashorn extension directive string
+     * @return integer flag for the given directive.
+     */
+    public static int getDirectiveFlag(final String directive) {
+        switch (directive) {
+            case "nashorn callsite trace enterexit":
+                return IS_TRACE_ENTEREXIT;
+            case "nashorn callsite trace misses":
+                return IS_TRACE_MISSES;
+            case "nashorn callsite trace objects":
+                return IS_TRACE_VALUES;
+            case "nashorn callsite profile":
+                return IS_PROFILE;
+            case "nashorn print parse":
+                return IS_PRINT_PARSE;
+            case "nashorn print lower parse":
+                return IS_PRINT_LOWER_PARSE;
+            case "nashorn print ast":
+                return IS_PRINT_AST;
+            case "nashorn print lower ast":
+                return IS_PRINT_LOWER_AST;
+            case "nashorn print symbols":
+                return IS_PRINT_SYMBOLS;
+            default:
+                // unknown/unsupported directive
+                return 0;
+        }
     }
 
     /**
@@ -360,53 +503,6 @@
     }
 
     /**
-     * Get the version of this function node's code as it looked upon construction
-     * i.e typically parsed and nothing else
-     * @return initial version of function node
-     */
-    public FunctionNode getSnapshot() {
-        return snapshot;
-    }
-
-    /**
-     * Throw away the snapshot, if any, to save memory. Used when heuristic
-     * determines that a method is not worth specializing
-     *
-     * @param lc lexical context
-     * @return new function node if a snapshot was present, now with snapsnot null
-     */
-    public FunctionNode clearSnapshot(final LexicalContext lc) {
-        if (this.snapshot == null) {
-            return this;
-        }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, null, hints));
-    }
-
-    /**
-     * Take a snapshot of this function node at a given point in time
-     * and store it in the function node
-     * @param lc lexical context
-     * @return function node
-     */
-    public FunctionNode snapshot(final LexicalContext lc) {
-        if (this.snapshot == this) {
-            return this;
-        }
-        if (isProgram() || parameters.isEmpty()) {
-            return this; //never specialize anything that won't be recompiled
-        }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, this, hints));
-    }
-
-    /**
-     * Can this function node be regenerated with more specific type args?
-     * @return true if specialization is possible
-     */
-    public boolean canSpecialize() {
-        return snapshot != null && getFlag(CAN_SPECIALIZE);
-    }
-
-    /**
      * Get the compilation state of this function
      * @return the compilation state
      */
@@ -421,21 +517,7 @@
      * @return true of the node is in the given state
      */
     public boolean hasState(final EnumSet<CompilationState> state) {
-        return compilationState.equals(state);
-    }
-
-    /**
-     * Check whether the state of this FunctionNode contains a given compilation
-     * state.
-     *
-     * A node can be in many states at once, e.g. both lowered and initialized.
-     * To check for an exact state, use {FunctionNode{@link #hasState(EnumSet)}
-     *
-     * @param state state to check for
-     * @return true if state is present in the total compilation state of this FunctionNode
-     */
-    public boolean hasState(final CompilationState state) {
-        return compilationState.contains(state);
+        return !AssertsEnabled.assertsEnabled() || compilationState.containsAll(state);
     }
 
     /**
@@ -448,33 +530,26 @@
      * @return function node or a new one if state was changed
      */
     public FunctionNode setState(final LexicalContext lc, final CompilationState state) {
-        if (this.compilationState.contains(state)) {
+        if (!AssertsEnabled.assertsEnabled() || this.compilationState.contains(state)) {
             return this;
         }
         final EnumSet<CompilationState> newState = EnumSet.copyOf(this.compilationState);
         newState.add(state);
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, newState, body, parameters, snapshot, hints));
-    }
-
-    /**
-     * Get any compiler hints that may associated with the function
-     * @return compiler hints
-     */
-    public Compiler.Hints getHints() {
-        return this.hints == null ? Compiler.Hints.EMPTY : hints;
-    }
-
-    /**
-     * Set compiler hints for this function
-     * @param lc    lexical context
-     * @param hints compiler hints
-     * @return new function if hints changed
-     */
-    public FunctionNode setHints(final LexicalContext lc, final Compiler.Hints hints) {
-        if (this.hints == hints) {
-            return this;
-        }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        newState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
@@ -486,48 +561,66 @@
         return namespace.uniqueName(base);
     }
 
-
     @Override
-    public void toString(final StringBuilder sb) {
-        sb.append('[');
-        sb.append(returnType);
-        sb.append(']');
-        sb.append(' ');
+    public void toString(final StringBuilder sb, final boolean printTypes) {
+        sb.append('[').
+            append(returnType).
+            append(']').
+            append(' ');
 
         sb.append("function");
 
         if (ident != null) {
             sb.append(' ');
-            ident.toString(sb);
+            ident.toString(sb, printTypes);
         }
 
         sb.append('(');
-        boolean first = true;
 
-        for (final IdentNode parameter : parameters) {
-            if (!first) {
-                sb.append(", ");
-            } else {
-                first = false;
+        for (final Iterator<IdentNode> iter = parameters.iterator(); iter.hasNext(); ) {
+            final IdentNode parameter = iter.next();
+            if (parameter.getSymbol() != null) {
+                sb.append('[').append(parameter.getType()).append(']').append(' ');
             }
-
-            parameter.toString(sb);
+            parameter.toString(sb, printTypes);
+            if (iter.hasNext()) {
+                sb.append(", ");
+            }
         }
 
         sb.append(')');
     }
 
     @Override
+    public int getFlags() {
+        return flags;
+    }
+
+    @Override
     public boolean getFlag(final int flag) {
         return (flags & flag) != 0;
     }
 
     @Override
-    public FunctionNode setFlags(final LexicalContext lc, int flags) {
+    public FunctionNode setFlags(final LexicalContext lc, final int flags) {
         if (this.flags == flags) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     @Override
@@ -549,11 +642,11 @@
     }
 
     /**
-     * Should this function node be lazily code generated, i.e. first at link time
-     * @return true if lazy
+     * Returns true if the function contains at least one optimistic operation (and thus can be deoptimized).
+     * @return true if the function contains at least one optimistic operation (and thus can be deoptimized).
      */
-    public boolean isLazy() {
-        return getFlag(IS_LAZY);
+    public boolean canBeDeoptimized() {
+        return getFlag(IS_DEOPTIMIZABLE);
     }
 
     /**
@@ -587,10 +680,21 @@
      * (since it exposes {@code arguments.callee} property) will need to have a callee parameter. We also return true
      * for split functions to make sure symbols slots are the same in the main and split methods.
      *
+     * A function that has had an apply(this,arguments) turned into a call doesn't need arguments anymore, but still
+     * has to fit the old callsite, thus, we require a dummy callee parameter for those functions as well
+     *
      * @return true if the function's generated Java method needs a {@code callee} parameter.
      */
     public boolean needsCallee() {
-        return needsParentScope() || needsSelfSymbol() || isSplit() || (needsArguments() && !isStrict());
+        return needsParentScope() || usesSelfSymbol() || isSplit() || (needsArguments() && !isStrict()) || hasOptimisticApplyToCall();
+    }
+
+    /**
+     * Check if this function uses the return symbol
+     * @return true if uses the return symbol
+     */
+    public boolean usesReturnSymbol() {
+        return isProgram() || isSplit() || getFlag(USES_RETURN_SYMBOL);
     }
 
     /**
@@ -602,6 +706,15 @@
         return getFlag(USES_THIS);
     }
 
+
+    /**
+     * Return true if function contains an apply to call transform
+     * @return true if this function has transformed apply to call
+     */
+    public boolean hasOptimisticApplyToCall() {
+        return getFlag(HAS_APPLY_TO_CALL_SPECIALIZATION);
+    }
+
     /**
      * Get the identifier for this function, this is its symbol.
      * @return the identifier as an IdentityNode
@@ -643,10 +756,27 @@
      * @return new function node if body changed, same if not
      */
     public FunctionNode setBody(final LexicalContext lc, final Block body) {
-        if(this.body == body) {
+        if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags | (body.needsScope() ? FunctionNode.HAS_SCOPE_BLOCK : 0), sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags |
+                            (body.needsScope() ?
+                                    FunctionNode.HAS_SCOPE_BLOCK :
+                                    0),
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
@@ -662,6 +792,36 @@
     }
 
     /**
+     * Was this function declared in a dynamic context, i.e. in a with or eval style
+     * chain
+     * @return true if in dynamic context
+     */
+    public boolean inDynamicContext() {
+        return getFlag(IN_DYNAMIC_CONTEXT);
+    }
+
+    /**
+     * Check whether a function would need dynamic scope, which is does if it has
+     * evals and isn't strict.
+     * @return true if dynamic scope is needed
+     */
+    public boolean needsDynamicScope() {
+        // Function has a direct eval in it (so a top-level "var ..." in the eval code can introduce a new
+        // variable into the function's scope), and it isn't strict (as evals in strict functions get an
+        // isolated scope).
+        return hasEval() && !isStrict();
+    }
+
+    /**
+     * Flag this function as declared in a dynamic context
+     * @param lc lexical context
+     * @return new function node, or same if unmodified
+     */
+    public FunctionNode setInDynamicContext(final LexicalContext lc) {
+        return setFlag(lc, IN_DYNAMIC_CONTEXT);
+    }
+
+    /**
      * Returns true if this function needs to have an Arguments object defined as a local variable named "arguments".
      * Functions that use "arguments" as identifier and don't define it as a name of a parameter or a nested function
      * (see ECMAScript 5.1 Chapter 10.5), as well as any function that uses eval or with, or has a nested function that
@@ -688,22 +848,38 @@
     }
 
     /**
-     * Register a property assigned to the this object in this function.
-     * @param key the property name
+     * Set the number of properties assigned to the this object in this function.
+     * @param lc the current lexical context.
+     * @param thisProperties number of properties
+     * @return a potentially modified function node
      */
-    public void addThisProperty(final String key) {
-        if (thisProperties == null) {
-            thisProperties = new HashSet<>();
+    public FunctionNode setThisProperties(final LexicalContext lc, final int thisProperties) {
+        if (this.thisProperties == thisProperties) {
+            return this;
         }
-        thisProperties.add(key);
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
      * Get the number of properties assigned to the this object in this function.
      * @return number of properties
      */
-    public int countThisProperties() {
-        return thisProperties == null ? 0 : thisProperties.size();
+    public int getThisProperties() {
+        return thisProperties;
     }
 
     /**
@@ -741,7 +917,21 @@
         if (this.lastToken == lastToken) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
@@ -752,7 +942,6 @@
         return name;
     }
 
-
     /**
      * Set the internal name for this function
      * @param lc    lexical context
@@ -763,7 +952,21 @@
         if (this.name.equals(name)) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
@@ -786,15 +989,6 @@
     }
 
     /**
-     * Checks if this function has yet-to-be-generated child functions
-     *
-     * @return true if there are lazy child functions
-     */
-    public boolean hasLazyChildren() {
-        return getFlag(HAS_LAZY_CHILDREN);
-    }
-
-    /**
      * Get the parameters to this function
      * @return a list of IdentNodes which represent the function parameters, in order
      */
@@ -803,6 +997,16 @@
     }
 
     /**
+     * Returns the identifier for a named parameter at the specified position in this function's parameter list.
+     * @param index the parameter's position.
+     * @return the identifier for the requested named parameter.
+     * @throws IndexOutOfBoundsException if the index is invalid.
+     */
+    public IdentNode getParameter(final int index) {
+        return parameters.get(index);
+    }
+
+    /**
      * Reset the compile unit used to compile this function
      * @see Compiler
      * @param  lc lexical context
@@ -813,7 +1017,21 @@
         if (this.parameters == parameters) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
@@ -833,16 +1051,22 @@
     }
 
     /**
-     * Does this function need a self symbol - this is needed only for self
-     * referring functions
-     * @return true if function needs a symbol for self
+     * Does this function use its self symbol - this is needed only for self-referencing named function expressions.
+     * Self-referencing declared functions won't have this flag set, as they can access their own symbol through the
+     * scope (since they're bound to the symbol with their name in their enclosing scope).
+     * @return true if this function node is a named function expression that uses the symbol for itself.
      */
-    public boolean needsSelfSymbol() {
-        return body.getFlag(Block.NEEDS_SELF_SYMBOL);
+    public boolean usesSelfSymbol() {
+        return getFlag(USES_SELF_SYMBOL);
     }
 
     @Override
-    public Type getType() {
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        return FUNCTION_TYPE;
+    }
+
+    @Override
+    public Type getWidestOperationType() {
         return FUNCTION_TYPE;
     }
 
@@ -867,10 +1091,10 @@
         //we never bother with object types narrower than objects, that will lead to byte code verification errors
         //as for instance even if we know we are returning a string from a method, the code generator will always
         //treat it as an object, at least for now
-        if (this.returnType == returnType) {
+        final Type type = returnType.isObject() ? Type.OBJECT : returnType;
+        if (this.returnType == type) {
             return this;
         }
-        final Type type = Type.widest(this.returnType, returnType.isObject() ? Type.OBJECT : returnType);
         return Node.replaceInLexicalContext(
             lc,
             this,
@@ -878,16 +1102,16 @@
                 this,
                 lastToken,
                 flags,
-                sourceURL,
                 name,
                 type,
                 compileUnit,
                 compilationState,
-                body.setReturnType(type),
+                body,
                 parameters,
-                snapshot,
-                hints));
-    }
+                thisProperties,
+                rootClass
+                ));
+   }
 
     /**
      * Check if the function is generated in strict mode
@@ -917,7 +1141,21 @@
         if (this.compileUnit == compileUnit) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new FunctionNode(this, lastToken, flags, sourceURL, name, returnType, compileUnit, compilationState, body, parameters, snapshot, hints));
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
     }
 
     /**
@@ -938,4 +1176,40 @@
     public Symbol compilerConstant(final CompilerConstants cc) {
         return body.getExistingSymbol(cc.symbolName());
     }
+
+    /**
+     * Get the root class that this function node compiles to
+     * @return root class
+     */
+    public Class<?> getRootClass() {
+        return rootClass;
+    }
+
+    /**
+     * Reset the root class that this function is compiled to
+     * @see Compiler
+     * @param lc lexical context
+     * @param rootClass root class
+     * @return function node or a new one if state was changed
+     */
+    public FunctionNode setRootClass(final LexicalContext lc, final Class<?> rootClass) {
+        if (this.rootClass == rootClass) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(
+                lc,
+                this,
+                new FunctionNode(
+                        this,
+                        lastToken,
+                        flags,
+                        name,
+                        returnType,
+                        compileUnit,
+                        compilationState,
+                        body,
+                        parameters,
+                        thisProperties,
+                        rootClass));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java
index 30e8ed1..2450197 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/IdentNode.java
@@ -28,16 +28,20 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.__DIR__;
 import static jdk.nashorn.internal.codegen.CompilerConstants.__FILE__;
 import static jdk.nashorn.internal.codegen.CompilerConstants.__LINE__;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.Token;
+import jdk.nashorn.internal.parser.TokenType;
 
 /**
  * IR representation for an identifier.
  */
 @Immutable
-public final class IdentNode extends Expression implements PropertyKey, FunctionCall {
+public final class IdentNode extends Expression implements PropertyKey, FunctionCall, Optimistic, JoinPredecessor {
     private static final int PROPERTY_NAME     = 1 << 0;
     private static final int INITIALIZED_HERE  = 1 << 1;
     private static final int FUNCTION          = 1 << 2;
@@ -46,11 +50,18 @@
     /** Identifier. */
     private final String name;
 
-    /** Type for a callsite, e.g. X in a get()X or a set(X)V */
-    private final Type callSiteType;
+    /** Optimistic type */
+    private final Type type;
 
     private final int flags;
 
+    private final int programPoint;
+
+    private final LocalVariableConversion conversion;
+
+    private Symbol symbol;
+
+
     /**
      * Constructor
      *
@@ -60,16 +71,21 @@
      */
     public IdentNode(final long token, final int finish, final String name) {
         super(token, finish);
-        this.name = name.intern();
-        this.callSiteType = null;
+        this.name = name;
+        this.type = null;
         this.flags = 0;
+        this.programPoint = INVALID_PROGRAM_POINT;
+        this.conversion = null;
     }
 
-    private IdentNode(final IdentNode identNode, final String name, final Type callSiteType, final int flags) {
+    private IdentNode(final IdentNode identNode, final String name, final Type type, final int flags, final int programPoint, final LocalVariableConversion conversion) {
         super(identNode);
         this.name = name;
-        this.callSiteType = callSiteType;
+        this.type = type;
         this.flags = flags;
+        this.programPoint = programPoint;
+        this.conversion = conversion;
+        this.symbol = identNode.symbol;
     }
 
     /**
@@ -79,24 +95,33 @@
      */
     public IdentNode(final IdentNode identNode) {
         super(identNode);
-        this.name         = identNode.getName();
-        this.callSiteType = null;
-        this.flags        = identNode.flags;
+        this.name = identNode.getName();
+        this.type = identNode.type;
+        this.flags = identNode.flags;
+        this.conversion = identNode.conversion;
+        this.programPoint = INVALID_PROGRAM_POINT;
+        this.symbol = identNode.symbol;
+    }
+
+    /**
+     * Creates an identifier for the symbol. Normally used by code generator for creating temporary storage identifiers
+     * that must contain both a symbol and a type.
+     * @param symbol the symbol to create a temporary identifier for.
+     * @return a temporary identifier for the symbol.
+     */
+    public static IdentNode createInternalIdentifier(final Symbol symbol) {
+        return new IdentNode(Token.toDesc(TokenType.IDENT, 0, 0), 0, symbol.getName()).setSymbol(symbol);
     }
 
     @Override
-    public Type getType() {
-        return callSiteType == null ? super.getType() : callSiteType;
-    }
-
-    @Override
-    public boolean isAtom() {
-        return true;
-    }
-
-    private boolean hasCallSiteType() {
-        //this is an identity that's part of a getter or setter
-        return callSiteType != null;
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        if(type != null) {
+            return type;
+        } else if(symbol != null && symbol.isScope()) {
+            return Type.OBJECT;
+        }
+        final Type symbolType = localVariableTypes.apply(symbol);
+        return symbolType == null ? Type.UNDEFINED : symbolType;
     }
 
     /**
@@ -114,14 +139,10 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        if (hasCallSiteType()) {
-            sb.append('{');
-            final String desc = getType().getDescriptor();
-            sb.append(desc.charAt(desc.length() - 1) == ';' ? 'O' : getType().getDescriptor());
-            sb.append('}');
+    public void toString(final StringBuilder sb, final boolean printType) {
+        if (printType) {
+            optimisticTypeToString(sb, symbol == null || !symbol.hasSlot());
         }
-
         sb.append(name);
     }
 
@@ -144,11 +165,36 @@
     }
 
     /**
+     * Return the Symbol the compiler has assigned to this identifier. The symbol is a description of the storage
+     * location for the identifier.
+     *
+     * @return the symbol
+     */
+    public Symbol getSymbol() {
+        return symbol;
+    }
+
+    /**
+     * Assign a symbol to this identifier. See {@link IdentNode#getSymbol()} for explanation of what a symbol is.
+     *
+     * @param symbol the symbol
+     * @return new node
+     */
+    public IdentNode setSymbol(final Symbol symbol) {
+        if (this.symbol == symbol) {
+            return this;
+        }
+        final IdentNode newIdent = (IdentNode)clone();
+        newIdent.symbol = symbol;
+        return newIdent;
+    }
+
+    /**
      * Check if this IdentNode is a property name
      * @return true if this is a property name
      */
     public boolean isPropertyName() {
-        return (flags & PROPERTY_NAME) != 0;
+        return (flags & PROPERTY_NAME) == PROPERTY_NAME;
     }
 
     /**
@@ -159,7 +205,7 @@
         if (isPropertyName()) {
             return this;
         }
-        return new IdentNode(this, name, callSiteType, flags | PROPERTY_NAME);
+        return new IdentNode(this, name, type, flags | PROPERTY_NAME, programPoint, conversion);
     }
 
     /**
@@ -167,7 +213,7 @@
      * @return true if this is a future strict name
      */
     public boolean isFutureStrictName() {
-        return (flags & FUTURESTRICT_NAME) != 0;
+        return (flags & FUTURESTRICT_NAME) == FUTURESTRICT_NAME;
     }
 
     /**
@@ -178,7 +224,7 @@
         if (isFutureStrictName()) {
             return this;
         }
-        return new IdentNode(this, name, callSiteType, flags | FUTURESTRICT_NAME);
+        return new IdentNode(this, name, type, flags | FUTURESTRICT_NAME, programPoint, conversion);
     }
 
     /**
@@ -186,7 +232,7 @@
      * @return true if IdentNode is initialized on creation
      */
     public boolean isInitializedHere() {
-        return (flags & INITIALIZED_HERE) != 0;
+        return (flags & INITIALIZED_HERE) == INITIALIZED_HERE;
     }
 
     /**
@@ -197,22 +243,30 @@
         if (isInitializedHere()) {
             return this;
         }
-        return new IdentNode(this, name, callSiteType, flags | INITIALIZED_HERE);
+        return new IdentNode(this, name, type, flags | INITIALIZED_HERE, programPoint, conversion);
     }
 
     /**
-     * Check if this IdentNode is a special identity, currently __DIR__, __FILE__
-     * or __LINE__
+     * Check if the name of this IdentNode is same as that of a compile-time property (currently __DIR__, __FILE__, and
+     * __LINE__).
      *
-     * @return true if this IdentNode is special
+     * @return true if this IdentNode's name is same as that of a compile-time property
      */
-    public boolean isSpecialIdentity() {
+    public boolean isCompileTimePropertyName() {
         return name.equals(__DIR__.symbolName()) || name.equals(__FILE__.symbolName()) || name.equals(__LINE__.symbolName());
     }
 
     @Override
     public boolean isFunction() {
-        return (flags & FUNCTION) != 0;
+        return (flags & FUNCTION) == FUNCTION;
+    }
+
+    @Override
+    public IdentNode setType(final Type type) {
+        if (this.type == type) {
+            return this;
+        }
+        return new IdentNode(this, name, type, flags, programPoint, conversion);
     }
 
     /**
@@ -223,6 +277,68 @@
         if (isFunction()) {
             return this;
         }
-        return new IdentNode(this, name, callSiteType, flags | FUNCTION);
+        return new IdentNode(this, name, type, flags | FUNCTION, programPoint, conversion);
+    }
+
+    /**
+     * Mark this node as not being the callee operand of a {@link CallNode}.
+     * @return an ident node identical to this one in all aspects except with its function flag unset.
+     */
+    public IdentNode setIsNotFunction() {
+        if (! isFunction()) {
+            return this;
+        }
+        return new IdentNode(this, name, type, flags & ~FUNCTION, programPoint, conversion);
+    }
+
+    @Override
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    @Override
+    public Optimistic setProgramPoint(final int programPoint) {
+        if (this.programPoint == programPoint) {
+            return this;
+        }
+        return new IdentNode(this, name, type, flags, programPoint, conversion);
+    }
+
+    @Override
+    public Type getMostOptimisticType() {
+        return Type.INT;
+    }
+
+    @Override
+    public Type getMostPessimisticType() {
+        return Type.OBJECT;
+    }
+
+    @Override
+    public boolean canBeOptimistic() {
+        return true;
+    }
+
+    @Override
+    public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return new IdentNode(this, name, type, flags, programPoint, conversion);
+    }
+
+    /**
+     * Is this an internal symbol, i.e. one that starts with ':'. Those can
+     * never be optimistic.
+     * @return true if internal symbol
+     */
+    public boolean isInternal() {
+        assert name != null;
+        return name.charAt(0) == ':';
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/IfNode.java b/nashorn/src/jdk/nashorn/internal/ir/IfNode.java
index 64e70d8..4561389 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/IfNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/IfNode.java
@@ -32,7 +32,7 @@
  * IR representation for an IF statement.
  */
 @Immutable
-public final class IfNode extends Statement {
+public final class IfNode extends Statement implements JoinPredecessor {
     /** Test expression. */
     private final Expression test;
 
@@ -43,6 +43,12 @@
     private final Block fail;
 
     /**
+     * Local variable conversions that need to be performed after test if it evaluates to false, and there's no else
+     * branch.
+     */
+    private final LocalVariableConversion conversion;
+
+    /**
      * Constructor
      *
      * @param lineNumber line number
@@ -57,13 +63,15 @@
         this.test = test;
         this.pass = pass;
         this.fail = fail;
+        this.conversion = null;
     }
 
-    private IfNode(final IfNode ifNode, final Expression test, final Block pass, final Block fail) {
+    private IfNode(final IfNode ifNode, final Expression test, final Block pass, final Block fail, final LocalVariableConversion conversion) {
         super(ifNode);
         this.test = test;
         this.pass = pass;
         this.fail = fail;
+        this.conversion = conversion;
     }
 
     @Override
@@ -84,9 +92,9 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printTypes) {
         sb.append("if (");
-        test.toString(sb);
+        test.toString(sb, printTypes);
         sb.append(')');
     }
 
@@ -102,7 +110,7 @@
         if (this.fail == fail) {
             return this;
         }
-        return new IfNode(this, test, pass, fail);
+        return new IfNode(this, test, pass, fail, conversion);
     }
 
     /**
@@ -117,7 +125,7 @@
         if (this.pass == pass) {
             return this;
         }
-        return new IfNode(this, test, pass, fail);
+        return new IfNode(this, test, pass, fail, conversion);
     }
 
     /**
@@ -137,6 +145,19 @@
         if (this.test == test) {
             return this;
         }
-        return new IfNode(this, test, pass, fail);
+        return new IfNode(this, test, pass, fail, conversion);
+    }
+
+    @Override
+    public IfNode setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return new IfNode(this, test, pass, fail, conversion);
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java b/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java
index 83f58ff..3d3c316 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/IndexNode.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.ir;
 
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
-
 /**
  * IR representation of an indexed access (brackets operator.)
  */
@@ -49,8 +49,8 @@
         this.index = index;
     }
 
-    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction) {
-        super(indexNode, base, isFunction);
+    private IndexNode(final IndexNode indexNode, final Expression base, final Expression index, final boolean isFunction, final Type type, final int programPoint) {
+        super(indexNode, base, isFunction, type, programPoint);
         this.index = index;
     }
 
@@ -65,21 +65,25 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         final boolean needsParen = tokenType().needsParens(base.tokenType(), true);
 
         if (needsParen) {
             sb.append('(');
         }
 
-        base.toString(sb);
+        if (printType) {
+            optimisticTypeToString(sb);
+        }
+
+        base.toString(sb, printType);
 
         if (needsParen) {
             sb.append(')');
         }
 
         sb.append('[');
-        index.toString(sb);
+        index.toString(sb, printType);
         sb.append(']');
     }
 
@@ -95,7 +99,7 @@
         if (this.base == base) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction());
+        return new IndexNode(this, base, index, isFunction(), type, programPoint);
     }
 
     /**
@@ -103,19 +107,34 @@
      * @param index new index expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public IndexNode setIndex(Expression index) {
+    public IndexNode setIndex(final Expression index) {
         if(this.index == index) {
             return this;
         }
-        return new IndexNode(this, base, index, isFunction());
+        return new IndexNode(this, base, index, isFunction(), type, programPoint);
     }
 
     @Override
-    public BaseNode setIsFunction() {
+    public IndexNode setType(final Type type) {
+        if (this.type == type) {
+            return this;
+        }
+        return new IndexNode(this, base, index, isFunction(), type, programPoint);
+    }
+
+    @Override
+    public IndexNode setIsFunction() {
         if (isFunction()) {
             return this;
         }
-        return new IndexNode(this, base, index, true);
+        return new IndexNode(this, base, index, true, type, programPoint);
     }
 
+    @Override
+    public IndexNode setProgramPoint(final int programPoint) {
+        if (this.programPoint == programPoint) {
+            return this;
+        }
+        return new IndexNode(this, base, index, isFunction(), type, programPoint);
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessor.java b/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessor.java
new file mode 100644
index 0000000..e55aec0
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessor.java
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+/**
+ * Interface implemented by AST nodes that either can occur as predecessors of a control flow join, or contain a control
+ * flow join themselves. JoinPredecessor only provides a getter and setter for a {@link LocalVariableConversion}; the
+ * semantics of control flow for a particular node implementing the interface are shared between
+ * {@code LocalVariableTypesCalculator} that creates the conversions, and {@code CodeGenerator} that uses them.
+ */
+public interface JoinPredecessor {
+    /**
+     * Set the local variable conversions needed to unify their types at a control flow join point.
+     * @param lc the current lexical context
+     * @param conversion the conversions.
+     * @return this node or a different node representing the change.
+     */
+    public JoinPredecessor setLocalVariableConversion(LexicalContext lc, LocalVariableConversion conversion);
+
+    /**
+     * Returns the local variable conversions needed to unify their types at a control flow join point.
+     * @return the local variable conversions needed to unify their types at a control flow join point. Can be null.
+     * Can contain {@link LocalVariableConversion#isLive() dead conversions}.
+     */
+    public LocalVariableConversion getLocalVariableConversion();
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java b/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
new file mode 100644
index 0000000..3242de2
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/JoinPredecessorExpression.java
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+
+/**
+ * A wrapper for an expression that is in a position to be a join predecessor.
+ */
+public class JoinPredecessorExpression extends Expression implements JoinPredecessor {
+
+    private final Expression expression;
+    private final LocalVariableConversion conversion;
+
+    /**
+     * A no-arg constructor does not wrap any expression on its own, but can be used as a place to contain a local
+     * variable conversion in a place where an expression can otherwise stand.
+     */
+    public JoinPredecessorExpression() {
+        this(null);
+    }
+
+    /**
+     * A constructor for wrapping an expression and making it a join predecessor. Typically used on true and false
+     * subexpressions of the ternary node as well as on the operands of short-circuiting logical expressions {@code &&}
+     * and {@code ||}.
+     * @param expression the expression to wrap
+     */
+    public JoinPredecessorExpression(final Expression expression) {
+        this(expression, null);
+    }
+
+    private JoinPredecessorExpression(final Expression expression, final LocalVariableConversion conversion) {
+        super(expression == null ? 0L : expression.getToken(), expression == null ? 0 : expression.getStart(), expression == null ? 0 : expression.getFinish());
+        this.expression = expression;
+        this.conversion = conversion;
+    }
+
+    @Override
+    public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(conversion == this.conversion) {
+            return this;
+        }
+        return new JoinPredecessorExpression(expression, conversion);
+    }
+
+    @Override
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        return expression.getType(localVariableTypes);
+    }
+
+    @Override
+    public boolean isAlwaysFalse() {
+        return expression != null && expression.isAlwaysFalse();
+    }
+
+    @Override
+    public boolean isAlwaysTrue() {
+        return expression != null && expression.isAlwaysTrue();
+    }
+
+    /**
+     * Returns the underlying expression.
+     * @return the underlying expression.
+     */
+    public Expression getExpression() {
+        return expression;
+    }
+
+    /**
+     * Sets the underlying expression.
+     * @param expression the new underlying expression
+     * @return this or modified join predecessor expression object.
+     */
+    public JoinPredecessorExpression setExpression(final Expression expression) {
+        if(expression == this.expression) {
+            return this;
+        }
+        return new JoinPredecessorExpression(expression, conversion);
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
+    }
+
+    @Override
+    public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+        if(visitor.enterJoinPredecessorExpression(this)) {
+            final Expression expr = getExpression();
+            return visitor.leaveJoinPredecessorExpression(expr == null ? this : setExpression((Expression)expr.accept(visitor)));
+        }
+        return this;
+    }
+
+    @Override
+    public void toString(final StringBuilder sb, final boolean printType) {
+        if(expression != null) {
+            expression.toString(sb, printType);
+        }
+        if(conversion != null) {
+            conversion.toString(sb);
+        }
+    }
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/JumpStatement.java b/nashorn/src/jdk/nashorn/internal/ir/JumpStatement.java
new file mode 100644
index 0000000..aabb9de
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/JumpStatement.java
@@ -0,0 +1,99 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+/**
+ * Common base class for jump statements (e.g. {@code break} and {@code continue}).
+ */
+public abstract class JumpStatement extends Statement implements JoinPredecessor {
+
+    private final String labelName;
+    private final LocalVariableConversion conversion;
+
+    /**
+     * Constructor
+     *
+     * @param lineNumber line number
+     * @param token      token
+     * @param finish     finish
+     * @param labelName  label name for break or null if none
+     */
+    protected JumpStatement(final int lineNumber, final long token, final int finish, final String labelName) {
+        super(lineNumber, token, finish);
+        this.labelName = labelName;
+        this.conversion = null;
+    }
+
+    /**
+     * Copy constructor.
+     * @param jumpStatement the original jump statement.
+     * @param conversion a new local variable conversion.
+     */
+    protected JumpStatement(final JumpStatement jumpStatement, final LocalVariableConversion conversion) {
+        super(jumpStatement);
+        this.labelName = jumpStatement.labelName;
+        this.conversion = conversion;
+    }
+
+    @Override
+    public boolean hasGoto() {
+        return true;
+    }
+
+    /**
+     * Get the label name for this break node
+     * @return label name, or null if none
+     */
+    public String getLabelName() {
+        return labelName;
+    }
+
+    @Override
+    public void toString(final StringBuilder sb, final boolean printType) {
+        sb.append(getStatementName());
+
+        if (labelName != null) {
+            sb.append(' ').append(labelName);
+        }
+    }
+
+    abstract String getStatementName();
+
+    @Override
+    public JumpStatement setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return createNewJumpStatement(conversion);
+    }
+
+    abstract JumpStatement createNewJumpStatement(LocalVariableConversion newConversion);
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java b/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java
index 9903c2b..17b97aa 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/LabelNode.java
@@ -29,36 +29,42 @@
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
 /**
- * IR representation for a labeled statement.
+ * IR representation for a labeled statement. It implements JoinPredecessor to hold conversions that need to be effected
+ * when the block exits normally, but is also targeted by a break statement that might bring different local variable
+ * types to the join at the break point.
  */
 @Immutable
-public final class LabelNode extends LexicalContextStatement {
+public final class LabelNode extends LexicalContextStatement implements JoinPredecessor {
     /** Label ident. */
-    private final IdentNode label;
+    private final String labelName;
 
     /** Statements. */
     private final Block body;
 
+    private final LocalVariableConversion localVariableConversion;
+
     /**
      * Constructor
      *
      * @param lineNumber line number
      * @param token      token
      * @param finish     finish
-     * @param label      label identifier
+     * @param labelName  label name
      * @param body       body of label node
      */
-    public LabelNode(final int lineNumber, final long token, final int finish, final IdentNode label, final Block body) {
+    public LabelNode(final int lineNumber, final long token, final int finish, final String labelName, final Block body) {
         super(lineNumber, token, finish);
 
-        this.label = label;
+        this.labelName = labelName;
         this.body  = body;
+        this.localVariableConversion = null;
     }
 
-    private LabelNode(final LabelNode labelNode, final IdentNode label, final Block body) {
+    private LabelNode(final LabelNode labelNode, final String labelName, final Block body, final LocalVariableConversion localVariableConversion) {
         super(labelNode);
-        this.label = label;
-        this.body  = body;
+        this.labelName = labelName;
+        this.body = body;
+        this.localVariableConversion = localVariableConversion;
     }
 
     @Override
@@ -69,18 +75,15 @@
     @Override
     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterLabelNode(this)) {
-            return visitor.leaveLabelNode(
-                setLabel(lc, (IdentNode)label.accept(visitor)).
-                setBody(lc, (Block)body.accept(visitor)));
+            return visitor.leaveLabelNode(setBody(lc, (Block)body.accept(visitor)));
         }
 
         return this;
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        label.toString(sb);
-        sb.append(':');
+    public void toString(final StringBuilder sb, final boolean printType) {
+        sb.append(labelName).append(':');
     }
 
     /**
@@ -101,22 +104,27 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new LabelNode(this, label, body));
+        return Node.replaceInLexicalContext(lc, this, new LabelNode(this, labelName, body, localVariableConversion));
     }
 
     /**
-     * Get the identifier representing the label name
+     * Get the label name
      * @return the label
      */
-    public IdentNode getLabel() {
-        return label;
+    public String getLabelName() {
+        return labelName;
     }
 
-    private LabelNode setLabel(final LexicalContext lc, final IdentNode label) {
-        if (this.label == label) {
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return localVariableConversion;
+    }
+
+    @Override
+    public LabelNode setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion localVariableConversion) {
+        if(this.localVariableConversion == localVariableConversion) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new LabelNode(this, label, body));
+        return Node.replaceInLexicalContext(lc, this, new LabelNode(this, labelName, body, localVariableConversion));
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Labels.java b/nashorn/src/jdk/nashorn/internal/ir/Labels.java
new file mode 100644
index 0000000..ce5e9dc
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/Labels.java
@@ -0,0 +1,43 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import java.util.List;
+import jdk.nashorn.internal.codegen.Label;
+
+/**
+ * Interface that can be used to get a list of all labels in a node
+ */
+public interface Labels {
+
+    /**
+     * Return the labels associated with this node. Breakable nodes that
+     * aren't LoopNodes only have a break label - the location immediately
+     * afterwards the node in code
+     * @return list of labels representing locations around this node
+     */
+    public List<Label> getLabels();
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java b/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java
index 1b380d3..ef56ae1 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContext.java
@@ -27,7 +27,6 @@
 import java.io.File;
 import java.util.Iterator;
 import java.util.NoSuchElementException;
-import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.Source;
 
@@ -148,6 +147,7 @@
      * @return the node that was pushed
      */
     public <T extends LexicalContextNode> T push(final T node) {
+        assert !contains(node);
         if (sp == stack.length) {
             final LexicalContextNode[] newStack = new LexicalContextNode[sp * 2];
             System.arraycopy(stack, 0, newStack, 0, sp);
@@ -201,6 +201,18 @@
         return (T)popped;
     }
 
+    /**
+     * Explicitly apply flags to the topmost element on the stack. This is only valid to use from a
+     * {@code NodeVisitor.leaveXxx()} method and only on the node being exited at the time. It is not mandatory to use,
+     * as {@link #pop(LexicalContextNode)} will apply the flags automatically, but this method can be used to apply them
+     * during the {@code leaveXxx()} method in case its logic depends on the value of the flags.
+     * @param node the node to apply the flags to. Must be the topmost node on the stack.
+     * @return the passed in node, or a modified node (if any flags were modified)
+     */
+    public <T extends LexicalContextNode & Flags<T>> T applyTopFlags(final T node) {
+        assert node == peek();
+        return node.setFlag(this, flags[sp - 1]);
+    }
 
     /**
      * Return the top element in the context
@@ -233,10 +245,9 @@
      * @return the new node
      */
     public LexicalContextNode replace(final LexicalContextNode oldNode, final LexicalContextNode newNode) {
-       //System.err.println("REPLACE old=" + Debug.id(oldNode) + " new=" + Debug.id(newNode));
         for (int i = sp - 1; i >= 0; i--) {
             if (stack[i] == oldNode) {
-                assert i == (sp - 1) : "violation of contract - we always expect to find the replacement node on top of the lexical context stack: " + newNode + " has " + stack[i + 1].getClass() + " above it";
+                assert i == sp - 1 : "violation of contract - we always expect to find the replacement node on top of the lexical context stack: " + newNode + " has " + stack[i + 1].getClass() + " above it";
                 stack[i] = newNode;
                 break;
             }
@@ -271,6 +282,31 @@
     }
 
     /**
+     * Gets the label node of the current block.
+     * @return the label node of the current block, if it is labeled. Otherwise returns null.
+     */
+    public LabelNode getCurrentBlockLabelNode() {
+        assert stack[sp - 1] instanceof Block;
+        if(sp < 2) {
+            return null;
+        }
+        final LexicalContextNode parent = stack[sp - 2];
+        return parent instanceof LabelNode ? (LabelNode)parent : null;
+    }
+
+
+    /*
+    public FunctionNode getProgram() {
+        final Iterator<FunctionNode> iter = getFunctions();
+        FunctionNode last = null;
+        while (iter.hasNext()) {
+            last = iter.next();
+        }
+        assert last != null;
+        return last;
+    }*/
+
+    /**
      * Returns an iterator over all ancestors block of the given block, with its parent block first.
      * @param block the block whose ancestors are returned
      * @return an iterator over all ancestors block of the given block.
@@ -364,9 +400,6 @@
      * @return block in which the symbol is defined, assert if no such block in context
      */
     public Block getDefiningBlock(final Symbol symbol) {
-        if (symbol.isTemp()) {
-            return null;
-        }
         final String name = symbol.getName();
         for (final Iterator<Block> it = getBlocks(); it.hasNext();) {
             final Block next = it.next();
@@ -382,10 +415,7 @@
      * @param symbol symbol
      * @return function node in which this symbol is defined, assert if no such symbol exists in context
      */
-    public FunctionNode getDefiningFunction(Symbol symbol) {
-        if (symbol.isTemp()) {
-            return null;
-        }
+    public FunctionNode getDefiningFunction(final Symbol symbol) {
         final String name = symbol.getName();
         for (final Iterator<LexicalContextNode> iter = new NodeIterator<>(LexicalContextNode.class); iter.hasNext();) {
             final LexicalContextNode next = iter.next();
@@ -393,7 +423,7 @@
                 while (iter.hasNext()) {
                     final LexicalContextNode next2 = iter.next();
                     if (next2 instanceof FunctionNode) {
-                        return ((FunctionNode)next2);
+                        return (FunctionNode)next2;
                     }
                 }
                 throw new AssertionError("Defining block for symbol " + name + " has no function in the context");
@@ -411,22 +441,6 @@
     }
 
     /**
-     * Returns true if the expression defining the function is a callee of a CallNode that should be the second
-     * element on the stack, e.g. <code>(function(){})()</code>. That is, if the stack ends with
-     * {@code [..., CallNode, FunctionNode]} then {@code callNode.getFunction()} should be equal to
-     * {@code functionNode}, and the top of the stack should itself be a variant of {@code functionNode}.
-     * @param functionNode the function node being tested
-     * @return true if the expression defining the current function is a callee of a call expression.
-     */
-    public boolean isFunctionDefinedInCurrentCall(FunctionNode functionNode) {
-        final LexicalContextNode parent = stack[sp - 2];
-        if (parent instanceof CallNode && ((CallNode)parent).getFunction() == functionNode) {
-            return true;
-        }
-        return false;
-    }
-
-    /**
      * Get the parent function for a function in the lexical context
      * @param functionNode function for which to get parent
      * @return parent function of functionNode or null if none (e.g. if functionNode is the program)
@@ -444,15 +458,29 @@
     }
 
     /**
-     * Count the number of with scopes until a given node
-     * @param until node to stop counting at, or null if all nodes should be counted
+     * Count the number of scopes until a given node. Note that this method is solely used to figure out the number of
+     * scopes that need to be explicitly popped in order to perform a break or continue jump within the current bytecode
+     * method. For this reason, the method returns 0 if it encounters a {@code SplitNode} between the current location
+     * and the break/continue target.
+     * @param until node to stop counting at. Must be within the current  function
      * @return number of with scopes encountered in the context
      */
     public int getScopeNestingLevelTo(final LexicalContextNode until) {
+        assert until != null;
         //count the number of with nodes until "until" is hit
         int n = 0;
-        for (final Iterator<WithNode> iter = new NodeIterator<>(WithNode.class, until); iter.hasNext(); iter.next()) {
-            n++;
+        for (final Iterator<LexicalContextNode> iter = getAllNodes(); iter.hasNext();) {
+            final LexicalContextNode node = iter.next();
+            if (node == until) {
+                break;
+            } else if (node instanceof SplitNode) {
+                // Don't bother popping scopes if we're going to do a return from a split method anyway.
+                return 0;
+            }
+            assert !(node instanceof FunctionNode); // Can't go outside current function
+            if (node instanceof WithNode || node instanceof Block && ((Block)node).needsScope()) {
+                n++;
+            }
         }
         return n;
     }
@@ -486,12 +514,13 @@
 
     /**
      * Find the breakable node corresponding to this label.
-     * @param label label to search for, if null the closest breakable node will be returned unconditionally, e.g. a while loop with no label
+     * @param labelName name of the label to search for. If null, the closest breakable node will be returned
+     * unconditionally, e.g. a while loop with no label
      * @return closest breakable node
      */
-    public BreakableNode getBreakable(final IdentNode label) {
-        if (label != null) {
-            final LabelNode foundLabel = findLabel(label.getName());
+    public BreakableNode getBreakable(final String labelName) {
+        if (labelName != null) {
+            final LabelNode foundLabel = findLabel(labelName);
             if (foundLabel != null) {
                 // iterate to the nearest breakable to the foundLabel
                 BreakableNode breakable = null;
@@ -511,12 +540,13 @@
 
     /**
      * Find the continue target node corresponding to this label.
-     * @param label label to search for, if null the closest loop node will be returned unconditionally, e.g. a while loop with no label
+     * @param labelName label name to search for. If null the closest loop node will be returned unconditionally, e.g. a
+     * while loop with no label
      * @return closest continue target node
      */
-    public LoopNode getContinueTo(final IdentNode label) {
-        if (label != null) {
-            final LabelNode foundLabel = findLabel(label.getName());
+    public LoopNode getContinueTo(final String labelName) {
+        if (labelName != null) {
+            final LabelNode foundLabel = findLabel(labelName);
             if (foundLabel != null) {
                 // iterate to the nearest loop to the foundLabel
                 LoopNode loop = null;
@@ -538,7 +568,7 @@
     public LabelNode findLabel(final String name) {
         for (final Iterator<LabelNode> iter = new NodeIterator<>(LabelNode.class, getCurrentFunction()); iter.hasNext(); ) {
             final LabelNode next = iter.next();
-            if (next.getLabel().getName().equals(name)) {
+            if (next.getLabelName().equals(name)) {
                 return next;
             }
         }
@@ -546,31 +576,21 @@
     }
 
     /**
-     * Checks whether a given label is a jump destination that lies outside a given
-     * split node
+     * Checks whether a given target is a jump destination that lies outside a given split node
      * @param splitNode the split node
-     * @param label     the label
-     * @return true if label resides outside the split node
+     * @param target the target node
+     * @return true if target resides outside the split node
      */
-    public boolean isExternalTarget(final SplitNode splitNode, final Label label) {
-        boolean targetFound = false;
-        for (int i = sp - 1; i >= 0; i--) {
+    public boolean isExternalTarget(final SplitNode splitNode, final BreakableNode target) {
+        for (int i = sp; i-- > 0;) {
             final LexicalContextNode next = stack[i];
             if (next == splitNode) {
-                return !targetFound;
-            }
-
-            if (next instanceof BreakableNode) {
-                for (final Label l : ((BreakableNode)next).getLabels()) {
-                    if (l == label) {
-                        targetFound = true;
-                        break;
-                    }
-                }
+                return true;
+            } else if (next == target) {
+                return false;
             }
         }
-        assert false : label + " was expected in lexical context " + LexicalContext.this + " but wasn't";
-        return false;
+        throw new AssertionError(target + " was expected in lexical context " + LexicalContext.this + " but wasn't");
     }
 
     @Override
@@ -627,11 +647,12 @@
             if (next == null) {
                 throw new NoSuchElementException();
             }
-            T lnext = next;
+            final T lnext = next;
             next = findNext();
             return lnext;
         }
 
+        @SuppressWarnings("unchecked")
         private T findNext() {
             for (int i = index; i >= 0; i--) {
                 final Object node = stack[i];
@@ -640,7 +661,7 @@
                 }
                 if (clazz.isAssignableFrom(node.getClass())) {
                     index = i - 1;
-                    return clazz.cast(node);
+                    return (T)node;
                 }
             }
             return null;
diff --git a/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
index d3c7777..b259a2a 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/LexicalContextExpression.java
@@ -29,15 +29,15 @@
 
 abstract class LexicalContextExpression extends Expression implements LexicalContextNode {
 
-    LexicalContextExpression(LexicalContextExpression expr) {
+    LexicalContextExpression(final LexicalContextExpression expr) {
         super(expr);
     }
 
-    LexicalContextExpression(long token, int start, int finish) {
+    LexicalContextExpression(final long token, final int start, final int finish) {
         super(token, start, finish);
     }
 
-    LexicalContextExpression(long token, int finish) {
+    LexicalContextExpression(final long token, final int finish) {
         super(token, finish);
     }
 
@@ -45,15 +45,4 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         return Acceptor.accept(this, visitor);
     }
-
-    /**
-     * Set the symbol and replace in lexical context if applicable
-     * @param lc     lexical context
-     * @param symbol symbol
-     * @return new node if symbol changed
-     */
-    @Override
-    public Expression setSymbol(final LexicalContext lc, final Symbol symbol) {
-        return Node.replaceInLexicalContext(lc, this, (LexicalContextExpression)super.setSymbol(null, symbol));
-    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java
index 8d6823c..8ff4f9f 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/LiteralNode.java
@@ -28,7 +28,7 @@
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
-
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.CompileUnit;
 import jdk.nashorn.internal.codegen.types.ArrayType;
 import jdk.nashorn.internal.codegen.types.Type;
@@ -86,9 +86,15 @@
         this.value = newValue;
     }
 
-    @Override
-    public boolean isAtom() {
-        return true;
+    /**
+     * Initialization setter, if required for immutable state. This is used for
+     * things like ArrayLiteralNodes that need to carry state for the splitter.
+     * Default implementation is just a nop.
+     * @param lc lexical context
+     * @return new literal node with initialized state, or same if nothing changed
+     */
+    public LiteralNode<?> initialize(final LexicalContext lc) {
+        return this;
     }
 
     /**
@@ -100,7 +106,7 @@
     }
 
     @Override
-    public Type getType() {
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
         return Type.typeFor(value.getClass());
     }
 
@@ -215,7 +221,7 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         if (value == null) {
             sb.append("null");
         } else {
@@ -227,7 +233,7 @@
      * Get the literal node value
      * @return the value
      */
-    public T getValue() {
+    public final T getValue() {
         return value;
     }
 
@@ -280,6 +286,16 @@
         public boolean isLocal() {
             return true;
         }
+
+        @Override
+        public boolean isAlwaysFalse() {
+            return !isTrue();
+        }
+
+        @Override
+        public boolean isAlwaysTrue() {
+            return isTrue();
+        }
     }
 
     @Immutable
@@ -299,7 +315,7 @@
         }
 
         @Override
-        public Type getType() {
+        public Type getType(final Function<Symbol, Type> localVariableTypes) {
             return Type.BOOLEAN;
         }
 
@@ -362,7 +378,7 @@
         }
 
         @Override
-        public Type getType() {
+        public Type getType(final Function<Symbol, Type> localVariableTypes) {
             return type;
         }
 
@@ -443,7 +459,7 @@
         }
 
         @Override
-        public void toString(final StringBuilder sb) {
+        public void toString(final StringBuilder sb, final boolean printType) {
             sb.append('\"');
             sb.append(value);
             sb.append('\"');
@@ -486,12 +502,12 @@
         }
 
         @Override
-        public Type getType() {
+        public Type getType(final Function<Symbol, Type> localVariableTypes) {
             return Type.OBJECT;
         }
 
         @Override
-        public void toString(final StringBuilder sb) {
+        public void toString(final StringBuilder sb, final boolean printType) {
             sb.append(value.toString());
         }
     }
@@ -555,7 +571,7 @@
         }
 
         @Override
-        public Type getType() {
+        public Type getType(final Function<Symbol, Type> localVariableTypes) {
             return Type.OBJECT;
         }
 
@@ -568,24 +584,26 @@
     /**
      * Array literal node class.
      */
-    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> {
+    @Immutable
+    public static final class ArrayLiteralNode extends LiteralNode<Expression[]> implements LexicalContextNode {
 
         /** Array element type. */
-        private Type elementType;
+        private final Type elementType;
 
         /** Preset constant array. */
-        private Object presets;
+        private final Object presets;
 
         /** Indices of array elements requiring computed post sets. */
-        private int[] postsets;
+        private final int[] postsets;
 
-        private List<ArrayUnit> units;
+        /** Sub units with indexes ranges, in which to split up code generation, for large literals */
+        private final List<ArrayUnit> units;
 
         /**
          * An ArrayUnit is a range in an ArrayLiteral. ArrayLiterals can
          * be split if they are too large, for bytecode generation reasons
          */
-        public static class ArrayUnit {
+        public static final class ArrayUnit {
             /** Compile unit associated with the postsets range. */
             private final CompileUnit compileUnit;
 
@@ -629,6 +647,150 @@
             }
         }
 
+        private static final class ArrayLiteralInitializer {
+
+            static ArrayLiteralNode initialize(final ArrayLiteralNode node) {
+                final Type elementType = computeElementType(node.value, node.elementType);
+                final int[] postsets = computePostsets(node.value);
+                final Object presets = computePresets(node.value, elementType, postsets);
+                return new ArrayLiteralNode(node, node.value, elementType, postsets, presets, node.units);
+            }
+
+            private static Type computeElementType(final Expression[] value, final Type elementType) {
+                Type widestElementType = Type.INT;
+
+                for (final Expression elem : value) {
+                    if (elem == null) {
+                        widestElementType = widestElementType.widest(Type.OBJECT); //no way to represent undefined as number
+                        break;
+                    }
+
+                    final Type type = elem.getType().isUnknown() ? Type.OBJECT : elem.getType();
+                    if (type.isBoolean()) {
+                        //TODO fix this with explicit boolean types
+                        widestElementType = widestElementType.widest(Type.OBJECT);
+                        break;
+                    }
+
+                    widestElementType = widestElementType.widest(type);
+                    if (widestElementType.isObject()) {
+                        break;
+                    }
+                }
+                return widestElementType;
+            }
+
+            private static int[] computePostsets(final Expression[] value) {
+                final int[] computed = new int[value.length];
+                int nComputed = 0;
+
+                for (int i = 0; i < value.length; i++) {
+                    final Expression element = value[i];
+                    if (element == null || objectAsConstant(element) == POSTSET_MARKER) {
+                        computed[nComputed++] = i;
+                    }
+                }
+                return Arrays.copyOf(computed, nComputed);
+            }
+
+            private static boolean setArrayElement(final int[] array, final int i, final Object n) {
+                if (n instanceof Number) {
+                    array[i] = ((Number)n).intValue();
+                    return true;
+                }
+                return false;
+            }
+
+            private static boolean setArrayElement(final long[] array, final int i, final Object n) {
+                if (n instanceof Number) {
+                    array[i] = ((Number)n).longValue();
+                    return true;
+                }
+                return false;
+            }
+
+            private static boolean setArrayElement(final double[] array, final int i, final Object n) {
+                if (n instanceof Number) {
+                    array[i] = ((Number)n).doubleValue();
+                    return true;
+                }
+                return false;
+            }
+
+            private static int[] presetIntArray(final Expression[] value, final int[] postsets) {
+                final int[] array = new int[value.length];
+                int nComputed = 0;
+                for (int i = 0; i < value.length; i++) {
+                    if (!setArrayElement(array, i, objectAsConstant(value[i]))) {
+                        assert postsets[nComputed++] == i;
+                    }
+                }
+                assert postsets.length == nComputed;
+                return array;
+            }
+
+            private static long[] presetLongArray(final Expression[] value, final int[] postsets) {
+                final long[] array = new long[value.length];
+                int nComputed = 0;
+                for (int i = 0; i < value.length; i++) {
+                    if (!setArrayElement(array, i, objectAsConstant(value[i]))) {
+                        assert postsets[nComputed++] == i;
+                    }
+                }
+                assert postsets.length == nComputed;
+                return array;
+            }
+
+            private static double[] presetDoubleArray(final Expression[] value, final int[] postsets) {
+                final double[] array = new double[value.length];
+                int nComputed = 0;
+                for (int i = 0; i < value.length; i++) {
+                    if (!setArrayElement(array, i, objectAsConstant(value[i]))) {
+                        assert postsets[nComputed++] == i;
+                    }
+                }
+                assert postsets.length == nComputed;
+                return array;
+            }
+
+            private static Object[] presetObjectArray(final Expression[] value, final int[] postsets) {
+                final Object[] array = new Object[value.length];
+                int nComputed = 0;
+
+                for (int i = 0; i < value.length; i++) {
+                    final Node node = value[i];
+
+                    if (node == null) {
+                        assert postsets[nComputed++] == i;
+                        continue;
+                    }
+                    final Object element = objectAsConstant(node);
+
+                    if (element != POSTSET_MARKER) {
+                        array[i] = element;
+                    } else {
+                        assert postsets[nComputed++] == i;
+                    }
+                }
+
+                assert postsets.length == nComputed;
+                return array;
+            }
+
+            static Object computePresets(final Expression[] value, final Type elementType, final int[] postsets) {
+                assert !elementType.isUnknown();
+                if (elementType.isInteger()) {
+                    return presetIntArray(value, postsets);
+                } else if (elementType.isLong()) {
+                    return presetLongArray(value, postsets);
+                } else if (elementType.isNumeric()) {
+                    return presetDoubleArray(value, postsets);
+                } else {
+                    return presetObjectArray(value, postsets);
+                }
+            }
+        }
+
         /**
          * Constructor
          *
@@ -639,144 +801,21 @@
         protected ArrayLiteralNode(final long token, final int finish, final Expression[] value) {
             super(Token.recast(token, TokenType.ARRAY), finish, value);
             this.elementType = Type.UNKNOWN;
+            this.presets     = null;
+            this.postsets    = null;
+            this.units       = null;
         }
 
         /**
          * Copy constructor
          * @param node source array literal node
          */
-        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value) {
+        private ArrayLiteralNode(final ArrayLiteralNode node, final Expression[] value, final Type elementType, final int[] postsets, final Object presets, final List<ArrayUnit> units) {
             super(node, value);
-            this.elementType = node.elementType;
-            this.presets     = node.presets;
-            this.postsets    = node.postsets;
-            this.units       = node.units;
-        }
-
-        /**
-         * Compute things like widest element type needed. Internal use from compiler only
-         */
-        public void analyze() {
-            elementType = Type.INT;
-            analyzeElements();
-
-            if (elementType.isInteger()) {
-                presetIntArray();
-            } else if (elementType.isLong()) {
-                presetLongArray();
-            } else if (elementType.isNumeric()) {
-                presetNumberArray();
-            } else {
-                presetObjectArray();
-            }
-        }
-
-        private void presetIntArray() {
-            final int[] array = new int[value.length];
-            final int[] computed = new int[value.length];
-            int nComputed = 0;
-
-            for (int i = 0; i < value.length; i++) {
-                final Object element = objectAsConstant(value[i]);
-
-                if (element instanceof Number) {
-                    array[i] = ((Number)element).intValue();
-                } else {
-                    computed[nComputed++] = i;
-                }
-            }
-
-            presets = array;
-            postsets = Arrays.copyOf(computed, nComputed);
-        }
-
-        private void presetLongArray() {
-            final long[] array = new long[value.length];
-            final int[] computed = new int[value.length];
-            int nComputed = 0;
-
-            for (int i = 0; i < value.length; i++) {
-                final Object element = objectAsConstant(value[i]);
-
-                if (element instanceof Number) {
-                    array[i] = ((Number)element).longValue();
-                } else {
-                    computed[nComputed++] = i;
-                }
-            }
-
-            presets = array;
-            postsets = Arrays.copyOf(computed, nComputed);
-        }
-
-        private void presetNumberArray() {
-            final double[] array = new double[value.length];
-            final int[] computed = new int[value.length];
-            int nComputed = 0;
-
-            for (int i = 0; i < value.length; i++) {
-                final Object element = objectAsConstant(value[i]);
-
-                if (element instanceof Number) {
-                    array[i] = ((Number)element).doubleValue();
-                } else {
-                    computed[nComputed++] = i;
-                }
-            }
-
-            presets = array;
-            postsets = Arrays.copyOf(computed, nComputed);
-        }
-
-        private void presetObjectArray() {
-            final Object[] array = new Object[value.length];
-            final int[] computed = new int[value.length];
-            int nComputed = 0;
-
-            for (int i = 0; i < value.length; i++) {
-                final Node node = value[i];
-
-                if (node == null) {
-                    computed[nComputed++] = i;
-                } else {
-                    final Object element = objectAsConstant(node);
-
-                    if (element != POSTSET_MARKER) {
-                        array[i] = element;
-                    } else {
-                        computed[nComputed++] = i;
-                    }
-                }
-            }
-
-            presets = array;
-            postsets = Arrays.copyOf(computed, nComputed);
-        }
-
-        private void analyzeElements() {
-            for (final Expression node : value) {
-                if (node == null) {
-                    elementType = elementType.widest(Type.OBJECT); //no way to represent undefined as number
-                    break;
-                }
-
-                assert node.getSymbol() != null; //don't run this on unresolved nodes or you are in trouble
-                Type symbolType = node.getSymbol().getSymbolType();
-                if (symbolType.isUnknown()) {
-                    symbolType = Type.OBJECT;
-                }
-
-                if (symbolType.isBoolean()) {
-                    elementType = elementType.widest(Type.OBJECT);
-                    break;
-                }
-
-                elementType = elementType.widest(symbolType);
-
-                if (elementType.isObject()) {
-                    break;
-                }
-            }
+            this.elementType = elementType;
+            this.postsets    = postsets;
+            this.presets     = presets;
+            this.units       = units;
         }
 
         @Override
@@ -785,10 +824,27 @@
         }
 
         /**
+         * Setter that initializes all code generation meta data for an
+         * ArrayLiteralNode. This acts a setter, so the return value may
+         * return a new node and must be handled
+         *
+         * @param lc lexical context
+         * @return new array literal node with postsets, presets and element types initialized
+         */
+        @Override
+        public ArrayLiteralNode initialize(final LexicalContext lc) {
+            return Node.replaceInLexicalContext(lc, this, ArrayLiteralInitializer.initialize(this));
+        }
+
+        /**
          * Get the array element type as Java format, e.g. [I
          * @return array element type
          */
         public ArrayType getArrayType() {
+            return getArrayType(getElementType());
+        }
+
+        private static ArrayType getArrayType(final Type elementType) {
             if (elementType.isInteger()) {
                 return Type.INT_ARRAY;
             } else if (elementType.isLong()) {
@@ -801,7 +857,7 @@
         }
 
         @Override
-        public Type getType() {
+        public Type getType(final Function<Symbol, Type> localVariableTypes) {
             return Type.typeFor(NativeArray.class);
         }
 
@@ -810,6 +866,7 @@
          * @return element type
          */
         public Type getElementType() {
+            assert !elementType.isUnknown() : this + " has elementType=unknown";
             return elementType;
         }
 
@@ -819,14 +876,28 @@
          * @return post set indices
          */
         public int[] getPostsets() {
+            assert postsets != null : this + " elementType=" + elementType + " has no postsets";
             return postsets;
         }
 
+        private boolean presetsMatchElementType() {
+            if (elementType == Type.INT) {
+                return presets instanceof int[];
+            } else if (elementType == Type.LONG) {
+                return presets instanceof long[];
+            } else if (elementType == Type.NUMBER) {
+                return presets instanceof double[];
+            } else {
+                return presets instanceof Object[];
+            }
+        }
+
         /**
          * Get presets constant array
          * @return presets array, always returns an array type
          */
         public Object getPresets() {
+            assert presets != null && presetsMatchElementType() : this + " doesn't have presets, or invalid preset type: " + presets;
             return presets;
         }
 
@@ -841,29 +912,46 @@
 
         /**
          * Set the ArrayUnits that make up this ArrayLiteral
+         * @param lc lexical context
          * @see ArrayUnit
          * @param units list of array units
+         * @return new or changed arrayliteralnode
          */
-        public void setUnits(final List<ArrayUnit> units) {
-            this.units = units;
+        public ArrayLiteralNode setUnits(final LexicalContext lc, final List<ArrayUnit> units) {
+            if (this.units == units) {
+                return this;
+            }
+            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
         }
 
         @Override
         public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
+            return Acceptor.accept(this, visitor);
+        }
+
+        @Override
+        public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
             if (visitor.enterLiteralNode(this)) {
                 final List<Expression> oldValue = Arrays.asList(value);
-                final List<Expression> newValue = Node.accept(visitor, Expression.class, oldValue);
-                return visitor.leaveLiteralNode(oldValue != newValue ? setValue(newValue) : this);
+                final List<Expression> newValue = Node.accept(visitor, oldValue);
+                return visitor.leaveLiteralNode(oldValue != newValue ? setValue(lc, newValue) : this);
             }
             return this;
         }
 
-        private ArrayLiteralNode setValue(final List<Expression> value) {
-            return new ArrayLiteralNode(this, value.toArray(new Expression[value.size()]));
+        private ArrayLiteralNode setValue(final LexicalContext lc, final Expression[] value) {
+            if (this.value == value) {
+                return this;
+            }
+            return Node.replaceInLexicalContext(lc, this, new ArrayLiteralNode(this, value, elementType, postsets, presets, units));
+        }
+
+        private ArrayLiteralNode setValue(final LexicalContext lc, final List<Expression> value) {
+            return setValue(lc, value.toArray(new Expression[value.size()]));
         }
 
         @Override
-        public void toString(final StringBuilder sb) {
+        public void toString(final StringBuilder sb, final boolean printType) {
             sb.append('[');
             boolean first = true;
             for (final Node node : value) {
@@ -874,7 +962,7 @@
                 if (node == null) {
                     sb.append("undefined");
                 } else {
-                    node.toString(sb);
+                    node.toString(sb, printType);
                 }
                 first = false;
             }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/LocalVariableConversion.java b/nashorn/src/jdk/nashorn/internal/ir/LocalVariableConversion.java
new file mode 100644
index 0000000..b66a2fd
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/LocalVariableConversion.java
@@ -0,0 +1,174 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Class describing one or more local variable conversions that needs to be performed on entry to a control flow join
+ * point. Note that the class is named as a singular "Conversion" and not a plural "Conversions", but instances of the
+ * class have a reference to the next conversion, so multiple conversions are always represented with a single instance
+ * that is a head of a linked list of instances.
+ * @see JoinPredecessor
+ */
+public final class LocalVariableConversion {
+    private final Symbol symbol;
+    // TODO: maybe introduce a type pair class? These will often be repeated.
+    private final Type from;
+    private final Type to;
+    private final LocalVariableConversion next;
+
+    /**
+     * Creates a new object representing a local variable conversion.
+     * @param symbol the symbol representing the local variable whose value is being converted.
+     * @param from the type value is being converted from.
+     * @param to the type value is being converted to.
+     * @param next next conversion at the same join point, if any (the conversion object implements a singly-linked
+     * list of conversions).
+     */
+    public LocalVariableConversion(final Symbol symbol, final Type from, final Type to, final LocalVariableConversion next) {
+        this.symbol = symbol;
+        this.from = from;
+        this.to = to;
+        this.next = next;
+    }
+
+    /**
+     * Returns the type being converted from.
+     * @return the type being converted from.
+     */
+    public Type getFrom() {
+        return from;
+    }
+
+    /**
+     * Returns the type being converted to.
+     * @return the type being converted to.
+     */
+    public Type getTo() {
+        return to;
+    }
+
+    /**
+     * Returns the next conversion at the same join point, or null if this is the last one.
+     * @return the next conversion at the same join point.
+     */
+    public LocalVariableConversion getNext() {
+        return next;
+    }
+
+    /**
+     * Returns the symbol representing the local variable whose value is being converted.
+     * @return the symbol representing the local variable whose value is being converted.
+     */
+    public Symbol getSymbol() {
+        return symbol;
+    }
+
+    /**
+     * Returns true if this conversion is live. A conversion is live if the symbol has a slot for the conversion's
+     * {@link #getTo() to} type. If a conversion is dead, it can be omitted in code generator.
+     * @return true if this conversion is live.
+     */
+    public boolean isLive() {
+        return symbol.hasSlotFor(to);
+    }
+
+    /**
+     * Returns true if this conversion {@link #isLive()}, or if any of its {@link #getNext()} conversions are live.
+     * @return true if this conversion, or any conversion following it, are live.
+     */
+    public boolean isAnyLive() {
+        return isLive() || isAnyLive(next);
+    }
+
+    /**
+     * Returns true if the passed join predecessor has {@link #isAnyLive()} conversion.
+     * @param jp the join predecessor being examined.
+     * @return true if the join predecessor conversion is not null and {@link #isAnyLive()}.
+     */
+    public static boolean hasLiveConversion(final JoinPredecessor jp) {
+        return isAnyLive(jp.getLocalVariableConversion());
+    }
+
+    /**
+     * Returns true if the passed conversion is not null, and it {@link #isAnyLive()}.
+     * @parameter conv the conversion being tested for liveness.
+     * @return true if the conversion is not null and {@link #isAnyLive()}.
+     */
+    private static boolean isAnyLive(final LocalVariableConversion conv) {
+        return conv != null && conv.isAnyLive();
+    }
+
+    @Override
+    public String toString() {
+        return toString(new StringBuilder()).toString();
+    }
+
+    /**
+     * Generates a string representation of this conversion in the passed string builder.
+     * @param sb the string builder in which to generate a string representation of this conversion.
+     * @return the passed in string builder.
+     */
+    public StringBuilder toString(final StringBuilder sb) {
+        if(isLive()) {
+            return toStringNext(sb.append('\u27e6'), true).append("\u27e7 ");
+        }
+        return next == null ? sb : next.toString(sb);
+    }
+
+    /**
+     * Generates a string representation of the passed conversion in the passed string builder.
+     * @param conv the conversion to render in the string builder.
+     * @param sb the string builder in which to generate a string representation of this conversion.
+     * @return the passed in string builder.
+     */
+    public static StringBuilder toString(final LocalVariableConversion conv, final StringBuilder sb) {
+        return conv == null ? sb : conv.toString(sb);
+    }
+
+    private StringBuilder toStringNext(final StringBuilder sb, final boolean first) {
+        if(isLive()) {
+            if(!first) {
+                sb.append(", ");
+            }
+            sb.append(symbol.getName()).append(':').append(getTypeChar(from)).append('\u2192').append(getTypeChar(to));
+            return next == null ? sb : next.toStringNext(sb, false);
+        }
+        return next == null ? sb : next.toStringNext(sb, first);
+    }
+
+    private static char getTypeChar(final Type type) {
+        if(type == Type.UNDEFINED) {
+            return 'U';
+        } else if(type.isObject()) {
+            return 'O';
+        } else if(type == Type.BOOLEAN) {
+            return 'Z';
+        }
+        return type.getBytecodeStackType();
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java b/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java
index 107030a..86ef3cd 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/LoopNode.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.ir;
 
 import java.util.Arrays;
+import java.util.Collections;
 import java.util.List;
 import jdk.nashorn.internal.codegen.Label;
 
@@ -37,7 +38,7 @@
     protected final Label continueLabel;
 
     /** Loop test node, null if infinite */
-    protected final Expression test;
+    protected final JoinPredecessorExpression test;
 
     /** Loop body */
     protected final Block body;
@@ -51,14 +52,13 @@
      * @param lineNumber         lineNumber
      * @param token              token
      * @param finish             finish
-     * @param test               test, or null if infinite loop
      * @param body               loop body
      * @param controlFlowEscapes controlFlowEscapes
      */
-    protected LoopNode(final int lineNumber, final long token, final int finish, final Expression test, final Block body, final boolean controlFlowEscapes) {
+    protected LoopNode(final int lineNumber, final long token, final int finish, final Block body, final boolean controlFlowEscapes) {
         super(lineNumber, token, finish, new Label("while_break"));
         this.continueLabel = new Label("while_continue");
-        this.test = test;
+        this.test = null;
         this.body = body;
         this.controlFlowEscapes = controlFlowEscapes;
     }
@@ -70,9 +70,11 @@
      * @param test     new test
      * @param body     new body
      * @param controlFlowEscapes controlFlowEscapes
+     * @param conversion the local variable conversion carried by this loop node.
      */
-    protected LoopNode(final LoopNode loopNode, final Expression test, final Block body, final boolean controlFlowEscapes) {
-        super(loopNode);
+    protected LoopNode(final LoopNode loopNode, final JoinPredecessorExpression test, final Block body,
+            final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+        super(loopNode, conversion);
         this.continueLabel = new Label(loopNode.continueLabel);
         this.test = test;
         this.body = body;
@@ -125,7 +127,7 @@
 
     @Override
     public List<Label> getLabels() {
-        return Arrays.asList(breakLabel, continueLabel);
+        return Collections.unmodifiableList(Arrays.asList(breakLabel, continueLabel));
     }
 
     @Override
@@ -150,7 +152,9 @@
      * Get the test for this for node
      * @return the test
      */
-    public abstract Expression getTest();
+    public final JoinPredecessorExpression getTest() {
+        return test;
+    }
 
     /**
      * Set the test for this for node
@@ -159,7 +163,7 @@
      * @param test new test
      * @return same or new node depending on if test was changed
      */
-    public abstract LoopNode setTest(final LexicalContext lc, final Expression test);
+    public abstract LoopNode setTest(final LexicalContext lc, final JoinPredecessorExpression test);
 
     /**
      * Set the control flow escapes flag for this node.
@@ -170,5 +174,4 @@
      * @return new loop node if changed otherwise the same
      */
     public abstract LoopNode setControlFlowEscapes(final LexicalContext lc, final boolean controlFlowEscapes);
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Node.java b/nashorn/src/jdk/nashorn/internal/ir/Node.java
index c59c235..37ec4b9 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Node.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Node.java
@@ -27,7 +27,6 @@
 
 import java.util.ArrayList;
 import java.util.List;
-import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
@@ -82,15 +81,6 @@
     }
 
     /**
-     * Is this an atom node - for example a literal or an identity
-     *
-     * @return true if atom
-     */
-    public boolean isAtom() {
-        return false;
-    }
-
-    /**
      * Is this a loop node?
      *
      * @return true if atom
@@ -110,31 +100,6 @@
     }
 
     /**
-     * Is this a self modifying assignment?
-     * @return true if self modifying, e.g. a++, or a*= 17
-     */
-    public boolean isSelfModifying() {
-        return false;
-    }
-
-    /**
-     * Returns widest operation type of this operation.
-     *
-     * @return the widest type for this operation
-     */
-    public Type getWidestOperationType() {
-        return Type.OBJECT;
-    }
-
-    /**
-     * Returns true if this node represents a comparison operator
-     * @return true if comparison
-     */
-    public boolean isComparison() {
-        return false;
-    }
-
-    /**
      * For reference copies - ensure that labels in the copy node are unique
      * using an appropriate copy constructor
      * @param lc lexical context
@@ -164,16 +129,19 @@
      *
      * @param sb a StringBuilder
      */
-    public abstract void toString(StringBuilder sb);
+    public void toString(final StringBuilder sb) {
+        toString(sb, true);
+    }
 
     /**
-     * Check if this node has terminal flags, i.e. ends or breaks control flow
-     *
-     * @return true if terminal
+     * Print logic that decides whether to show the optimistic type
+     * or not - for example it should not be printed after just parse,
+     * when it hasn't been computed, or has been set to a trivially provable
+     * value
+     * @param sb   string builder
+     * @param printType print type?
      */
-    public boolean hasTerminalFlags() {
-        return isTerminal() || hasGoto();
-    }
+    public abstract void toString(final StringBuilder sb, final boolean printType);
 
     /**
      * Get the finish position for this node in the source string
@@ -192,15 +160,6 @@
     }
 
     /**
-     * Check if this function repositions control flow with goto like
-     * semantics, for example {@link BreakNode} or a {@link ForNode} with no test
-     * @return true if node has goto semantics
-     */
-    public boolean hasGoto() {
-        return false;
-    }
-
-    /**
      * Get start position for node
      * @return start position
      */
@@ -219,12 +178,15 @@
 
     @Override
     public final boolean equals(final Object other) {
-        return super.equals(other);
+        return this == other;
     }
 
     @Override
     public final int hashCode() {
-        return super.hashCode();
+        // NOTE: we aren't delegating to Object.hashCode as it still requires trip to the VM for initializing,
+        // it touches the object header and/or stores the identity hashcode somewhere, etc. There's several
+        // places in the compiler pipeline that store nodes in maps, so this can get hot.
+        return Long.hashCode(token);
     }
 
     /**
@@ -272,30 +234,35 @@
         return token;
     }
 
-    /**
-     * Is this a terminal Node, i.e. does it end control flow like a throw or return
-     * expression does?
-     *
-     * @return true if this node is terminal
-     */
-    public boolean isTerminal() {
-        return false;
-    }
-
     //on change, we have to replace the entire list, that's we can't simple do ListIterator.set
-    static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final Class<T> clazz, final List<T> list) {
-        boolean changed = false;
-        final List<T> newList = new ArrayList<>();
-
-        for (final Node node : list) {
-            final T newNode = node == null ? null : clazz.cast(node.accept(visitor));
-            if (newNode != node) {
-                changed = true;
-            }
-            newList.add(newNode);
+    static <T extends Node> List<T> accept(final NodeVisitor<? extends LexicalContext> visitor, final List<T> list) {
+        final int size = list.size();
+        if (size == 0) {
+            return list;
         }
 
-        return changed ? newList : list;
+         List<T> newList = null;
+
+        for (int i = 0; i < size; i++) {
+            final T node = list.get(i);
+            @SuppressWarnings("unchecked")
+            final T newNode = node == null ? null : (T)node.accept(visitor);
+            if (newNode != node) {
+                if (newList == null) {
+                    newList = new ArrayList<>(size);
+                    for (int j = 0; j < i; j++) {
+                        newList.add(list.get(j));
+                    }
+                }
+                newList.add(newNode);
+            } else {
+                if (newList != null) {
+                    newList.add(node);
+                }
+            }
+        }
+
+        return newList == null ? list : newList;
     }
 
     static <T extends LexicalContextNode> T replaceInLexicalContext(final LexicalContext lc, final T oldNode, final T newNode) {
diff --git a/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java
index b46e9b3..38fd667 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/ObjectNode.java
@@ -27,6 +27,8 @@
 
 import java.util.Collections;
 import java.util.List;
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -59,14 +61,19 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterObjectNode(this)) {
-            return visitor.leaveObjectNode(setElements(Node.accept(visitor, PropertyNode.class, elements)));
+            return visitor.leaveObjectNode(setElements(Node.accept(visitor, elements)));
         }
 
         return this;
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        return Type.OBJECT;
+    }
+
+    @Override
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append('{');
 
         if (!elements.isEmpty()) {
@@ -79,7 +86,7 @@
                 }
                 first = false;
 
-                element.toString(sb);
+                element.toString(sb, printType);
             }
             sb.append(' ');
         }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Optimistic.java b/nashorn/src/jdk/nashorn/internal/ir/Optimistic.java
new file mode 100644
index 0000000..8337d08
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/Optimistic.java
@@ -0,0 +1,92 @@
+/*
+ * 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.
+ */
+package jdk.nashorn.internal.ir;
+
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Is this a node that can be optimistically typed? This means that it
+ * has a probable type but it's not available through static analysis
+ *
+ * The follow nodes are optimistic, with reasons therefore given within
+ * parenthesis
+ *
+ * @see IndexNode  (dynamicGetIndex)
+ * @see BinaryNode (local calculations to strongly typed bytecode)
+ * @see UnaryNode  (local calculations to strongly typed bytecode)
+ * @see CallNode   (dynamicCall)
+ * @see AccessNode (dynamicGet)
+ * @see IdentNode  (dynamicGet)
+ */
+public interface Optimistic {
+    /**
+     * Unique node ID that is associated with an invokedynamic call that mail
+     * fail and its callsite. This is so that nodes can be regenerated less
+     * pessimistically the next generation if an assumption failed
+     *
+     * @return unique node id
+     */
+    public int getProgramPoint();
+
+    /**
+     * Set the node number for this node, associating with a unique per-function
+     * program point
+     * @param programPoint the node number
+     * @return new node, or same if unchanged
+     */
+    public Optimistic setProgramPoint(final int programPoint);
+
+    /**
+     * Is it possible for this particular implementor to actually have any optimism?
+     * SHIFT operators for instance are binary nodes, but never optimistic. Multiply
+     * operators are. We might want to refurbish the type hierarchy to fix this.
+     * @return true if theoretically optimistic
+     */
+    public boolean canBeOptimistic();
+
+    /**
+     * Get the most optimistic type for this node. Typically we start out as
+     * an int, and then at runtime we bump this up to number and then Object
+     *
+     * @return optimistic type to be used in code generation
+     */
+    public Type getMostOptimisticType();
+
+    /**
+     * Most pessimistic type that is guaranteed to be safe.  Typically this is
+     * number for arithmetic operations that can overflow, or Object for an add
+     *
+     * @return pessimistic type guaranteed to never overflow
+     */
+    public Type getMostPessimisticType();
+
+    /**
+     * Set the override type
+     *
+     * @param type the type
+     * @return a node equivalent to this one except for the requested change.
+     */
+    public Optimistic setType(final Type type);
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java b/nashorn/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
new file mode 100644
index 0000000..9d97a43
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/OptimisticLexicalContext.java
@@ -0,0 +1,128 @@
+/*
+ * 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.
+ */
+package jdk.nashorn.internal.ir;
+
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.List;
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * Lexical context that keeps track of optimistic assumptions (if any)
+ * made during code generation. Used from Attr and FinalizeTypes
+ */
+public class OptimisticLexicalContext extends LexicalContext {
+
+    private final boolean isEnabled;
+
+    class Assumption {
+        Symbol symbol;
+        Type   type;
+
+        Assumption(final Symbol symbol, final Type type) {
+            this.symbol = symbol;
+            this.type   = type;
+        }
+        @Override
+        public String toString() {
+            return symbol.getName() + "=" + type;
+        }
+    }
+
+    /** Optimistic assumptions that could be made per function */
+    private final Deque<List<Assumption>> optimisticAssumptions = new ArrayDeque<>();
+
+    /**
+     * Constructor
+     * @param isEnabled are optimistic types enabled?
+     */
+    public OptimisticLexicalContext(final boolean isEnabled) {
+        super();
+        this.isEnabled = isEnabled;
+    }
+
+    /**
+     * Are optimistic types enabled
+     * @return true if optimistic types
+     */
+    public boolean isEnabled() {
+        return isEnabled;
+    }
+
+    /**
+     * Log an optimistic assumption during codegen
+     * TODO : different parameters and more info about the assumption for future profiling
+     * needs
+     * @param symbol symbol
+     * @param type   type
+     */
+    public void logOptimisticAssumption(final Symbol symbol, final Type type) {
+        if (isEnabled) {
+            final List<Assumption> peek = optimisticAssumptions.peek();
+            peek.add(new Assumption(symbol, type));
+        }
+    }
+
+    /**
+     * Get the list of optimistic assumptions made
+     * @return optimistic assumptions
+     */
+    public List<Assumption> getOptimisticAssumptions() {
+        return Collections.unmodifiableList(optimisticAssumptions.peek());
+    }
+
+    /**
+     * Does this method have optimistic assumptions made during codegen?
+     * @return true if optimistic assumptions were made
+     */
+    public boolean hasOptimisticAssumptions() {
+        return !optimisticAssumptions.isEmpty() && !getOptimisticAssumptions().isEmpty();
+    }
+
+    @Override
+    public <T extends LexicalContextNode> T push(final T node) {
+        if (isEnabled) {
+            if(node instanceof FunctionNode) {
+                optimisticAssumptions.push(new ArrayList<Assumption>());
+            }
+        }
+
+        return super.push(node);
+    }
+
+    @Override
+    public <T extends LexicalContextNode> T pop(final T node) {
+        final T popped = super.pop(node);
+        if (isEnabled) {
+            if(node instanceof FunctionNode) {
+                optimisticAssumptions.pop();
+            }
+        }
+        return popped;
+    }
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java b/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java
index 9cb8209..b65d129 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/PropertyNode.java
@@ -94,25 +94,25 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         if (value instanceof FunctionNode && ((FunctionNode)value).getIdent() != null) {
             value.toString(sb);
         }
 
         if (value != null) {
-            ((Node)key).toString(sb);
+            ((Node)key).toString(sb, printType);
             sb.append(": ");
-            value.toString(sb);
+            value.toString(sb, printType);
         }
 
         if (getter != null) {
             sb.append(' ');
-            getter.toString(sb);
+            getter.toString(sb, printType);
         }
 
         if (setter != null) {
             sb.append(' ');
-            setter.toString(sb);
+            setter.toString(sb, printType);
         }
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java b/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java
index 209e47b..5ea1220 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/ReturnNode.java
@@ -100,11 +100,11 @@
 
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append(isYield() ? "yield" : "return");
         if (expression != null) {
             sb.append(' ');
-            expression.toString(sb);
+            expression.toString(sb, printType);
         }
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java b/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java
index 269cb90..755b352 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/RuntimeNode.java
@@ -25,10 +25,13 @@
 
 package jdk.nashorn.internal.ir;
 
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
@@ -38,7 +41,7 @@
  * IR representation for a runtime call.
  */
 @Immutable
-public class RuntimeNode extends Expression {
+public class RuntimeNode extends Expression implements Optimistic {
 
     /**
      * Request enum used for meta-information about the runtime request
@@ -77,7 +80,11 @@
         /** !== operator with at least one object */
         NE_STRICT(TokenType.NE_STRICT, Type.BOOLEAN, 2, true),
         /** != operator with at least one object */
-        NE(TokenType.NE, Type.BOOLEAN, 2, true);
+        NE(TokenType.NE, Type.BOOLEAN, 2, true),
+        /** is undefined */
+        IS_UNDEFINED(TokenType.EQ_STRICT, Type.BOOLEAN, 2),
+        /** is not undefined */
+        IS_NOT_UNDEFINED(TokenType.NE_STRICT, Type.BOOLEAN, 2);
 
         /** token type */
         private final TokenType tokenType;
@@ -163,9 +170,14 @@
          * @param node the node
          * @return request type
          */
-        public static Request requestFor(final Node node) {
-            assert node.isComparison();
+        public static Request requestFor(final Expression node) {
             switch (node.tokenType()) {
+            case TYPEOF:
+                return Request.TYPEOF;
+            case IN:
+                return Request.IN;
+            case INSTANCEOF:
+                return Request.INSTANCEOF;
             case EQ_STRICT:
                 return Request.EQ_STRICT;
             case NE_STRICT:
@@ -189,6 +201,17 @@
         }
 
         /**
+         * Is this an undefined check?
+         *
+         * @param request request
+         *
+         * @return true if undefined check
+         */
+        public static boolean isUndefinedCheck(final Request request) {
+            return request == IS_UNDEFINED || request == IS_NOT_UNDEFINED;
+        }
+
+        /**
          * Is this an EQ or EQ_STRICT?
          *
          * @param request a request
@@ -211,6 +234,17 @@
         }
 
         /**
+         * Is this strict?
+         *
+         * @param request a request
+         *
+         * @return true if script
+         */
+        public static boolean isStrict(final Request request) {
+            return request == EQ_STRICT || request == NE_STRICT;
+        }
+
+        /**
          * If this request can be reversed, return the reverse request
          * Eq EQ {@literal ->} NE.
          *
@@ -285,6 +319,8 @@
             case LT:
             case GE:
             case GT:
+            case IS_UNDEFINED:
+            case IS_NOT_UNDEFINED:
                 return true;
             default:
                 return false;
@@ -301,6 +337,8 @@
     /** is final - i.e. may not be removed again, lower in the code pipeline */
     private final boolean isFinal;
 
+    private final int programPoint;
+
     /**
      * Constructor
      *
@@ -315,14 +353,16 @@
         this.request      = request;
         this.args         = args;
         this.isFinal      = false;
+        this.programPoint = INVALID_PROGRAM_POINT;
     }
 
-    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args) {
+    private RuntimeNode(final RuntimeNode runtimeNode, final Request request, final boolean isFinal, final List<Expression> args, final int programPoint) {
         super(runtimeNode);
 
         this.request      = request;
         this.args         = args;
         this.isFinal      = isFinal;
+        this.programPoint = programPoint;
     }
 
     /**
@@ -361,6 +401,7 @@
         this.request      = request;
         this.args         = args;
         this.isFinal      = false;
+        this.programPoint = parent instanceof Optimistic ? ((Optimistic)parent).getProgramPoint() : INVALID_PROGRAM_POINT;
     }
 
     /**
@@ -370,20 +411,32 @@
      * @param request the request
      */
     public RuntimeNode(final UnaryNode parent, final Request request) {
-        this(parent, request, parent.rhs());
+        this(parent, request, parent.getExpression());
     }
 
     /**
-     * Constructor
+     * Constructor used to replace a binary node with a runtime request.
      *
      * @param parent  parent node from which to inherit source, token, finish and arguments
-     * @param request the request
      */
-    public RuntimeNode(final BinaryNode parent, final Request request) {
-        this(parent, request, parent.lhs(), parent.rhs());
+    public RuntimeNode(final BinaryNode parent) {
+        this(parent, Request.requestFor(parent), parent.lhs(), parent.rhs());
     }
 
     /**
+     * Reset the request for this runtime node
+     * @param request request
+     * @return new runtime node or same if same request
+     */
+    public RuntimeNode setRequest(final Request request) {
+       if (this.request == request) {
+           return this;
+       }
+       return new RuntimeNode(this, request, isFinal, args, programPoint);
+   }
+
+
+    /**
      * Is this node final - i.e. it can never be replaced with other nodes again
      * @return true if final
      */
@@ -400,14 +453,14 @@
         if (this.isFinal == isFinal) {
             return this;
         }
-        return new RuntimeNode(this, request, isFinal, args);
+        return new RuntimeNode(this, request, isFinal, args, programPoint);
     }
 
     /**
      * Return type for the ReferenceNode
      */
     @Override
-    public Type getType() {
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
         return request.getReturnType();
     }
 
@@ -425,7 +478,7 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("ScriptRuntime.");
         sb.append(request);
         sb.append('(');
@@ -439,7 +492,7 @@
                 first = false;
             }
 
-            arg.toString(sb);
+            arg.toString(sb, printType);
         }
 
         sb.append(')');
@@ -453,11 +506,16 @@
         return Collections.unmodifiableList(args);
     }
 
-    private RuntimeNode setArgs(final List<Expression> args) {
+    /**
+     * Set the arguments of this runtime node
+     * @param args new arguments
+     * @return new runtime node, or identical if no change
+     */
+    public RuntimeNode setArgs(final List<Expression> args) {
         if (this.args == args) {
             return this;
         }
-        return new RuntimeNode(this, request, isFinal, args);
+        return new RuntimeNode(this, request, isFinal, args, programPoint);
     }
 
     /**
@@ -483,4 +541,39 @@
         }
         return true;
     }
+
+//TODO these are blank for now:
+
+    @Override
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    @Override
+    public RuntimeNode setProgramPoint(final int programPoint) {
+        if(this.programPoint == programPoint) {
+            return this;
+        }
+        return new RuntimeNode(this, request, isFinal, args, programPoint);
+    }
+
+    @Override
+    public boolean canBeOptimistic() {
+        return false;
+    }
+
+    @Override
+    public Type getMostOptimisticType() {
+        return getType();
+    }
+
+    @Override
+    public Type getMostPessimisticType() {
+        return getType();
+    }
+
+    @Override
+    public RuntimeNode setType(final Type type) {
+        return this;
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java b/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java
index d6c619b..ba2409e 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/SplitNode.java
@@ -25,7 +25,13 @@
 
 package jdk.nashorn.internal.ir;
 
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 import jdk.nashorn.internal.codegen.CompileUnit;
+import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -33,7 +39,7 @@
  * Node indicating code is split across classes.
  */
 @Immutable
-public class SplitNode extends LexicalContextStatement {
+public class SplitNode extends LexicalContextStatement implements Labels {
     /** Split node method name. */
     private final String name;
 
@@ -41,7 +47,9 @@
     private final CompileUnit compileUnit;
 
     /** Body of split code. */
-    private final Node body;
+    private final Block body;
+
+    private Map<Label, JoinPredecessor> jumps;
 
     /**
      * Constructor
@@ -50,18 +58,19 @@
      * @param body        body of split code
      * @param compileUnit compile unit to use for the body
      */
-    public SplitNode(final String name, final Node body, final CompileUnit compileUnit) {
-        super(-1, body.getToken(), body.getFinish());
+    public SplitNode(final String name, final Block body, final CompileUnit compileUnit) {
+        super(body.getFirstStatementLineNumber(), body.getToken(), body.getFinish());
         this.name        = name;
         this.body        = body;
         this.compileUnit = compileUnit;
     }
 
-    private SplitNode(final SplitNode splitNode, final Node body) {
+    private SplitNode(final SplitNode splitNode, final Block body, final CompileUnit compileUnit, final Map<Label, JoinPredecessor> jumps) {
         super(splitNode);
         this.name        = splitNode.name;
         this.body        = body;
-        this.compileUnit = splitNode.compileUnit;
+        this.compileUnit = compileUnit;
+        this.jumps       = jumps;
     }
 
     /**
@@ -72,27 +81,27 @@
         return body;
     }
 
-    private SplitNode setBody(final LexicalContext lc, final Node body) {
+    private SplitNode setBody(final LexicalContext lc, final Block body) {
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body));
+        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit, jumps));
     }
 
     @Override
     public Node accept(final LexicalContext lc, final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterSplitNode(this)) {
-            return visitor.leaveSplitNode(setBody(lc, body.accept(visitor)));
+            return visitor.leaveSplitNode(setBody(lc, (Block)body.accept(visitor)));
         }
         return this;
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("<split>(");
         sb.append(compileUnit.getClass().getSimpleName());
         sb.append(") ");
-        body.toString(sb);
+        body.toString(sb, printType);
     }
 
     /**
@@ -111,4 +120,43 @@
         return compileUnit;
     }
 
+    /**
+     * Set the compile unit for this split node
+     * @param lc lexical context
+     * @param compileUnit compile unit
+     * @return new node if changed, otherwise same node
+     */
+    public SplitNode setCompileUnit(final LexicalContext lc, final CompileUnit compileUnit) {
+        if (this.compileUnit == compileUnit) {
+            return this;
+        }
+        return Node.replaceInLexicalContext(lc, this, new SplitNode(this, body, compileUnit, jumps));
+    }
+
+    /**
+     * Adds a jump that crosses this split node's boundary (it originates within the split node, and goes to a target
+     * outside of it).
+     * @param jumpOrigin the join predecessor that's the origin of the jump
+     * @param targetLabel the label that's the target of the jump.
+     */
+    public void addJump(final JoinPredecessor jumpOrigin, final Label targetLabel) {
+        if (jumps == null) {
+            jumps = new HashMap<>();
+        }
+        jumps.put(targetLabel, jumpOrigin);
+    }
+
+    /**
+     * Returns the jump origin within this split node for a target.
+     * @param targetLabel the target for which a jump origin is sought.
+     * @return the jump origin, or null.
+     */
+    public JoinPredecessor getJumpOrigin(final Label targetLabel) {
+        return jumps == null ? null : jumps.get(targetLabel);
+    }
+
+    @Override
+    public List<Label> getLabels() {
+        return Collections.unmodifiableList(new ArrayList<>(jumps.keySet()));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Statement.java b/nashorn/src/jdk/nashorn/internal/ir/Statement.java
index 6b171cb..b436f71 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Statement.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Statement.java
@@ -30,7 +30,7 @@
  * made up of statements. The only node subclass that needs to keep token and
  * location information is the Statement
  */
-public abstract class Statement extends Node {
+public abstract class Statement extends Node implements Terminal {
 
     private final int lineNumber;
 
@@ -77,4 +77,32 @@
         return lineNumber;
     }
 
+    /**
+     * Is this a terminal statement, i.e. does it end control flow like a throw or return?
+     *
+     * @return true if this node statement is terminal
+     */
+    @Override
+    public boolean isTerminal() {
+        return false;
+    }
+
+    /**
+     * Check if this statement repositions control flow with goto like
+     * semantics, for example {@link BreakNode} or a {@link ForNode} with no test
+     * @return true if statement has goto semantics
+     */
+    public boolean hasGoto() {
+        return false;
+    }
+
+    /**
+     * Check if this statement has terminal flags, i.e. ends or breaks control flow
+     *
+     * @return true if has terminal flags
+     */
+    public final boolean hasTerminalFlags() {
+        return isTerminal() || hasGoto();
+    }
 }
+
diff --git a/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java
index d31bec5..a3eac1c 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/SwitchNode.java
@@ -66,11 +66,12 @@
         this.defaultCaseIndex = defaultCase == null ? -1 : cases.indexOf(defaultCase);
     }
 
-    private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases, final int defaultCase) {
-        super(switchNode);
+    private SwitchNode(final SwitchNode switchNode, final Expression expression, final List<CaseNode> cases,
+            final int defaultCaseIndex, final LocalVariableConversion conversion) {
+        super(switchNode, conversion);
         this.expression       = expression;
         this.cases            = cases;
-        this.defaultCaseIndex = defaultCase;
+        this.defaultCaseIndex = defaultCaseIndex;
         this.tag              = switchNode.getTag(); //TODO are symbols inhereted as references?
     }
 
@@ -78,9 +79,9 @@
     public Node ensureUniqueLabels(final LexicalContext lc) {
         final List<CaseNode> newCases = new ArrayList<>();
         for (final CaseNode caseNode : cases) {
-            newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody()));
+            newCases.add(new CaseNode(caseNode, caseNode.getTest(), caseNode.getBody(), caseNode.getLocalVariableConversion()));
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, newCases, defaultCaseIndex, conversion));
     }
 
     @Override
@@ -103,16 +104,16 @@
         if (visitor.enterSwitchNode(this)) {
             return visitor.leaveSwitchNode(
                 setExpression(lc, (Expression)expression.accept(visitor)).
-                setCases(lc, Node.accept(visitor, CaseNode.class, cases), defaultCaseIndex));
+                setCases(lc, Node.accept(visitor, cases), defaultCaseIndex));
         }
 
         return this;
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("switch (");
-        expression.toString(sb);
+        expression.toString(sb, printType);
         sb.append(')');
     }
 
@@ -138,7 +139,7 @@
      * by NodeVisitors who perform operations on every case node
      * @param lc    lexical context
      * @param cases list of cases
-     * @return new switcy node or same if no state was changed
+     * @return new switch node or same if no state was changed
      */
     public SwitchNode setCases(final LexicalContext lc, final List<CaseNode> cases) {
         return setCases(lc, cases, defaultCaseIndex);
@@ -148,7 +149,7 @@
         if (this.cases == cases) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion));
     }
 
     /**
@@ -180,7 +181,7 @@
         if (this.expression == expression) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex));
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion));
     }
 
     /**
@@ -200,5 +201,27 @@
     public void setTag(final Symbol tag) {
         this.tag = tag;
     }
-}
 
+    /**
+     * Returns true if all cases of this switch statement are 32-bit signed integer constants.
+     * @return true if all cases of this switch statement are 32-bit signed integer constants.
+     */
+    public boolean isInteger() {
+        for (final CaseNode caseNode : cases) {
+            final Expression test = caseNode.getTest();
+            if (test != null && !isIntegerLiteral(test)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+        return Node.replaceInLexicalContext(lc, this, new SwitchNode(this, expression, cases, defaultCaseIndex, conversion));
+    }
+
+    private static boolean isIntegerLiteral(final Expression expr) {
+        return expr instanceof LiteralNode && ((LiteralNode<?>)expr).getValue() instanceof Integer;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
index 2906893..542537b 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/Symbol.java
@@ -29,54 +29,60 @@
 import java.util.HashSet;
 import java.util.Set;
 import java.util.StringTokenizer;
-import jdk.nashorn.internal.codegen.types.Range;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.options.Options;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
-
 /**
- * Maps a name to specific data.
+ * Symbol is a symbolic address for a value ("variable" if you wish). Identifiers in JavaScript source, as well as
+ * certain synthetic variables created by the compiler are represented by Symbol objects. Symbols can address either
+ * local variable slots in bytecode ("slotted symbol"), or properties in scope objects ("scoped symbol"). A symbol can
+ * also end up being defined but then not used during symbol assignment calculations; such symbol will be neither
+ * scoped, nor slotted; it represents a dead variable (it might be written to, but is never read). Finally, a symbol can
+ * be both slotted and in scope. This special case can only occur with bytecode method parameters. They all come in as
+ * slotted, but if they are used by a nested function (or eval) then they will be copied into the scope object, and used
+ * from there onwards. Two further special cases are parameters stored in {@code NativeArguments} objects and parameters
+ * stored in {@code Object[]} parameter to variable-arity functions. Those use the {@code #getFieldIndex()} property to
+ * refer to their location.
  */
 
 public final class Symbol implements Comparable<Symbol> {
-    /** Symbol kinds. Kind ordered by precedence. */
-    public static final int IS_TEMP     = 1;
     /** Is this Global */
-    public static final int IS_GLOBAL   = 2;
+    public static final int IS_GLOBAL   = 1;
     /** Is this a variable */
-    public static final int IS_VAR      = 3;
+    public static final int IS_VAR      = 2;
     /** Is this a parameter */
-    public static final int IS_PARAM    = 4;
+    public static final int IS_PARAM    = 3;
     /** Is this a constant */
-    public static final int IS_CONSTANT = 5;
+    public static final int IS_CONSTANT = 4;
     /** Mask for kind flags */
     public static final int KINDMASK = (1 << 3) - 1; // Kinds are represented by lower three bits
 
-    /** Is this scope */
-    public static final int IS_SCOPE             = 1 <<  4;
+    /** Is this symbol in scope */
+    public static final int IS_SCOPE                = 1 <<  3;
     /** Is this a this symbol */
-    public static final int IS_THIS              = 1 <<  5;
-    /** Can this symbol ever be undefined */
-    public static final int CAN_BE_UNDEFINED     = 1 <<  6;
-    /** Is this symbol always defined? */
-    public static final int IS_ALWAYS_DEFINED    = 1 <<  8;
-    /** Can this symbol ever have primitive types */
-    public static final int CAN_BE_PRIMITIVE     = 1 <<  9;
+    public static final int IS_THIS                 = 1 <<  4;
     /** Is this a let */
-    public static final int IS_LET               = 1 << 10;
+    public static final int IS_LET                  = 1 <<  5;
     /** Is this an internal symbol, never represented explicitly in source code */
-    public static final int IS_INTERNAL          = 1 << 11;
+    public static final int IS_INTERNAL             = 1 <<  6;
     /** Is this a function self-reference symbol */
-    public static final int IS_FUNCTION_SELF     = 1 << 12;
-    /** Is this a specialized param? */
-    public static final int IS_SPECIALIZED_PARAM = 1 << 13;
-    /** Is this symbol a shared temporary? */
-    public static final int IS_SHARED            = 1 << 14;
+    public static final int IS_FUNCTION_SELF        = 1 <<  7;
     /** Is this a function declaration? */
-    public static final int IS_FUNCTION_DECLARATION = 1 << 15;
+    public static final int IS_FUNCTION_DECLARATION = 1 <<  8;
+    /** Is this a program level symbol? */
+    public static final int IS_PROGRAM_LEVEL        = 1 <<  9;
+    /** Are this symbols' values stored in local variable slots? */
+    public static final int HAS_SLOT                = 1 << 10;
+    /** Is this symbol known to store an int value ? */
+    public static final int HAS_INT_VALUE           = 1 << 11;
+    /** Is this symbol known to store a long value ? */
+    public static final int HAS_LONG_VALUE          = 1 << 12;
+    /** Is this symbol known to store a double value ? */
+    public static final int HAS_DOUBLE_VALUE        = 1 << 13;
+    /** Is this symbol known to store an object value ? */
+    public static final int HAS_OBJECT_VALUE        = 1 << 14;
 
     /** Null or name identifying symbol. */
     private final String name;
@@ -84,11 +90,9 @@
     /** Symbol flags. */
     private int flags;
 
-    /** Type of symbol. */
-    private Type type;
-
-    /** Local variable slot. -1 indicates external property. */
-    private int slot;
+    /** First bytecode method local variable slot for storing the value(s) of this variable. -1 indicates the variable
+     * is not stored in local variable slots or it is not yet known. */
+    private int firstSlot = -1;
 
     /** Field number in scope or property; array index in varargs when not using arguments object. */
     private int fieldIndex;
@@ -96,9 +100,6 @@
     /** Number of times this symbol is used in code */
     private int useCount;
 
-    /** Range for symbol */
-    private Range range;
-
     /** Debugging option - dump info and stack trace when symbols with given names are manipulated */
     private static final Set<String> TRACE_SYMBOLS;
     private static final Set<String> TRACE_SYMBOLS_STACKTRACE;
@@ -109,7 +110,7 @@
         if (stacktrace != null) {
             trace = stacktrace; //stacktrace always implies trace as well
             TRACE_SYMBOLS_STACKTRACE = new HashSet<>();
-            for (StringTokenizer st = new StringTokenizer(stacktrace, ","); st.hasMoreTokens(); ) {
+            for (final StringTokenizer st = new StringTokenizer(stacktrace, ","); st.hasMoreTokens(); ) {
                 TRACE_SYMBOLS_STACKTRACE.add(st.nextToken());
             }
         } else {
@@ -119,7 +120,7 @@
 
         if (trace != null) {
             TRACE_SYMBOLS = new HashSet<>();
-            for (StringTokenizer st = new StringTokenizer(trace, ","); st.hasMoreTokens(); ) {
+            for (final StringTokenizer st = new StringTokenizer(trace, ","); st.hasMoreTokens(); ) {
                 TRACE_SYMBOLS.add(st.nextToken());
             }
         } else {
@@ -132,17 +133,16 @@
      *
      * @param name  name of symbol
      * @param flags symbol flags
-     * @param type  type of this symbol
      * @param slot  bytecode slot for this symbol
      */
-    protected Symbol(final String name, final int flags, final Type type, final int slot) {
+    protected Symbol(final String name, final int flags, final int slot) {
         this.name       = name;
         this.flags      = flags;
-        this.type       = type;
-        this.slot       = slot;
+        this.firstSlot  = slot;
         this.fieldIndex = -1;
-        this.range      = Range.createUnknownRange();
-        trace("CREATE SYMBOL");
+        if(shouldTrace()) {
+            trace("CREATE SYMBOL " + name);
+        }
     }
 
     /**
@@ -152,29 +152,7 @@
      * @param flags symbol flags
      */
     public Symbol(final String name, final int flags) {
-        this(name, flags, Type.UNKNOWN, -1);
-    }
-
-    /**
-     * Constructor
-     *
-     * @param name  name of symbol
-     * @param flags symbol flags
-     * @param type  type of this symbol
-     */
-    public Symbol(final String name, final int flags, final Type type) {
-        this(name, flags, type, -1);
-    }
-
-    private Symbol(final Symbol base, final String name, final int flags) {
-        this.flags = flags;
-        this.name  = name;
-
-        this.fieldIndex = base.fieldIndex;
-        this.slot       = base.slot;
-        this.type       = base.type;
-        this.useCount   = base.useCount;
-        this.range      = base.range;
+        this(name, flags, -1);
     }
 
     private static String align(final String string, final int max) {
@@ -188,74 +166,59 @@
     }
 
     /**
-     * Return the type for this symbol. Normally, if there is no type override,
-     * this is where any type for any node is stored. If the node has a TypeOverride,
-     * it may override this, e.g. when asking for a scoped field as a double
-     *
-     * @return symbol type
-     */
-    public final Type getSymbolType() {
-        return type;
-    }
-
-    /**
      * Debugging .
      *
      * @param stream Stream to print to.
      */
 
     void print(final PrintWriter stream) {
-        final String printName = align(name, 20);
-        final String printType = align(type.toString(), 10);
-        final String printSlot = align(slot == -1 ? "none" : "" + slot, 10);
-        String printFlags = "";
+        final StringBuilder sb = new StringBuilder();
+
+        sb.append(align(name, 20)).
+            append(": ").
+            append(", ").
+            append(align(firstSlot == -1 ? "none" : "" + firstSlot, 10));
 
         switch (flags & KINDMASK) {
-        case IS_TEMP:
-            printFlags = "temp " + printFlags;
-            break;
         case IS_GLOBAL:
-            printFlags = "global " + printFlags;
+            sb.append(" global");
             break;
         case IS_VAR:
-            printFlags = "var " + printFlags;
+            sb.append(" var");
             break;
         case IS_PARAM:
-            printFlags = "param " + printFlags;
+            sb.append(" param");
             break;
         case IS_CONSTANT:
-            printFlags = "CONSTANT " + printFlags;
+            sb.append(" const");
             break;
         default:
             break;
         }
 
         if (isScope()) {
-            printFlags += "scope ";
+            sb.append(" scope");
         }
 
         if (isInternal()) {
-            printFlags += "internal ";
+            sb.append(" internal");
         }
 
         if (isLet()) {
-            printFlags += "let ";
+            sb.append(" let");
         }
 
         if (isThis()) {
-            printFlags += "this ";
+            sb.append(" this");
         }
 
-        if (!canBeUndefined()) {
-            printFlags += "always_def ";
+        if (isProgramLevel()) {
+            sb.append(" program");
         }
 
-        if (canBePrimitive()) {
-            printFlags += "can_be_prim ";
-        }
+        sb.append('\n');
 
-        stream.print(printName + ": " + printType + ", " + printSlot + ", " + printFlags);
-        stream.println();
+        stream.print(sb.toString());
     }
 
     /**
@@ -272,9 +235,16 @@
      * Allocate a slot for this symbol.
      *
      * @param needsSlot True if symbol needs a slot.
+     * @return the symbol
      */
-    public void setNeedsSlot(final boolean needsSlot) {
-        setSlot(needsSlot ? 0 : -1);
+    public Symbol setNeedsSlot(final boolean needsSlot) {
+        if(needsSlot) {
+            assert !isScope();
+            flags |= HAS_SLOT;
+        } else {
+            flags &= ~HAS_SLOT;
+        }
+        return this;
     }
 
     /**
@@ -283,7 +253,14 @@
      * @return Number of slots.
      */
     public int slotCount() {
-        return type.isCategory2() ? 2 : 1;
+        return ((flags & HAS_INT_VALUE)    == 0 ? 0 : 1) +
+               ((flags & HAS_LONG_VALUE)   == 0 ? 0 : 2) +
+               ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2) +
+               ((flags & HAS_OBJECT_VALUE) == 0 ? 0 : 1);
+    }
+
+    private boolean isSlotted() {
+        return firstSlot != -1 && ((flags & HAS_SLOT) != 0);
     }
 
     @Override
@@ -291,17 +268,18 @@
         final StringBuilder sb = new StringBuilder();
 
         sb.append(name).
-            append(' ').
-            append('(').
-            append(getSymbolType().getTypeClass().getSimpleName()).
-            append(')');
+            append(' ');
 
         if (hasSlot()) {
             sb.append(' ').
                 append('(').
                 append("slot=").
-                append(slot).
-                append(')');
+                append(firstSlot).append(' ');
+            if((flags & HAS_INT_VALUE) != 0) { sb.append('I'); }
+            if((flags & HAS_LONG_VALUE) != 0) { sb.append('J'); }
+            if((flags & HAS_DOUBLE_VALUE) != 0) { sb.append('D'); }
+            if((flags & HAS_OBJECT_VALUE) != 0) { sb.append('O'); }
+            sb.append(')');
         }
 
         if (isScope()) {
@@ -312,10 +290,6 @@
             }
         }
 
-        if (canBePrimitive()) {
-            sb.append(" P?");
-        }
-
         return sb.toString();
     }
 
@@ -325,21 +299,31 @@
     }
 
     /**
-     * Does this symbol have an allocated bytecode slot. If not, it is scope
-     * and must be loaded from memory upon access
+     * Does this symbol have an allocated bytecode slot? Note that having an allocated bytecode slot doesn't necessarily
+     * mean the symbol's value will be stored in it. Namely, a function parameter can have a bytecode slot, but if it is
+     * in scope, then the bytecode slot will not be used. See {@link #isBytecodeLocal()}.
      *
      * @return true if this symbol has a local bytecode slot
      */
     public boolean hasSlot() {
-        return slot >= 0;
+        return (flags & HAS_SLOT) != 0;
     }
 
     /**
-     * Check if this is a temporary symbol
-     * @return true if temporary
+     * Is this symbol a local variable stored in bytecode local variable slots? This is true for a slotted variable that
+     * is not in scope. (E.g. a parameter that is in scope is slotted, but it will not be a local variable).
+     * @return true if this symbol is using bytecode local slots for its storage.
      */
-    public boolean isTemp() {
-        return (flags & KINDMASK) == IS_TEMP;
+    public boolean isBytecodeLocal() {
+        return hasSlot() && !isScope();
+    }
+
+    /**
+     * Returns true if this symbol is dead (it is a local variable that is statically proven to never be read in any type).
+     * @return true if this symbol is dead
+     */
+    public boolean isDead() {
+        return (flags & (HAS_SLOT | IS_SCOPE)) == 0;
     }
 
     /**
@@ -349,16 +333,8 @@
      * @return true if this is scoped
      */
     public boolean isScope() {
-        assert ((flags & KINDMASK) != IS_GLOBAL) || ((flags & IS_SCOPE) == IS_SCOPE) : "global without scope flag";
-        return (flags & IS_SCOPE) == IS_SCOPE;
-    }
-
-    /**
-     * Returns true if this symbol is a temporary that is being shared across expressions.
-     * @return true if this symbol is a temporary that is being shared across expressions.
-     */
-    public boolean isShared() {
-        return (flags & IS_SHARED) == IS_SHARED;
+        assert (flags & KINDMASK) != IS_GLOBAL || (flags & IS_SCOPE) == IS_SCOPE : "global without scope flag";
+        return (flags & IS_SCOPE) != 0;
     }
 
     /**
@@ -366,51 +342,34 @@
      * @return true if a function declaration
      */
     public boolean isFunctionDeclaration() {
-        return (flags & IS_FUNCTION_DECLARATION) == IS_FUNCTION_DECLARATION;
-    }
-
-    /**
-     * Creates an unshared copy of a symbol. The symbol must be currently shared.
-     * @param newName the name for the new symbol.
-     * @return a new, unshared symbol.
-     */
-    public Symbol createUnshared(final String newName) {
-        assert isShared();
-        return new Symbol(this, newName, flags & ~IS_SHARED);
+        return (flags & IS_FUNCTION_DECLARATION) != 0;
     }
 
     /**
      * Flag this symbol as scope as described in {@link Symbol#isScope()}
+     * @return the symbol
      */
-    /**
-     * Flag this symbol as scope as described in {@link Symbol#isScope()}
-     */
-     public void setIsScope() {
+     public Symbol setIsScope() {
         if (!isScope()) {
-            trace("SET IS SCOPE");
-            assert !isShared();
+            if(shouldTrace()) {
+                trace("SET IS SCOPE");
+            }
             flags |= IS_SCOPE;
+            if(!isParam()) {
+                flags &= ~HAS_SLOT;
+            }
         }
+        return this;
     }
 
-     /**
-      * Mark this symbol as one being shared by multiple expressions. The symbol must be a temporary.
-      */
-     public void setIsShared() {
-         if (!isShared()) {
-             assert isTemp();
-             trace("SET IS SHARED");
-             flags |= IS_SHARED;
-         }
-     }
-
-
     /**
      * Mark this symbol as a function declaration.
      */
     public void setIsFunctionDeclaration() {
         if (!isFunctionDeclaration()) {
-            trace("SET IS FUNCTION DECLARATION");
+            if(shouldTrace()) {
+                trace("SET IS FUNCTION DECLARATION");
+            }
             flags |= IS_FUNCTION_DECLARATION;
         }
     }
@@ -440,84 +399,11 @@
     }
 
     /**
-     * Check if this symbol is always defined, which overrides all canBeUndefined tags
-     * @return true if always defined
+     * Check if this is a program (script) level definition
+     * @return true if program level
      */
-    public boolean isAlwaysDefined() {
-        return isParam() || (flags & IS_ALWAYS_DEFINED) == IS_ALWAYS_DEFINED;
-    }
-
-    /**
-     * Get the range for this symbol
-     * @return range for symbol
-     */
-    public Range getRange() {
-        return range;
-    }
-
-    /**
-     * Set the range for this symbol
-     * @param range range
-     */
-    public void setRange(final Range range) {
-        this.range = range;
-    }
-
-    /**
-     * Check if this symbol represents a return value with a known non-generic type.
-     * @return true if specialized return value
-     */
-    public boolean isNonGenericReturn() {
-        return getName().equals(RETURN.symbolName()) && type != Type.OBJECT;
-    }
-
-    /**
-     * Check if this symbol is a function parameter of known
-     * narrowest type
-     * @return true if parameter
-     */
-    public boolean isSpecializedParam() {
-        return (flags & IS_SPECIALIZED_PARAM) == IS_SPECIALIZED_PARAM;
-    }
-
-    /**
-     * Check whether this symbol ever has primitive assignments. Conservative
-     * @return true if primitive assignments exist
-     */
-    public boolean canBePrimitive() {
-        return (flags & CAN_BE_PRIMITIVE) == CAN_BE_PRIMITIVE;
-    }
-
-    /**
-     * Check if this symbol can ever be undefined
-     * @return true if can be undefined
-     */
-    public boolean canBeUndefined() {
-        return (flags & CAN_BE_UNDEFINED) == CAN_BE_UNDEFINED;
-    }
-
-    /**
-     * Flag this symbol as potentially undefined in parts of the program
-     */
-    public void setCanBeUndefined() {
-        assert type.isObject() : type;
-        if (isAlwaysDefined()) {
-            return;
-        } else if (!canBeUndefined()) {
-            assert !isShared();
-            flags |= CAN_BE_UNDEFINED;
-        }
-    }
-
-    /**
-     * Flag this symbol as potentially primitive
-     * @param type the primitive type it occurs with, currently unused but can be used for width guesses
-     */
-    public void setCanBePrimitive(final Type type) {
-        if(!canBePrimitive()) {
-            assert !isShared();
-            flags |= CAN_BE_PRIMITIVE;
-        }
+    public boolean isProgramLevel() {
+        return (flags & IS_PROGRAM_LEVEL) != 0;
     }
 
     /**
@@ -550,15 +436,14 @@
      * @return true if let
      */
     public boolean isLet() {
-        return (flags & IS_LET) == IS_LET;
+        return (flags & IS_LET) != 0;
     }
 
     /**
      * Flag this symbol as a let
      */
     public void setIsLet() {
-        if(!isLet()) {
-            assert !isShared();
+        if (!isLet()) {
             flags |= IS_LET;
         }
     }
@@ -568,7 +453,7 @@
      * @return true if this symbol as a function's self-referencing symbol.
      */
     public boolean isFunctionSelf() {
-        return (flags & IS_FUNCTION_SELF) == IS_FUNCTION_SELF;
+        return (flags & IS_FUNCTION_SELF) != 0;
     }
 
     /**
@@ -587,12 +472,13 @@
      * and get allocated in a JO-prefixed ScriptObject subclass.
      *
      * @param fieldIndex field index - a positive integer
+     * @return the symbol
      */
-    public void setFieldIndex(final int fieldIndex) {
-        if(this.fieldIndex != fieldIndex) {
-            assert !isShared();
+    public Symbol setFieldIndex(final int fieldIndex) {
+        if (this.fieldIndex != fieldIndex) {
             this.fieldIndex = fieldIndex;
         }
+        return this;
     }
 
     /**
@@ -606,12 +492,37 @@
     /**
      * Set the symbol flags
      * @param flags flags
+     * @return the symbol
      */
-    public void setFlags(final int flags) {
-        if(this.flags != flags) {
-            assert !isShared();
+    public Symbol setFlags(final int flags) {
+        if (this.flags != flags) {
             this.flags = flags;
         }
+        return this;
+    }
+
+    /**
+     * Set a single symbol flag
+     * @param flag flag to set
+     * @return the symbol
+     */
+    public Symbol setFlag(final int flag) {
+        if ((this.flags & flag) == 0) {
+            this.flags |= flag;
+        }
+        return this;
+    }
+
+    /**
+     * Clears a single symbol flag
+     * @param flag flag to set
+     * @return the symbol
+     */
+    public Symbol clearFlag(final int flag) {
+        if ((this.flags & flag) != 0) {
+            this.flags &= ~flag;
+        }
+        return this;
     }
 
     /**
@@ -623,18 +534,82 @@
     }
 
     /**
-     * Get the byte code slot for this symbol
-     * @return byte code slot, or -1 if no slot allocated/possible
+     * Get the index of the first bytecode slot for this symbol
+     * @return byte code slot
      */
-    public int getSlot() {
-        return slot;
+    public int getFirstSlot() {
+        assert isSlotted();
+        return firstSlot;
+    }
+
+    /**
+     * Get the index of the bytecode slot for this symbol for storing a value of the specified type.
+     * @param type the requested type
+     * @return byte code slot
+     */
+    public int getSlot(final Type type) {
+        assert isSlotted();
+        int typeSlot = firstSlot;
+        if(type.isBoolean() || type.isInteger()) {
+            assert (flags & HAS_INT_VALUE) != 0;
+            return typeSlot;
+        }
+        typeSlot += ((flags & HAS_INT_VALUE) == 0 ? 0 : 1);
+        if(type.isLong()) {
+            assert (flags & HAS_LONG_VALUE) != 0;
+            return typeSlot;
+        }
+        typeSlot += ((flags & HAS_LONG_VALUE) == 0 ? 0 : 2);
+        if(type.isNumber()) {
+            assert (flags & HAS_DOUBLE_VALUE) != 0;
+            return typeSlot;
+        }
+        assert type.isObject();
+        assert (flags & HAS_OBJECT_VALUE) != 0 : name;
+        return typeSlot + ((flags & HAS_DOUBLE_VALUE) == 0 ? 0 : 2);
+    }
+
+    /**
+     * Returns true if this symbol has a local variable slot for storing a value of specific type.
+     * @param type the type
+     * @return true if this symbol has a local variable slot for storing a value of specific type.
+     */
+    public boolean hasSlotFor(final Type type) {
+        if(type.isBoolean() || type.isInteger()) {
+            return (flags & HAS_INT_VALUE) != 0;
+        } else if(type.isLong()) {
+            return (flags & HAS_LONG_VALUE) != 0;
+        } else if(type.isNumber()) {
+            return (flags & HAS_DOUBLE_VALUE) != 0;
+        }
+        assert type.isObject();
+        return (flags & HAS_OBJECT_VALUE) != 0;
+    }
+
+    /**
+     * Marks this symbol as having a local variable slot for storing a value of specific type.
+     * @param type the type
+     */
+    public void setHasSlotFor(final Type type) {
+        if(type.isBoolean() || type.isInteger()) {
+            setFlag(HAS_INT_VALUE);
+        } else if(type.isLong()) {
+            setFlag(HAS_LONG_VALUE);
+        } else if(type.isNumber()) {
+            setFlag(HAS_DOUBLE_VALUE);
+        } else {
+            assert type.isObject();
+            setFlag(HAS_OBJECT_VALUE);
+        }
     }
 
     /**
      * Increase the symbol's use count by one.
+     * @return the symbol
      */
-    public void increaseUseCount() {
+    public Symbol increaseUseCount() {
         useCount++;
+        return this;
     }
 
     /**
@@ -647,76 +622,16 @@
 
     /**
      * Set the bytecode slot for this symbol
-     * @param slot valid bytecode slot, or -1 if not available
+     * @param  firstSlot valid bytecode slot
+     * @return the symbol
      */
-    public void setSlot(final int slot) {
-        if (slot != this.slot) {
-            assert !isShared();
-            trace("SET SLOT " + slot);
-            this.slot = slot;
-        }
-    }
-
-    /**
-     * Assign a specific subclass of Object to the symbol
-     *
-     * @param type  the type
-     */
-    public void setType(final Class<?> type) {
-        assert !type.isPrimitive() && !Number.class.isAssignableFrom(type) : "Class<?> types can only be subclasses of object";
-        setType(Type.typeFor(type));
-    }
-
-    /**
-     * Assign a type to the symbol
-     *
-     * @param type the type
-     */
-    public void setType(final Type type) {
-        setTypeOverride(Type.widest(this.type, type));
-    }
-
-    /**
-     * Returns true if calling {@link #setType(Type)} on this symbol would effectively change its type.
-     * @param newType the new type to test for
-     * @return true if setting this symbols type to a new value would effectively change its type.
-     */
-    public boolean wouldChangeType(final Type newType) {
-        return Type.widest(this.type, newType) != this.type;
-    }
-
-    /**
-     * Only use this if you know about an existing type
-     * constraint - otherwise a type can only be
-     * widened
-     *
-     * @param type  the type
-     */
-    public void setTypeOverride(final Type type) {
-        final Type old = this.type;
-        if (old != type) {
-            assert !isShared();
-            trace("TYPE CHANGE: " + old + "=>" + type + " == " + type);
-            this.type = type;
-        }
-    }
-
-    /**
-     * Sets the type of the symbol to the specified type. If the type would be changed, but this symbol is a shared
-     * temporary, it will instead return a different temporary symbol of the requested type from the passed temporary
-     * symbols. That way, it never mutates the type of a shared temporary.
-     * @param type the new type for the symbol
-     * @param ts a holder of temporary symbols
-     * @return either this symbol, or a different symbol if this symbol is a shared temporary and it type would have to
-     * be changed.
-     */
-    public Symbol setTypeOverrideShared(final Type type, final TemporarySymbols ts) {
-        if(getSymbolType() != type) {
-            if(isShared()) {
-                assert !hasSlot();
-                return ts.getTypedTemporarySymbol(type);
+    public Symbol setFirstSlot(final int firstSlot) {
+        assert firstSlot >= 0 && firstSlot <= 65535;
+        if (firstSlot != this.firstSlot) {
+            if(shouldTrace()) {
+                trace("SET SLOT " + firstSlot);
             }
-            setTypeOverride(type);
+            this.firstSlot = firstSlot;
         }
         return this;
     }
@@ -728,22 +643,26 @@
      * when flags need to be tagged, but block is in the
      * middle of evaluation and cannot be modified.
      *
-     * @param lc     lexical context
-     * @param symbol symbol
+     * @param  lc     lexical context
+     * @param  symbol symbol
+     * @return the symbol
      */
-    public static void setSymbolIsScope(final LexicalContext lc, final Symbol symbol) {
+    public static Symbol setSymbolIsScope(final LexicalContext lc, final Symbol symbol) {
         symbol.setIsScope();
         if (!symbol.isGlobal()) {
             lc.setBlockNeedsScope(lc.getDefiningBlock(symbol));
         }
+        return symbol;
+    }
+
+    private boolean shouldTrace() {
+        return TRACE_SYMBOLS != null && (TRACE_SYMBOLS.isEmpty() || TRACE_SYMBOLS.contains(name));
     }
 
     private void trace(final String desc) {
-        if (TRACE_SYMBOLS != null && (TRACE_SYMBOLS.isEmpty() || TRACE_SYMBOLS.contains(name))) {
-            Context.err(Debug.id(this) + " SYMBOL: '" + name + "' " + desc);
-            if (TRACE_SYMBOLS_STACKTRACE != null && (TRACE_SYMBOLS_STACKTRACE.isEmpty() || TRACE_SYMBOLS_STACKTRACE.contains(name))) {
-                new Throwable().printStackTrace(Context.getCurrentErr());
-            }
+        Context.err(Debug.id(this) + " SYMBOL: '" + name + "' " + desc);
+        if (TRACE_SYMBOLS_STACKTRACE != null && (TRACE_SYMBOLS_STACKTRACE.isEmpty() || TRACE_SYMBOLS_STACKTRACE.contains(name))) {
+            new Throwable().printStackTrace(Context.getCurrentErr());
         }
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java b/nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java
deleted file mode 100644
index 4a438dd..0000000
--- a/nashorn/src/jdk/nashorn/internal/ir/TemporarySymbols.java
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.ir;
-
-import static jdk.nashorn.internal.codegen.CompilerConstants.TEMP_PREFIX;
-import static jdk.nashorn.internal.ir.Symbol.IS_TEMP;
-
-import java.util.HashMap;
-import java.util.Map;
-import jdk.nashorn.internal.codegen.types.Type;
-
-/**
- * Class that holds reusable temporary symbols by type.
- *
- */
-public class TemporarySymbols {
-    private static final String prefix = TEMP_PREFIX.symbolName() + "$";
-
-    private int totalSymbolCount;
-    private final Map<Type, TypedTemporarySymbols> temporarySymbolsByType = new HashMap<>();
-
-    /**
-     * Associates a temporary symbol of a given type with a node, if the node doesn't already have any symbol.
-     * @param lc the current lexical context
-     * @param type the type of the temporary symbol
-     * @param node the node
-     * @return the node that is guaranteed to have a symbol.
-     */
-    public Expression ensureSymbol(final LexicalContext lc, final Type type, final Expression node) {
-        final Symbol symbol = node.getSymbol();
-        if (symbol != null) {
-            return node;
-        }
-        return node.setSymbol(lc, getTypedTemporarySymbol(type));
-    }
-
-    /**
-     * Given a type, returns a temporary symbol of that type.
-     * @param type the required type of the symbol.
-     * @return a temporary symbol of the required type.
-     */
-    public Symbol getTypedTemporarySymbol(final Type type) {
-        return getTypedTemporarySymbols(type).getTemporarySymbol(type);
-    }
-
-    private TypedTemporarySymbols getTypedTemporarySymbols(final Type type) {
-        TypedTemporarySymbols temporarySymbols = temporarySymbolsByType.get(type);
-        if(temporarySymbols == null) {
-            temporarySymbols = new TypedTemporarySymbols();
-            temporarySymbolsByType.put(type, temporarySymbols);
-        }
-        return temporarySymbols;
-    }
-
-    /**
-     * This method is called to signal to this object that all the symbols it holds can be reused now.
-     */
-    public void reuse() {
-        for(TypedTemporarySymbols ts: temporarySymbolsByType.values()) {
-            ts.reuse();
-        }
-    }
-
-    /**
-     * Given a shared symbol, creates an unshared copy of it with a unique name.
-     * @param symbol the shared symbol
-     * @return the unshared, uniquely named copy of the symbol
-     */
-    public Symbol createUnshared(Symbol symbol) {
-        return symbol.createUnshared(getUniqueName());
-    }
-
-    private String getUniqueName() {
-        return prefix + (++totalSymbolCount);
-    }
-
-    /**
-     * Returns the total number of symbols this object created during its lifetime.
-     * @return the total number of symbols this object created during its lifetime.
-     */
-    public int getTotalSymbolCount() {
-        return totalSymbolCount;
-    }
-
-    private class TypedTemporarySymbols {
-        private Symbol[] symbols = new Symbol[16];
-        private int nextFreeSymbol = 0;
-        private int symbolCount = 0;
-
-        Symbol getTemporarySymbol(final Type type) {
-            while(nextFreeSymbol < symbolCount) {
-                final Symbol nextSymbol = symbols[nextFreeSymbol];
-                assert nextSymbol != null;
-                // If it has a slot, we can't reuse it.
-                if(!nextSymbol.hasSlot()) {
-                    final Type symbolType = nextSymbol.getSymbolType();
-                    if(symbolType == type) {
-                        assert nextSymbol.isTemp();
-                        assert !nextSymbol.isScope();
-                        // If types match, we can reuse it.
-                        nextSymbol.setIsShared();
-                        nextFreeSymbol++;
-                        return nextSymbol;
-                    }
-                    // If its type changed, but it doesn't have a slot then move it to its new home according to its
-                    // new type.
-                    getTypedTemporarySymbols(symbolType).addSymbol(nextSymbol);
-                }
-                // If we can move another symbol into its place, do that and repeat the analysis for this symbol.
-                --symbolCount;
-                if(symbolCount != nextFreeSymbol) {
-                    final Symbol lastFreeSymbol = symbols[symbolCount];
-                    symbols[nextFreeSymbol] = lastFreeSymbol;
-                }
-                symbols[symbolCount] = null;
-            }
-            return createNewSymbol(type);
-        }
-
-        private Symbol createNewSymbol(final Type type) {
-            ensureCapacity();
-            final Symbol symbol = symbols[nextFreeSymbol] = new Symbol(getUniqueName(), IS_TEMP, type);
-            nextFreeSymbol++;
-            symbolCount++;
-            return symbol;
-        }
-
-        private void addSymbol(Symbol symbol) {
-            ensureCapacity();
-            symbols[symbolCount++] = symbol;
-        }
-
-        void reuse() {
-            nextFreeSymbol = 0;
-        }
-
-        private void ensureCapacity() {
-            if(symbolCount == symbols.length) {
-                final Symbol[] newSymbols = new Symbol[symbolCount * 2];
-                System.arraycopy(symbols, 0, newSymbols, 0, symbolCount);
-                symbols = newSymbols;
-            }
-        }
-    }
-
-}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/Terminal.java b/nashorn/src/jdk/nashorn/internal/ir/Terminal.java
new file mode 100644
index 0000000..3f5c25b
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/Terminal.java
@@ -0,0 +1,37 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.ir;
+
+/**
+ * Interface for AST nodes that can have a flag determining if they can terminate function control flow.
+ */
+public interface Terminal {
+    /**
+     * Returns true if this AST node is (or contains) a statement that terminates function control flow.
+     * @return true if this AST node is (or contains) a statement that terminates function control flow.
+     */
+    public boolean isTerminal();
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java b/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java
index 26c14b7..ed8016a 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/TernaryNode.java
@@ -25,20 +25,21 @@
 
 package jdk.nashorn.internal.ir;
 
+import java.util.function.Function;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.parser.TokenType;
 
 /**
- * TernaryNode nodes represent three operand operations (?:).
+ * TernaryNode represent the ternary operator {@code ?:}. Note that for control-flow calculation reasons its branch
+ * expressions (but not its test expression) are always wrapped in instances of {@link JoinPredecessorExpression}.
  */
 @Immutable
 public final class TernaryNode extends Expression {
     private final Expression test;
-
-    private final Expression trueExpr;
-
-    /** Third argument. */
-    private final Expression falseExpr;
+    private final JoinPredecessorExpression trueExpr;
+    private final JoinPredecessorExpression falseExpr;
 
     /**
      * Constructor
@@ -48,14 +49,15 @@
      * @param trueExpr  expression evaluated when test evaluates to true
      * @param falseExpr expression evaluated when test evaluates to true
      */
-    public TernaryNode(final long token, final Expression test, final Expression trueExpr, final Expression falseExpr) {
+    public TernaryNode(final long token, final Expression test, final JoinPredecessorExpression trueExpr, final JoinPredecessorExpression falseExpr) {
         super(token, falseExpr.getFinish());
         this.test = test;
         this.trueExpr = trueExpr;
         this.falseExpr = falseExpr;
     }
 
-    private TernaryNode(final TernaryNode ternaryNode, final Expression test, final Expression trueExpr, final Expression falseExpr) {
+    private TernaryNode(final TernaryNode ternaryNode, final Expression test, final JoinPredecessorExpression trueExpr,
+            final JoinPredecessorExpression falseExpr) {
         super(ternaryNode);
         this.test = test;
         this.trueExpr = trueExpr;
@@ -66,24 +68,25 @@
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterTernaryNode(this)) {
             final Expression newTest = (Expression)getTest().accept(visitor);
-            final Expression newTrueExpr = (Expression)getTrueExpression().accept(visitor);
-            final Expression newFalseExpr = (Expression)falseExpr.accept(visitor);
-            return visitor.leaveTernaryNode(setTest(newTest).setTrueExpression(newTrueExpr).setFalseExpression1(newFalseExpr));
+            final JoinPredecessorExpression newTrueExpr = (JoinPredecessorExpression)trueExpr.accept(visitor);
+            final JoinPredecessorExpression newFalseExpr = (JoinPredecessorExpression)falseExpr.accept(visitor);
+            return visitor.leaveTernaryNode(setTest(newTest).setTrueExpression(newTrueExpr).setFalseExpression(newFalseExpr));
         }
 
         return this;
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        final boolean testParen  = tokenType().needsParens(getTest().tokenType(), true);
-        final boolean trueParen  = tokenType().needsParens(getTrueExpression().tokenType(), false);
-        final boolean falseParen = tokenType().needsParens(getFalseExpression().tokenType(), false);
+    public void toString(final StringBuilder sb, final boolean printType) {
+        final TokenType tokenType  = tokenType();
+        final boolean   testParen  = tokenType.needsParens(getTest().tokenType(), true);
+        final boolean   trueParen  = tokenType.needsParens(getTrueExpression().tokenType(), false);
+        final boolean   falseParen = tokenType.needsParens(getFalseExpression().tokenType(), false);
 
         if (testParen) {
             sb.append('(');
         }
-        getTest().toString(sb);
+        getTest().toString(sb, printType);
         if (testParen) {
             sb.append(')');
         }
@@ -93,7 +96,7 @@
         if (trueParen) {
             sb.append('(');
         }
-        getTrueExpression().toString(sb);
+        getTrueExpression().toString(sb, printType);
         if (trueParen) {
             sb.append(')');
         }
@@ -103,7 +106,7 @@
         if (falseParen) {
             sb.append('(');
         }
-        getFalseExpression().toString(sb);
+        getFalseExpression().toString(sb, printType);
         if (falseParen) {
             sb.append(')');
         }
@@ -116,6 +119,12 @@
                 && getFalseExpression().isLocal();
     }
 
+    @Override
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        return Type.widestReturnType(getTrueExpression().getType(localVariableTypes), getFalseExpression().getType(localVariableTypes));
+    }
+
+
     /**
      * Get the test expression for this ternary expression, i.e. "x" in x ? y : z
      * @return the test expression
@@ -128,7 +137,7 @@
      * Get the true expression for this ternary expression, i.e. "y" in x ? y : z
      * @return the true expression
      */
-    public Expression getTrueExpression() {
+    public JoinPredecessorExpression getTrueExpression() {
         return trueExpr;
     }
 
@@ -136,7 +145,7 @@
      * Get the false expression for this ternary expression, i.e. "z" in x ? y : z
      * @return the false expression
      */
-    public Expression getFalseExpression() {
+    public JoinPredecessorExpression getFalseExpression() {
         return falseExpr;
     }
 
@@ -157,7 +166,7 @@
      * @param trueExpr new true expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public TernaryNode setTrueExpression(final Expression trueExpr) {
+    public TernaryNode setTrueExpression(final JoinPredecessorExpression trueExpr) {
         if (this.trueExpr == trueExpr) {
             return this;
         }
@@ -169,7 +178,7 @@
      * @param falseExpr new false expression
      * @return a node equivalent to this one except for the requested change.
      */
-    public TernaryNode setFalseExpression1(final Expression falseExpr) {
+    public TernaryNode setFalseExpression(final JoinPredecessorExpression falseExpr) {
         if (this.falseExpr == falseExpr) {
             return this;
         }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java b/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java
index 70efa53..5f5a135 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/ThrowNode.java
@@ -32,14 +32,13 @@
  * IR representation for THROW statements.
  */
 @Immutable
-public final class ThrowNode extends Statement {
+public final class ThrowNode extends Statement implements JoinPredecessor {
     /** Exception expression. */
     private final Expression expression;
 
-    private final int flags;
+    private final LocalVariableConversion conversion;
 
-    /** Is this block a synthethic rethrow created by finally inlining? */
-    public static final int IS_SYNTHETIC_RETHROW = 1;
+    private final boolean isSyntheticRethrow;
 
     /**
      * Constructor
@@ -48,18 +47,21 @@
      * @param token      token
      * @param finish     finish
      * @param expression expression to throw
-     * @param flags      flags
+     * @param isSyntheticRethrow true if this throw node is part of a synthetic rethrow.
      */
-    public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final int flags) {
+    public ThrowNode(final int lineNumber, final long token, final int finish, final Expression expression, final boolean isSyntheticRethrow) {
         super(lineNumber, token, finish);
         this.expression = expression;
-        this.flags = flags;
+        this.isSyntheticRethrow = isSyntheticRethrow;
+        this.conversion = null;
     }
 
-    private ThrowNode(final ThrowNode node, final Expression expression, final int flags) {
+    private ThrowNode(final ThrowNode node, final Expression expression, final boolean isSyntheticRethrow,
+            final LocalVariableConversion conversion) {
         super(node);
         this.expression = expression;
-        this.flags = flags;
+        this.isSyntheticRethrow = isSyntheticRethrow;
+        this.conversion = conversion;
     }
 
     @Override
@@ -81,11 +83,14 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("throw ");
 
         if (expression != null) {
-            expression.toString(sb);
+            expression.toString(sb, printType);
+        }
+        if (conversion != null) {
+            conversion.toString(sb);
         }
     }
 
@@ -106,7 +111,7 @@
         if (this.expression == expression) {
             return this;
         }
-        return new ThrowNode(this, expression, flags);
+        return new ThrowNode(this, expression, isSyntheticRethrow, conversion);
     }
 
     /**
@@ -116,7 +121,20 @@
      * @return true if synthetic throw node
      */
     public boolean isSyntheticRethrow() {
-        return (flags & IS_SYNTHETIC_RETHROW) == IS_SYNTHETIC_RETHROW;
+        return isSyntheticRethrow;
+    }
+
+    @Override
+    public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return new ThrowNode(this, expression, isSyntheticRethrow, conversion);
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
     }
 
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/TryNode.java b/nashorn/src/jdk/nashorn/internal/ir/TryNode.java
index 6c30118..87a8c56 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/TryNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/TryNode.java
@@ -28,8 +28,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
-
-import jdk.nashorn.internal.codegen.Label;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 
@@ -37,7 +35,7 @@
  * IR representation of a TRY statement.
  */
 @Immutable
-public final class TryNode extends Statement {
+public final class TryNode extends Statement implements JoinPredecessor {
     /** Try statements. */
     private final Block body;
 
@@ -47,15 +45,14 @@
     /** Finally clause. */
     private final Block finallyBody;
 
-    /** Exit label. */
-    private final Label exit;
-
     /** Exception symbol. */
     private Symbol exception;
 
     /** Catchall exception for finally expansion, where applicable */
     private Symbol finallyCatchAll;
 
+    private final LocalVariableConversion conversion;
+
     /**
      * Constructor
      *
@@ -71,21 +68,22 @@
         this.body        = body;
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
-        this.exit        = new Label("exit");
+        this.conversion  = null;
     }
 
-    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody) {
+    private TryNode(final TryNode tryNode, final Block body, final List<Block> catchBlocks, final Block finallyBody, final LocalVariableConversion conversion) {
         super(tryNode);
         this.body        = body;
         this.catchBlocks = catchBlocks;
         this.finallyBody = finallyBody;
-        this.exit        = new Label(tryNode.exit);
+        this.conversion  = conversion;
+        this.exception = tryNode.exception;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
         //try nodes are never in lex context
-        return new TryNode(this, body, catchBlocks, finallyBody);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
     }
 
     @Override
@@ -114,8 +112,7 @@
             return visitor.leaveTryNode(
                 setBody(newBody).
                 setFinallyBody(newFinallyBody).
-                setCatchBlocks(Node.accept(visitor, Block.class, catchBlocks)).
-                setException(exception).
+                setCatchBlocks(Node.accept(visitor, catchBlocks)).
                 setFinallyCatchAll(finallyCatchAll));
         }
 
@@ -123,7 +120,7 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("try ");
     }
 
@@ -144,7 +141,7 @@
         if (this.body == body) {
             return this;
         }
-        return new TryNode(this,  body, catchBlocks, finallyBody);
+        return new TryNode(this,  body, catchBlocks, finallyBody, conversion);
     }
 
     /**
@@ -154,11 +151,15 @@
     public List<CatchNode> getCatches() {
         final List<CatchNode> catches = new ArrayList<>(catchBlocks.size());
         for (final Block catchBlock : catchBlocks) {
-            catches.add((CatchNode)catchBlock.getStatements().get(0));
+            catches.add(getCatchNodeFromBlock(catchBlock));
         }
         return Collections.unmodifiableList(catches);
     }
 
+    private static CatchNode getCatchNodeFromBlock(final Block catchBlock) {
+        return (CatchNode)catchBlock.getStatements().get(0);
+    }
+
     /**
      * Get the catch blocks for this try block
      * @return a list of blocks
@@ -176,7 +177,7 @@
         if (this.catchBlocks == catchBlocks) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
     }
 
     /**
@@ -186,7 +187,6 @@
     public Symbol getException() {
         return exception;
     }
-
     /**
      * Set the exception symbol for this try block
      * @param exception a symbol for the compiler to store the exception in
@@ -219,14 +219,6 @@
     }
 
     /**
-     * Get the exit label for this try block
-     * @return exit label
-     */
-    public Label getExit() {
-        return exit;
-    }
-
-    /**
      * Get the body of the finally clause for this try
      * @return finally body, or null if no finally
      */
@@ -243,6 +235,19 @@
         if (this.finallyBody == finallyBody) {
             return this;
         }
-        return new TryNode(this, body, catchBlocks, finallyBody);
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+    }
+
+    @Override
+    public JoinPredecessor setLocalVariableConversion(final LexicalContext lc, final LocalVariableConversion conversion) {
+        if(this.conversion == conversion) {
+            return this;
+        }
+        return new TryNode(this, body, catchBlocks, finallyBody, conversion);
+    }
+
+    @Override
+    public LocalVariableConversion getLocalVariableConversion() {
+        return conversion;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java b/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java
index 4923d31..aeac234 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/UnaryNode.java
@@ -28,8 +28,14 @@
 import static jdk.nashorn.internal.parser.TokenType.BIT_NOT;
 import static jdk.nashorn.internal.parser.TokenType.DECPOSTFIX;
 import static jdk.nashorn.internal.parser.TokenType.INCPOSTFIX;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Function;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Immutable;
 import jdk.nashorn.internal.ir.visitor.NodeVisitor;
 import jdk.nashorn.internal.parser.Token;
@@ -39,9 +45,25 @@
  * UnaryNode nodes represent single operand operations.
  */
 @Immutable
-public final class UnaryNode extends Expression implements Assignment<Expression> {
+public final class UnaryNode extends Expression implements Assignment<Expression>, Optimistic {
     /** Right hand side argument. */
-    private final Expression rhs;
+    private final Expression expression;
+
+    private final int programPoint;
+
+    private final Type type;
+
+    @Ignore
+    private static final List<TokenType> CAN_OVERFLOW =
+            Collections.unmodifiableList(
+                Arrays.asList(new TokenType[] {
+                    TokenType.ADD,
+                    TokenType.SUB, //negate
+                    TokenType.DECPREFIX,
+                    TokenType.DECPOSTFIX,
+                    TokenType.INCPREFIX,
+                    TokenType.INCPOSTFIX,
+                }));
 
     /**
      * Constructor
@@ -56,20 +78,24 @@
     /**
      * Constructor
      *
-     * @param token  token
-     * @param start  start
-     * @param finish finish
-     * @param rhs    expression
+     * @param token      token
+     * @param start      start
+     * @param finish     finish
+     * @param expression expression
      */
-    public UnaryNode(final long token, final int start, final int finish, final Expression rhs) {
+    public UnaryNode(final long token, final int start, final int finish, final Expression expression) {
         super(token, start, finish);
-        this.rhs = rhs;
+        this.expression   = expression;
+        this.programPoint = INVALID_PROGRAM_POINT;
+        this.type = null;
     }
 
 
-    private UnaryNode(final UnaryNode unaryNode, final Expression rhs) {
+    private UnaryNode(final UnaryNode unaryNode, final Expression expression, final Type type, final int programPoint) {
         super(unaryNode);
-        this.rhs = rhs;
+        this.expression   = expression;
+        this.programPoint = programPoint;
+        this.type = type;
     }
 
     /**
@@ -95,19 +121,53 @@
         return isAssignment();
     }
 
+    private static final Function<Symbol, Type> UNKNOWN_LOCALS = new Function<Symbol, Type>() {
+        @Override
+        public Type apply(final Symbol t) {
+            return null;
+        }
+    };
+
+
     @Override
     public Type getWidestOperationType() {
-        return isAssignment() ? Type.NUMBER : Type.OBJECT;
+        return getWidestOperationType(UNKNOWN_LOCALS);
+    }
+
+    private Type getWidestOperationType(final Function<Symbol, Type> localVariableTypes) {
+        switch (tokenType()) {
+        case ADD:
+            final Type operandType = getExpression().getType(localVariableTypes);
+            if(operandType == Type.BOOLEAN) {
+                return Type.INT;
+            } else if(operandType.isObject()) {
+                return Type.NUMBER;
+            }
+            assert operandType.isNumeric();
+            return operandType;
+        case SUB:
+            // This might seems overly conservative until you consider that -0 can only be represented as a double.
+            return Type.NUMBER;
+        case NOT:
+        case DELETE:
+            return Type.BOOLEAN;
+        case BIT_NOT:
+            return Type.INT;
+        case VOID:
+            return Type.UNDEFINED;
+        default:
+            return isAssignment() ? Type.NUMBER : Type.OBJECT;
+        }
     }
 
     @Override
     public Expression getAssignmentDest() {
-        return isAssignment() ? rhs() : null;
+        return isAssignment() ? getExpression() : null;
     }
 
     @Override
-    public UnaryNode setAssignmentDest(Expression n) {
-        return setRHS(n);
+    public UnaryNode setAssignmentDest(final Expression n) {
+        return setExpression(n);
     }
 
     @Override
@@ -122,7 +182,7 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterUnaryNode(this)) {
-            return visitor.leaveUnaryNode(setRHS((Expression)rhs.accept(visitor)));
+            return visitor.leaveUnaryNode(setExpression((Expression)expression.accept(visitor)));
         }
 
         return this;
@@ -131,31 +191,33 @@
     @Override
     public boolean isLocal() {
         switch (tokenType()) {
-            case NEW:
-                return false;
-            case ADD:
-            case SUB:
-            case NOT:
-            case BIT_NOT:
-                return rhs.isLocal() && rhs.getType().isJSPrimitive();
-            case DECPOSTFIX:
-            case DECPREFIX:
-            case INCPOSTFIX:
-            case INCPREFIX:
-                return rhs instanceof IdentNode && rhs.isLocal() && rhs.getType().isJSPrimitive();
-            default:
-                return rhs.isLocal();
+        case NEW:
+            return false;
+        case ADD:
+        case SUB:
+        case NOT:
+        case BIT_NOT:
+            return expression.isLocal() && expression.getType().isJSPrimitive();
+        case DECPOSTFIX:
+        case DECPREFIX:
+        case INCPOSTFIX:
+        case INCPREFIX:
+            return expression instanceof IdentNode && expression.isLocal() && expression.getType().isJSPrimitive();
+        default:
+            return expression.isLocal();
         }
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
-        toString(sb, new Runnable() {
-            @Override
-            public void run() {
-                sb.append(rhs().toString());
-            }
-        });
+    public void toString(final StringBuilder sb, final boolean printType) {
+        toString(sb,
+                new Runnable() {
+                    @Override
+                    public void run() {
+                        getExpression().toString(sb, printType);
+                    }
+                },
+                printType);
     }
 
     /**
@@ -163,23 +225,27 @@
      * operand to a specified runnable.
      * @param sb the string builder to use
      * @param rhsStringBuilder the runnable that appends the string representation of the operand to the string builder
+     * @param printType should we print type
      * when invoked.
      */
-    public void toString(final StringBuilder sb, final Runnable rhsStringBuilder) {
-        final TokenType type      = tokenType();
-        final String    name      = type.getName();
-        final boolean   isPostfix = type == DECPOSTFIX || type == INCPOSTFIX;
+    public void toString(final StringBuilder sb, final Runnable rhsStringBuilder, final boolean printType) {
+        final TokenType tokenType = tokenType();
+        final String    name      = tokenType.getName();
+        final boolean   isPostfix = tokenType == DECPOSTFIX || tokenType == INCPOSTFIX;
 
-        boolean rhsParen   = type.needsParens(rhs().tokenType(), false);
+        if (isOptimistic()) {
+            sb.append(Expression.OPT_IDENTIFIER);
+        }
+        boolean rhsParen = tokenType.needsParens(getExpression().tokenType(), false);
 
         if (!isPostfix) {
             if (name == null) {
-                sb.append(type.name());
+                sb.append(tokenType.name());
                 rhsParen = true;
             } else {
                 sb.append(name);
 
-                if (type.ordinal() > BIT_NOT.ordinal()) {
+                if (tokenType.ordinal() > BIT_NOT.ordinal()) {
                     sb.append(' ');
                 }
             }
@@ -194,7 +260,7 @@
         }
 
         if (isPostfix) {
-            sb.append(type == DECPOSTFIX ? "--" : "++");
+            sb.append(tokenType == DECPOSTFIX ? "--" : "++");
         }
     }
 
@@ -206,8 +272,8 @@
      *
      * @return right hand side or expression node
      */
-    public Expression rhs() {
-        return rhs;
+    public Expression getExpression() {
+        return expression;
     }
 
     /**
@@ -216,13 +282,62 @@
      *
      * @see BinaryNode
      *
-     * @param rhs right hand side or expression node
+     * @param expression right hand side or expression node
      * @return a node equivalent to this one except for the requested change.
      */
-    public UnaryNode setRHS(final Expression rhs) {
-        if (this.rhs == rhs) {
+    public UnaryNode setExpression(final Expression expression) {
+        if (this.expression == expression) {
             return this;
         }
-        return new UnaryNode(this, rhs);
+        return new UnaryNode(this, expression, type, programPoint);
     }
+
+    @Override
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    @Override
+    public UnaryNode setProgramPoint(final int programPoint) {
+        if (this.programPoint == programPoint) {
+            return this;
+        }
+        return new UnaryNode(this, expression, type, programPoint);
+    }
+
+    @Override
+    public boolean canBeOptimistic() {
+        return getMostOptimisticType() != getMostPessimisticType();
+    }
+
+    @Override
+    public Type getMostOptimisticType() {
+        if (CAN_OVERFLOW.contains(tokenType())) {
+            return Type.INT;
+        }
+        return getMostPessimisticType();
+    }
+
+    @Override
+    public Type getMostPessimisticType() {
+        return getWidestOperationType();
+    }
+
+    @Override
+    public Type getType(final Function<Symbol, Type> localVariableTypes) {
+        final Type widest = getWidestOperationType(localVariableTypes);
+        if(type == null) {
+            return widest;
+        }
+        return Type.narrowest(widest, Type.widest(type, expression.getType(localVariableTypes)));
+    }
+
+    @Override
+    public UnaryNode setType(final Type type) {
+        if (this.type == type) {
+            return this;
+        }
+        return new UnaryNode(this, expression, type, programPoint);
+    }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/ir/VarNode.java b/nashorn/src/jdk/nashorn/internal/ir/VarNode.java
index 67648a0..02f7a52 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/VarNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/VarNode.java
@@ -99,7 +99,7 @@
     }
 
     @Override
-    public VarNode setAssignmentDest(IdentNode n) {
+    public VarNode setAssignmentDest(final IdentNode n) {
         return setName(n);
     }
 
@@ -123,8 +123,9 @@
     @Override
     public Node accept(final NodeVisitor<? extends LexicalContext> visitor) {
         if (visitor.enterVarNode(this)) {
-            final IdentNode  newName = (IdentNode)name.accept(visitor);
+            // var is right associative, so visit init before name
             final Expression newInit = init == null ? null : (Expression)init.accept(visitor);
+            final IdentNode  newName = (IdentNode)name.accept(visitor);
             final VarNode    newThis;
             if (name != newName || init != newInit) {
                 newThis = new VarNode(this, newName, newInit, flags);
@@ -137,13 +138,13 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("var ");
-        name.toString(sb);
+        name.toString(sb, printType);
 
         if (init != null) {
             sb.append(" = ");
-            init.toString(sb);
+            init.toString(sb, printType);
         }
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java
index 97e7ca5..0cced56 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java
@@ -47,7 +47,7 @@
      * @param isDoWhile  is this a do while loop?
      */
     public WhileNode(final int lineNumber, final long token, final int finish, final boolean isDoWhile) {
-        super(lineNumber, token, finish, null, null, false);
+        super(lineNumber, token, finish, null, false);
         this.isDoWhile = isDoWhile;
     }
 
@@ -58,15 +58,16 @@
      * @param test      test
      * @param body      body
      * @param controlFlowEscapes control flow escapes?
+     * @param conversion TODO
      */
-    protected WhileNode(final WhileNode whileNode, final Expression test, final Block body, final boolean controlFlowEscapes) {
-        super(whileNode, test, body, controlFlowEscapes);
+    private WhileNode(final WhileNode whileNode, final JoinPredecessorExpression test, final Block body, final boolean controlFlowEscapes, final LocalVariableConversion conversion) {
+        super(whileNode, test, body, controlFlowEscapes, conversion);
         this.isDoWhile = whileNode.isDoWhile;
     }
 
     @Override
     public Node ensureUniqueLabels(final LexicalContext lc) {
-        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -80,26 +81,21 @@
             if (isDoWhile()) {
                 return visitor.leaveWhileNode(
                         setBody(lc, (Block)body.accept(visitor)).
-                        setTest(lc, (Expression)test.accept(visitor)));
+                        setTest(lc, (JoinPredecessorExpression)test.accept(visitor)));
             }
             return visitor.leaveWhileNode(
-                    setTest(lc, (Expression)test.accept(visitor)).
+                    setTest(lc, (JoinPredecessorExpression)test.accept(visitor)).
                     setBody(lc, (Block)body.accept(visitor)));
         }
         return this;
     }
 
     @Override
-    public Expression getTest() {
-        return test;
-    }
-
-    @Override
-    public WhileNode setTest(final LexicalContext lc, final Expression test) {
+    public WhileNode setTest(final LexicalContext lc, final JoinPredecessorExpression test) {
         if (this.test == test) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -112,7 +108,7 @@
         if (this.body == body) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
     }
 
     @Override
@@ -120,7 +116,12 @@
         if (this.controlFlowEscapes == controlFlowEscapes) {
             return this;
         }
-        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes));
+        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
+    }
+
+    @Override
+    JoinPredecessor setLocalVariableConversionChanged(final LexicalContext lc, final LocalVariableConversion conversion) {
+        return Node.replaceInLexicalContext(lc, this, new WhileNode(this, test, body, controlFlowEscapes, conversion));
     }
 
     /**
@@ -132,9 +133,9 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("while (");
-        test.toString(sb);
+        test.toString(sb, printType);
         sb.append(')');
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/WithNode.java b/nashorn/src/jdk/nashorn/internal/ir/WithNode.java
index 69bd22d..0ea52c9 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/WithNode.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/WithNode.java
@@ -79,9 +79,9 @@
     }
 
     @Override
-    public void toString(final StringBuilder sb) {
+    public void toString(final StringBuilder sb, final boolean printType) {
         sb.append("with (");
-        expression.toString(sb);
+        expression.toString(sb, printType);
         sb.append(')');
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java b/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
index 19e4d04..52e3c0e 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/ASTWriter.java
@@ -36,8 +36,11 @@
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.Expression;
+import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.Node;
+import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.Symbol;
+import jdk.nashorn.internal.ir.Terminal;
 import jdk.nashorn.internal.ir.TernaryNode;
 import jdk.nashorn.internal.ir.annotations.Ignore;
 import jdk.nashorn.internal.ir.annotations.Reference;
@@ -104,23 +107,31 @@
 
         final boolean isReference = field != null && field.isAnnotationPresent(Reference.class);
 
-        Class<?> clazz = node.getClass();
+        final Class<?> clazz = node.getClass();
         String   type  = clazz.getName();
 
         type = type.substring(type.lastIndexOf('.') + 1, type.length());
+        int truncate = type.indexOf("Node");
+        if (truncate == -1) {
+            truncate = type.indexOf("Statement");
+        }
+        if (truncate != -1) {
+            type = type.substring(0, truncate);
+        }
+        type = type.toLowerCase();
+
         if (isReference) {
             type = "ref: " + type;
         }
-        type += "@" + Debug.id(node);
         final Symbol symbol;
-        if(node instanceof Expression) {
-            symbol = ((Expression)node).getSymbol();
+        if (node instanceof IdentNode) {
+            symbol = ((IdentNode)node).getSymbol();
         } else {
             symbol = null;
         }
 
         if (symbol != null) {
-            type += "#" + symbol;
+            type += ">" + symbol;
         }
 
         if (node instanceof Block && ((Block)node).needsScope()) {
@@ -135,11 +146,11 @@
 
         String status = "";
 
-        if (node.isTerminal()) {
+        if (node instanceof Terminal && ((Terminal)node).isTerminal()) {
             status += " Terminal";
         }
 
-        if (node.hasGoto()) {
+        if (node instanceof Statement && ((Statement)node).hasGoto()) {
             status += " Goto ";
         }
 
@@ -160,6 +171,8 @@
             status += " (" + tname + ")";
         }
 
+        status += " @" + Debug.id(node);
+
         if (children.isEmpty()) {
             sb.append("[").
                 append(type).
@@ -200,7 +213,7 @@
                 } else if (value instanceof Collection) {
                     int pos = 0;
                     ASTWriter.indent(sb, indent + 1);
-                    sb.append("[Collection ").
+                    sb.append('[').
                         append(child.getName()).
                         append("[0..").
                         append(((Collection<Node>)value).size()).
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java b/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
index c65f8ef..d5c8174 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/ClassHistogramElement.java
@@ -30,7 +30,7 @@
 /**
  * Class histogram element for IR / Java object instrumentation
  */
-public class ClassHistogramElement {
+public final class ClassHistogramElement {
     /**
      * Instance comparator
      */
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
index ef7f8a1..e3916d6 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java
@@ -27,10 +27,9 @@
 
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-import java.util.ArrayList;
-import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.ir.AccessNode;
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
@@ -41,12 +40,14 @@
 import jdk.nashorn.internal.ir.CatchNode;
 import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.EmptyNode;
+import jdk.nashorn.internal.ir.Expression;
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
@@ -72,7 +73,6 @@
 import jdk.nashorn.internal.parser.TokenType;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ParserException;
-import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.Source;
 
 /**
@@ -83,17 +83,17 @@
     /**
      * Returns AST as JSON compatible string.
      *
-     * @param env  script environment to use
+     * @param context context
      * @param code code to be parsed
      * @param name name of the code source (used for location)
      * @param includeLoc tells whether to include location information for nodes or not
      * @return JSON string representation of AST of the supplied code
      */
-    public static String parse(final ScriptEnvironment env, final String code, final String name, final boolean includeLoc) {
-        final Parser       parser     = new Parser(env, sourceFor(name, code), new Context.ThrowErrorManager(), env._strict);
+    public static String parse(final Context context, final String code, final String name, final boolean includeLoc) {
+        final Parser       parser     = new Parser(context.getEnv(), sourceFor(name, code), new Context.ThrowErrorManager(), context.getEnv()._strict, context.getLogger(Parser.class));
         final JSONWriter   jsonWriter = new JSONWriter(includeLoc);
         try {
-            final FunctionNode functionNode = parser.parse(CompilerConstants.RUN_SCRIPT.symbolName());
+            final FunctionNode functionNode = parser.parse(); //symbol name is ":program", default
             functionNode.accept(jsonWriter);
             return jsonWriter.getString();
         } catch (final ParserException e) {
@@ -103,6 +103,17 @@
     }
 
     @Override
+    public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression joinPredecessorExpression) {
+        final Expression expr = joinPredecessorExpression.getExpression();
+        if(expr != null) {
+            expr.accept(this);
+        } else {
+            nullValue();
+        }
+        return false;
+    }
+
+    @Override
     protected boolean enterDefault(final Node node) {
         objectStart();
         location(node);
@@ -132,8 +143,7 @@
         accessNode.getBase().accept(this);
         comma();
 
-        property("property");
-        accessNode.getProperty().accept(this);
+        property("property", accessNode.getProperty());
         comma();
 
         property("computed", false);
@@ -153,16 +163,6 @@
         return leave();
     }
 
-    private static boolean isLogical(final TokenType tt) {
-        switch (tt) {
-        case AND:
-        case OR:
-            return true;
-        default:
-            return false;
-        }
-    }
-
     @Override
     public boolean enterBinaryNode(final BinaryNode binaryNode) {
         enterDefault(binaryNode);
@@ -170,7 +170,7 @@
         final String name;
         if (binaryNode.isAssignment()) {
             name = "AssignmentExpression";
-        } else if (isLogical(binaryNode.tokenType())) {
+        } else if (binaryNode.isLogical()) {
             name = "LogicalExpression";
         } else {
             name = "BinaryExpression";
@@ -199,11 +199,11 @@
         type("BreakStatement");
         comma();
 
-        final IdentNode label = breakNode.getLabel();
-        property("label");
-        if (label != null) {
-            label.accept(this);
+        final String label = breakNode.getLabelName();
+        if(label != null) {
+            property("label", label);
         } else {
+            property("label");
             nullValue();
         }
 
@@ -278,11 +278,11 @@
         type("ContinueStatement");
         comma();
 
-        final IdentNode label = continueNode.getLabel();
-        property("label");
-        if (label != null) {
-            label.accept(this);
+        final String label = continueNode.getLabelName();
+        if(label != null) {
+            property("label", label);
         } else {
+            property("label");
             nullValue();
         }
 
@@ -319,7 +319,7 @@
     }
 
     @Override
-    public boolean enterBlockStatement(BlockStatement blockStatement) {
+    public boolean enterBlockStatement(final BlockStatement blockStatement) {
         enterDefault(blockStatement);
 
         type("BlockStatement");
@@ -339,13 +339,13 @@
             type("ForInStatement");
             comma();
 
-            Node init = forNode.getInit();
+            final Node init = forNode.getInit();
             assert init != null;
             property("left");
             init.accept(this);
             comma();
 
-            Node modify = forNode.getModify();
+            final Node modify = forNode.getModify();
             assert modify != null;
             property("right");
             modify.accept(this);
@@ -535,8 +535,7 @@
         type("LabeledStatement");
         comma();
 
-        property("label");
-        labelNode.getLabel().accept(this);
+        property("label", labelNode.getLabelName());
         comma();
 
         property("body");
@@ -762,8 +761,8 @@
         final List<CatchNode> guarded = new ArrayList<>();
         CatchNode unguarded = null;
         if (catches != null) {
-            for (Node n : catches) {
-                CatchNode cn = (CatchNode)n;
+            for (final Node n : catches) {
+                final CatchNode cn = (CatchNode)n;
                 if (cn.getExceptionCondition() != null) {
                     guarded.add(cn);
                 } else {
@@ -804,7 +803,7 @@
             type("NewExpression");
             comma();
 
-            final CallNode callNode = (CallNode)unaryNode.rhs();
+            final CallNode callNode = (CallNode)unaryNode.getExpression();
             property("callee");
             callNode.getFunction().accept(this);
             comma();
@@ -846,7 +845,7 @@
             comma();
 
             property("argument");
-            unaryNode.rhs().accept(this);
+            unaryNode.getExpression().accept(this);
         }
 
         return leave();
@@ -959,9 +958,13 @@
         buf.append(key);
         buf.append("\":");
         if (value != null) {
-            if (escape) buf.append('"');
+            if (escape) {
+                buf.append('"');
+            }
             buf.append(value);
-            if (escape) buf.append('"');
+            if (escape) {
+                buf.append('"');
+            }
         }
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java b/nashorn/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
new file mode 100644
index 0000000..87eb18d
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/NashornClassReader.java
@@ -0,0 +1,551 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir.debug;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.ClassReader;
+import jdk.internal.org.objectweb.asm.ClassVisitor;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.nashorn.internal.ir.debug.NashornTextifier.NashornLabel;
+
+/**
+ * Subclass of the ASM classs reader that retains more info, such
+ * as bytecode offsets
+ */
+public class NashornClassReader extends ClassReader {
+
+    private final Map<String, List<Label>> labelMap = new HashMap<>();
+
+    /**
+     * Constructor
+     * @param bytecode bytecode for class
+     */
+    public NashornClassReader(final byte[] bytecode) {
+        super(bytecode);
+        parse(bytecode);
+    }
+
+    List<Label> getExtraLabels(final String className, final String methodName, final String methodDesc) {
+        final String key = fullyQualifiedName(className, methodName, methodDesc);
+        return labelMap.get(key);
+    }
+
+    private static int readByte(final byte[] bytecode, final int index) {
+        return (byte)(bytecode[index] & 0xff);
+    }
+
+    private static int readShort(final byte[] bytecode, final int index) {
+        return (short)((bytecode[index] & 0xff) << 8) | (bytecode[index + 1] & 0xff);
+    }
+
+    private static int readInt(final byte[] bytecode, final int index) {
+        return ((bytecode[index] & 0xff) << 24) | ((bytecode[index + 1] & 0xff) << 16) | ((bytecode[index + 2] & 0xff) << 8) | (bytecode[index + 3] & 0xff);
+    }
+
+    private static long readLong(final byte[] bytecode, final int index) {
+        final int hi = readInt(bytecode, index);
+        final int lo = readInt(bytecode, index + 4);
+        return ((long)hi << 32) | lo;
+    }
+
+    private static String readUTF(final int index, final int utfLen, final byte[] bytecode) {
+        final int endIndex = index + utfLen;
+        final char buf[] = new char[utfLen * 2];
+        int strLen = 0;
+        int c;
+        int st = 0;
+        char cc = 0;
+        int i = index;
+
+        while (i < endIndex) {
+            c = bytecode[i++];
+            switch (st) {
+            case 0:
+                c = c & 0xFF;
+                if (c < 0x80) { // 0xxxxxxx
+                    buf[strLen++] = (char) c;
+                } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx
+                    cc = (char) (c & 0x1F);
+                    st = 1;
+                } else { // 1110 xxxx 10xx xxxx 10xx xxxx
+                    cc = (char) (c & 0x0F);
+                    st = 2;
+                }
+                break;
+
+            case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char
+                buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));
+                st = 0;
+                break;
+
+            case 2: // byte 2 of 3-byte char
+                cc = (char) ((cc << 6) | (c & 0x3F));
+                st = 1;
+                break;
+
+            default:
+                break;
+            }
+        }
+        return new String(buf, 0, strLen);
+    }
+
+    private String parse(final byte[] bytecode) {
+        String thisClassName;
+
+        int u = 0;
+
+        final int magic = readInt(bytecode, u);
+        u += 4; //magic
+        assert magic == 0xcafebabe : Integer.toHexString(magic);
+        readShort(bytecode, u); //minor
+        u += 2;
+        readShort(bytecode, u); //major
+        u += 2; //minor
+
+        final int cpc = readShort(bytecode, u);
+        u += 2;
+        final ArrayList<Constant> cp = new ArrayList<>(cpc);
+        cp.add(null);
+
+        for (int i = 1; i < cpc; i++) {
+            //constant pool entries
+            final int tag = readByte(bytecode, u);
+            u += 1;
+            switch (tag) {
+            case 7: //class
+                cp.add(new IndexInfo(cp, tag, readShort(bytecode, u)));
+                u += 2;
+                break;
+            case 9:  //fieldref
+            case 10: //methodref
+            case 11: //interfacemethodref
+                cp.add(new IndexInfo2(cp, tag, readShort(bytecode, u), readShort(bytecode, u + 2)));
+                u += 4;
+               break;
+            case 8: //string
+                cp.add(new IndexInfo(cp, tag, readShort(bytecode, u))); //string index
+                u += 2;
+                break;
+            case 3:  //int
+                cp.add(new DirectInfo<>(cp, tag, readInt(bytecode, u)));
+                u += 4;
+                break;
+            case 4:  //float
+                cp.add(new DirectInfo<>(cp, tag, Float.intBitsToFloat(readInt(bytecode, u))));
+                u += 4;
+                break;
+            case 5:  //long
+                cp.add(new DirectInfo<>(cp, tag, readLong(bytecode, u)));
+                cp.add(null);
+                i++;
+                u += 8;
+                break;
+            case 6:  //double
+                cp.add(new DirectInfo<>(cp, tag, Double.longBitsToDouble(readLong(bytecode, u))));
+                cp.add(null);
+                i++;
+                u += 8;
+                break;
+            case 12: //name and type
+                cp.add(new IndexInfo2(cp, tag, readShort(bytecode, u), readShort(bytecode, u + 2)));
+                u += 4;
+                break;
+            case 1:  //utf8
+                final int len = readShort(bytecode, u);
+                u += 2;
+                cp.add(new DirectInfo<>(cp, tag, readUTF(u, len, bytecode)));
+                u += len;
+                break;
+            case 16: //methodtype
+                cp.add(new IndexInfo(cp, tag, readShort(bytecode, u)));
+                u += 2;
+                break;
+            case 18: //indy
+                cp.add(new IndexInfo2(cp, tag, readShort(bytecode, u), readShort(bytecode, u + 2)) {
+                    @Override
+                    public String toString() {
+                        return "#" + index + ' ' + cp.get(index2).toString();
+                    }
+
+                });
+                u += 4;
+                break;
+            case 15: //methodhandle
+                final int kind = readByte(bytecode, u);
+                assert kind >= 1 && kind <= 9 : kind;
+                cp.add(new IndexInfo2(cp, tag, kind, readShort(bytecode, u + 1)) {
+                    @Override
+                    public String toString() {
+                        return "#" + index + ' ' + cp.get(index2).toString();
+                    }
+                });
+
+                u += 3;
+                break;
+            default:
+                assert false : tag;
+                break;
+            }
+        }
+
+        readShort(bytecode, u); //access flags
+        u += 2; //access
+        final int cls = readShort(bytecode, u);
+        u += 2; //this_class
+        thisClassName = cp.get(cls).toString();
+        u += 2; //super
+
+        final int ifc = readShort(bytecode, u);
+        u += 2;
+        u += ifc * 2;
+
+        final int fc = readShort(bytecode, u);
+        u += 2; //fields
+
+        for (int i = 0 ; i < fc ; i++) {
+            u += 2; //access
+            readShort(bytecode, u); //fieldname
+            u += 2; //name
+            u += 2; //descriptor
+            final int ac = readShort(bytecode, u);
+            u += 2;
+            //field attributes
+            for (int j = 0; j < ac; j++) {
+                u += 2; //attribute name
+                final int len = readInt(bytecode, u);
+                u += 4;
+                u += len;
+            }
+        }
+
+        final int mc = readShort(bytecode, u);
+        u += 2;
+        for (int i = 0 ; i < mc ; i++) {
+            readShort(bytecode, u);
+            u += 2; //access
+
+            final int methodNameIndex = readShort(bytecode, u);
+            u += 2;
+            final String methodName = cp.get(methodNameIndex).toString();
+
+            final int methodDescIndex = readShort(bytecode, u);
+            u += 2;
+            final String methodDesc = cp.get(methodDescIndex).toString();
+
+            final int ac = readShort(bytecode, u);
+            u += 2;
+
+            //method attributes
+            for (int j = 0; j < ac; j++) {
+                final int nameIndex = readShort(bytecode, u);
+                u += 2;
+                final String attrName = cp.get(nameIndex).toString();
+
+                final int attrLen = readInt(bytecode, u);
+                u += 4;
+
+                if ("Code".equals(attrName)) {
+                    readShort(bytecode, u);
+                    u += 2; //max stack
+                    readShort(bytecode, u);
+                    u += 2; //max locals
+                    final int len = readInt(bytecode, u);
+                    u += 4;
+                    parseCode(bytecode, u, len, fullyQualifiedName(thisClassName, methodName, methodDesc));
+                    u += len;
+                    final int elen = readShort(bytecode, u); //exception table length
+                    u += 2;
+                    u += elen * 8;
+
+                    //method attributes
+                    final int ac2 = readShort(bytecode, u);
+                    u += 2;
+                    for (int k = 0; k < ac2; k++) {
+                        u += 2; //name;
+                        final int aclen = readInt(bytecode, u);
+                        u += 4; //length
+                        u += aclen; //bytes;
+                    }
+                } else {
+                    u += attrLen;
+                }
+            }
+        }
+
+        final int ac = readShort(bytecode, u);
+        u += 2;
+        //other attributes
+        for (int i = 0 ; i < ac ; i++) {
+            readShort(bytecode, u); //name index
+            u += 2;
+            final int len = readInt(bytecode, u);
+            u += 4;
+            u += len;
+            //attribute
+        }
+
+        return thisClassName;
+    }
+
+    private static String fullyQualifiedName(final String className, final String methodName, final String methodDesc) {
+        return className + '.' + methodName + methodDesc;
+    }
+
+    private void parseCode(final byte[] bytecode, final int index, final int len, final String desc) {
+        final List<Label> labels = new ArrayList<>();
+        labelMap.put(desc, labels);
+
+        boolean wide = false;
+
+        for (int i = index; i < index + len;) {
+            final int opcode = bytecode[i];
+            labels.add(new NashornLabel(opcode, i - index));
+
+            switch (opcode & 0xff) {
+            case 0xc4: //wide
+                wide = true;
+                i += 1;
+                break;
+            case 0xa9: //ret
+                i += wide ? 4 : 2;
+                break;
+            case 0xab: //lookupswitch
+                i += 1;
+                while (((i - index) & 3) != 0) {
+                    i++;
+                }
+                readInt(bytecode, i);
+                i += 4; //defaultbyte
+                final int npairs = readInt(bytecode, i);
+                i += 4;
+                i += 8 * npairs;
+                break;
+            case 0xaa: //tableswitch
+                i += 1;
+                while (((i - index) & 3) != 0) {
+                    i++;
+                }
+                readInt(bytecode, i); //default
+                i += 4;
+                final int lo = readInt(bytecode, i);
+                i += 4;
+                final int hi = readInt(bytecode, i);
+                i += 4;
+                i += 4 * (hi - lo + 1);
+                break;
+            case 0xc5: //multianewarray
+                i += 4;
+                break;
+            case 0x19: //aload (wide)
+            case 0x18: //dload
+            case 0x17: //fload
+            case 0x15: //iload
+            case 0x16: //lload
+            case 0x3a: //astore wide
+            case 0x39: //dstore
+            case 0x38: //fstore
+            case 0x36: //istore
+            case 0x37: //lstore
+                i += wide ? 3 : 2;
+                break;
+            case 0x10: //bipush
+            case 0x12: //ldc
+            case 0xbc: //anewarrayu
+                i += 2;
+                break;
+            case 0xb4: //getfield
+            case 0xb2: //getstatic
+            case 0xbd: //anewarray
+            case 0xc0: //checkcast
+            case 0xa5: //ifacmp_eq
+            case 0xa6: //ifacmp_ne
+            case 0x9f: //all ifs and ifcmps
+            case 0xa0:
+            case 0xa1:
+            case 0xa2:
+            case 0xa3:
+            case 0xa4:
+            case 0x99:
+            case 0x9a:
+            case 0x9b:
+            case 0x9c:
+            case 0x9d:
+            case 0x9e:
+            case 0xc7:
+            case 0xc6:
+            case 0xc1: //instanceof
+            case 0xa7: //goto
+            case 0xb7: //special
+            case 0xb8: //static
+            case 0xb6: //virtual
+            case 0xa8: //jsr
+            case 0x13: //ldc_w
+            case 0x14: //ldc2_w
+            case 0xbb: //new
+            case 0xb5: //putfield
+            case 0xb3: //putstatic
+            case 0x11: //sipush
+                i += 3;
+                break;
+            case 0x84: //iinc (wide)
+                i += wide ? 5 : 3;
+                break;
+            case 0xba: //indy
+            case 0xb9: //interface
+            case 0xc8:
+            case 0xc9:  //jsr_w
+                i += 5; //goto_w
+                break;
+            default:
+                i++;
+                break;
+            }
+
+            if (wide) {
+                wide = false;
+            }
+        }
+    }
+
+    @Override
+    public void accept(final ClassVisitor classVisitor, final Attribute[] attrs, final int flags) {
+        super.accept(classVisitor, attrs, flags);
+    }
+
+    @Override
+    protected Label readLabel(final int offset, final Label[] labels) {
+        final Label label = super.readLabel(offset, labels);
+        label.info = offset;
+        return label;
+    }
+
+    private abstract static class Constant {
+        protected ArrayList<Constant> cp;
+        protected int tag;
+        protected Constant(final ArrayList<Constant> cp, final int tag) {
+            this.cp = cp;
+            this.tag = tag;
+        }
+
+        @SuppressWarnings("unused")
+        final String getType() {
+            String str = type[tag];
+            while (str.length() < 16) {
+                str += " ";
+            }
+            return str;
+        }
+    }
+
+    private static class IndexInfo extends Constant {
+        protected final int index;
+
+        IndexInfo(final ArrayList<Constant> cp, final int tag, final int index) {
+            super(cp, tag);
+            this.index = index;
+        }
+
+        @Override
+        public String toString() {
+            return cp.get(index).toString();
+        }
+    }
+
+    private static class IndexInfo2 extends IndexInfo {
+        protected final int index2;
+
+        IndexInfo2(final ArrayList<Constant> cp, final int tag, final int index, final int index2) {
+            super(cp, tag, index);
+            this.index2 = index2;
+        }
+
+        @Override
+        public String toString() {
+            return super.toString() + ' ' + cp.get(index2).toString();
+        }
+    }
+
+    private static class DirectInfo<T> extends Constant {
+        protected final T info;
+
+        DirectInfo(final ArrayList<Constant> cp, final int tag, final T info) {
+            super(cp, tag);
+            this.info = info;
+        }
+
+        @Override
+        public String toString() {
+            return info.toString();// + " [class=" + info.getClass().getSimpleName() + ']';
+        }
+    }
+
+    private static String type[] = {
+        //0
+        "<error>",
+        //1
+        "UTF8",
+        //2
+        "<error>",
+        //3
+        "Integer",
+        //4
+        "Float",
+        //5
+        "Long",
+        //6
+        "Double",
+        //7
+        "Class",
+        //8
+        "String",
+        //9
+        "Fieldref",
+        //10
+        "Methodref",
+        //11
+        "InterfaceMethodRef",
+        //12
+        "NameAndType",
+        //13
+        "<error>",
+        //14
+        "<error>",
+        //15
+        "MethodHandle",
+        //16
+        "MethodType",
+        //17
+        "<error>",
+        //18
+        "Invokedynamic"
+    };
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java b/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
new file mode 100644
index 0000000..5cdc67d
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/NashornTextifier.java
@@ -0,0 +1,1257 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.ir.debug;
+
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.CALLSITE_PROGRAM_POINT_SHIFT;
+import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.FLAGS_MASK;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.PrintWriter;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import jdk.internal.org.objectweb.asm.Attribute;
+import jdk.internal.org.objectweb.asm.Handle;
+import jdk.internal.org.objectweb.asm.Label;
+import jdk.internal.org.objectweb.asm.Opcodes;
+import jdk.internal.org.objectweb.asm.Type;
+import jdk.internal.org.objectweb.asm.signature.SignatureReader;
+import jdk.internal.org.objectweb.asm.util.Printer;
+import jdk.internal.org.objectweb.asm.util.TraceSignatureVisitor;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+
+/**
+ * Pretty printer for --print-code.
+ * Also supports dot formats if --print-code has arguments
+ */
+public final class NashornTextifier extends Printer {
+
+    private String currentClassName;
+    private Iterator<Label> labelIter;
+    private Graph graph;
+    private String currentBlock;
+
+    // Following variables are used to govern the state of collapsing long sequences of NOP.
+    /** True if the last instruction was a NOP. */
+    private boolean lastWasNop = false;
+    /** True if ellipse ("...") was emitted in place of a second NOP. */
+    private boolean lastWasEllipse = false;
+
+    private static final int INTERNAL_NAME = 0;
+    private static final int FIELD_DESCRIPTOR = 1;
+    private static final int FIELD_SIGNATURE = 2;
+    private static final int METHOD_DESCRIPTOR = 3;
+    private static final int METHOD_SIGNATURE = 4;
+    private static final int CLASS_SIGNATURE = 5;
+
+    private final String tab = "  ";
+    private final String tab2 = "    ";
+    private final String tab3 = "      ";
+
+    private Map<Label, String> labelNames;
+
+    private boolean localVarsStarted = false;
+
+    private NashornClassReader cr;
+    private ScriptEnvironment env;
+
+    /**
+     * Constructs a new {@link NashornTextifier}. <i>Subclasses must not use this
+     * constructor</i>. Instead, they must use the {@link #NashornTextifier(int)}
+     * version.
+     * @param env script environment
+     * @param cr a customized classreader for gathering, among other things, label
+     * information
+     */
+    public NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr) {
+        this(Opcodes.ASM5);
+        this.env = env;
+        this.cr = cr;
+    }
+
+    private NashornTextifier(final ScriptEnvironment env, final NashornClassReader cr, final Iterator<Label> labelIter, final Graph graph) {
+        this(env, cr);
+        this.labelIter = labelIter;
+        this.graph = graph;
+    }
+
+    /**
+     * Constructs a new {@link NashornTextifier}.
+     *
+     * @param api
+     *            the ASM API version implemented by this visitor. Must be one
+     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.
+     */
+    protected NashornTextifier(final int api) {
+        super(api);
+    }
+
+    @Override
+    public void visit(final int version, final int access, final String name, final String signature, final String superName, final String[] interfaces) {
+        final int major = version & 0xFFFF;
+        final int minor = version >>> 16;
+
+        currentClassName = name;
+
+        final StringBuilder sb = new StringBuilder();
+        sb.append("// class version ").
+            append(major).
+            append('.').
+            append(minor).append(" (").
+            append(version).
+            append(")\n");
+
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            sb.append("// DEPRECATED\n");
+        }
+
+        sb.append("// access flags 0x"). //TODO TRANSLATE TO WHAT THEY MEAN
+            append(Integer.toHexString(access).toUpperCase()).
+            append('\n');
+
+        appendDescriptor(sb, CLASS_SIGNATURE, signature);
+        if (signature != null) {
+            final TraceSignatureVisitor sv = new TraceSignatureVisitor(access);
+            final SignatureReader r = new SignatureReader(signature);
+            r.accept(sv);
+            sb.append("// declaration: ").
+                append(name).
+                append(sv.getDeclaration()).
+                append('\n');
+        }
+
+        appendAccess(sb, access & ~Opcodes.ACC_SUPER);
+        if ((access & Opcodes.ACC_ANNOTATION) != 0) {
+            sb.append("@interface ");
+        } else if ((access & Opcodes.ACC_INTERFACE) != 0) {
+            sb.append("interface ");
+        } else if ((access & Opcodes.ACC_ENUM) == 0) {
+            sb.append("class ");
+        }
+        appendDescriptor(sb, INTERNAL_NAME, name);
+
+        if (superName != null && !"java/lang/Object".equals(superName)) {
+            sb.append(" extends ");
+            appendDescriptor(sb, INTERNAL_NAME, superName);
+            sb.append(' ');
+        }
+        if (interfaces != null && interfaces.length > 0) {
+            sb.append(" implements ");
+            for (final String interface1 : interfaces) {
+                appendDescriptor(sb, INTERNAL_NAME, interface1);
+                sb.append(' ');
+            }
+        }
+        sb.append(" {\n");
+
+        addText(sb);
+    }
+
+    @Override
+    public void visitSource(final String file, final String debug) {
+        final StringBuilder sb = new StringBuilder();
+        if (file != null) {
+            sb.append(tab).
+                append("// compiled from: ").
+                append(file).
+                append('\n');
+        }
+        if (debug != null) {
+            sb.append(tab).
+                append("// debug info: ").
+                append(debug).
+                append('\n');
+        }
+        if (sb.length() > 0) {
+            addText(sb);
+        }
+    }
+
+    @Override
+    public void visitOuterClass(final String owner, final String name, final String desc) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(tab).append("outer class ");
+        appendDescriptor(sb, INTERNAL_NAME, owner);
+        sb.append(' ');
+        if (name != null) {
+            sb.append(name).append(' ');
+        }
+        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+        sb.append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public NashornTextifier visitField(final int access, final String name, final String desc, final String signature, final Object value) {
+        final StringBuilder sb = new StringBuilder();
+//        sb.append('\n');
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            sb.append(tab).append("// DEPRECATED\n");
+        }
+
+/*        sb.append(tab).
+            append("// access flags 0x").
+            append(Integer.toHexString(access).toUpperCase()).
+            append('\n');
+*/
+
+        if (signature != null) {
+            sb.append(tab);
+            appendDescriptor(sb, FIELD_SIGNATURE, signature);
+
+            final TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+            final SignatureReader r = new SignatureReader(signature);
+            r.acceptType(sv);
+            sb.append(tab).
+                append("// declaration: ").
+                append(sv.getDeclaration()).
+                append('\n');
+        }
+
+        sb.append(tab);
+        appendAccess(sb, access);
+
+        final String prunedDesc = desc.endsWith(";") ? desc.substring(0, desc.length() - 1) : desc;
+        appendDescriptor(sb, FIELD_DESCRIPTOR, prunedDesc);
+        sb.append(' ').append(name);
+        if (value != null) {
+            sb.append(" = ");
+            if (value instanceof String) {
+                sb.append('\"').append(value).append('\"');
+            } else {
+                sb.append(value);
+            }
+        }
+
+        sb.append(";\n");
+        addText(sb);
+
+        final NashornTextifier t = createNashornTextifier();
+        addText(t.getText());
+
+        return t;
+    }
+
+    @Override
+    public NashornTextifier visitMethod(final int access, final String name, final String desc, final String signature, final String[] exceptions) {
+
+        graph = new Graph(name);
+
+        final List<Label> extraLabels = cr.getExtraLabels(currentClassName, name, desc);
+        this.labelIter = extraLabels == null ? null : extraLabels.iterator();
+
+        final StringBuilder sb = new StringBuilder();
+
+        sb.append('\n');
+        if ((access & Opcodes.ACC_DEPRECATED) != 0) {
+            sb.append(tab).
+                append("// DEPRECATED\n");
+        }
+
+        sb.append(tab).
+            append("// access flags 0x").
+            append(Integer.toHexString(access).toUpperCase()).
+            append('\n');
+
+        if (signature != null) {
+            sb.append(tab);
+            appendDescriptor(sb, METHOD_SIGNATURE, signature);
+
+            final TraceSignatureVisitor v = new TraceSignatureVisitor(0);
+            final SignatureReader r = new SignatureReader(signature);
+            r.accept(v);
+            final String genericDecl = v.getDeclaration();
+            final String genericReturn = v.getReturnType();
+            final String genericExceptions = v.getExceptions();
+
+            sb.append(tab).
+                append("// declaration: ").
+                append(genericReturn).
+                append(' ').
+                append(name).
+                append(genericDecl);
+
+            if (genericExceptions != null) {
+                sb.append(" throws ").append(genericExceptions);
+            }
+            sb.append('\n');
+        }
+
+        sb.append(tab);
+        appendAccess(sb, access);
+        if ((access & Opcodes.ACC_NATIVE) != 0) {
+            sb.append("native ");
+        }
+        if ((access & Opcodes.ACC_VARARGS) != 0) {
+            sb.append("varargs ");
+        }
+        if ((access & Opcodes.ACC_BRIDGE) != 0) {
+            sb.append("bridge ");
+        }
+
+        sb.append(name);
+        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+        if (exceptions != null && exceptions.length > 0) {
+            sb.append(" throws ");
+            for (final String exception : exceptions) {
+                appendDescriptor(sb, INTERNAL_NAME, exception);
+                sb.append(' ');
+            }
+        }
+
+        sb.append('\n');
+        addText(sb);
+
+        final NashornTextifier t = createNashornTextifier();
+        addText(t.getText());
+        return t;
+    }
+
+    @Override
+    public void visitClassEnd() {
+        addText("}\n");
+    }
+
+    @Override
+    public void visitFieldEnd() {
+        //empty
+    }
+
+    @Override
+    public void visitParameter(final String name, final int access) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(tab2).append("// parameter ");
+        appendAccess(sb, access);
+        sb.append(' ').append(name == null ? "<no name>" : name)
+                .append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitCode() {
+        //empty
+    }
+
+    @Override
+    public void visitFrame(final int type, final int nLocal, final Object[] local, final int nStack, final Object[] stack) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("frame ");
+        switch (type) {
+        case Opcodes.F_NEW:
+        case Opcodes.F_FULL:
+            sb.append("full [");
+            appendFrameTypes(sb, nLocal, local);
+            sb.append("] [");
+            appendFrameTypes(sb, nStack, stack);
+            sb.append(']');
+            break;
+        case Opcodes.F_APPEND:
+            sb.append("append [");
+            appendFrameTypes(sb, nLocal, local);
+            sb.append(']');
+            break;
+        case Opcodes.F_CHOP:
+            sb.append("chop ").append(nLocal);
+            break;
+        case Opcodes.F_SAME:
+            sb.append("same");
+            break;
+        case Opcodes.F_SAME1:
+            sb.append("same1 ");
+            appendFrameTypes(sb, 1, stack);
+            break;
+        default:
+            assert false;
+            break;
+        }
+        sb.append('\n');
+        sb.append('\n');
+        addText(sb);
+    }
+
+    private StringBuilder appendOpcode(final StringBuilder sb, final int opcode) {
+        final Label next = getNextLabel();
+        if (next instanceof NashornLabel) {
+            final int bci = next.getOffset();
+            if (bci != -1) {
+                final String bcis = "" + bci;
+                for (int i = 0; i < 5 - bcis.length(); i++) {
+                    sb.append(' ');
+                }
+                sb.append(bcis);
+                sb.append(' ');
+            } else {
+                sb.append("       ");
+            }
+        }
+
+        return sb.append(tab2).append(OPCODES[opcode].toLowerCase());
+    }
+
+    private Label getNextLabel() {
+        return labelIter == null ? null : labelIter.next();
+    }
+
+    @Override
+    public void visitInsn(final int opcode) {
+        if(opcode == Opcodes.NOP) {
+            if(lastWasEllipse) {
+                getNextLabel();
+                return;
+            } else if(lastWasNop) {
+                getNextLabel();
+                addText("          ...\n");
+                lastWasEllipse = true;
+                return;
+            } else {
+                lastWasNop = true;
+            }
+        } else {
+            lastWasNop = lastWasEllipse = false;
+        }
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode).append('\n');
+        addText(sb);
+        checkNoFallThru(opcode, null);
+    }
+
+    @Override
+    public void visitIntInsn(final int opcode, final int operand) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode)
+                .append(' ')
+                .append(opcode == Opcodes.NEWARRAY ? TYPES[operand] : Integer
+                        .toString(operand)).append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitVarInsn(final int opcode, final int var) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode).append(' ').append(var).append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitTypeInsn(final int opcode, final String type) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode).append(' ');
+        appendDescriptor(sb, INTERNAL_NAME, type);
+        sb.append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode).append(' ');
+        appendDescriptor(sb, INTERNAL_NAME, owner);
+        sb.append('.').append(name).append(" : ");
+        appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+        sb.append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitMethodInsn(final int opcode, final String owner, final String name, final String desc, final boolean itf) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode).append(' ');
+        appendDescriptor(sb, INTERNAL_NAME, owner);
+        sb.append('.').append(name);
+        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+        sb.append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitInvokeDynamicInsn(final String name, final String desc, final Handle bsm, final Object... bsmArgs) {
+        final StringBuilder sb = new StringBuilder();
+
+        appendOpcode(sb, Opcodes.INVOKEDYNAMIC).append(' ');
+        sb.append(name);
+        appendDescriptor(sb, METHOD_DESCRIPTOR, desc);
+        final int len = sb.length();
+        for (int i = 0; i < 80 - len ; i++) {
+            sb.append(' ');
+        }
+        sb.append(" [");
+        appendHandle(sb, bsm);
+        if (bsmArgs.length == 0) {
+            sb.append("none");
+        } else {
+            for (final Object cst : bsmArgs) {
+                if (cst instanceof String) {
+                    appendStr(sb, (String)cst);
+                } else if (cst instanceof Type) {
+                    sb.append(((Type)cst).getDescriptor()).append(".class");
+                } else if (cst instanceof Handle) {
+                    appendHandle(sb, (Handle)cst);
+                } else if (cst instanceof Integer) {
+                    final int c = (Integer)cst;
+                    final int pp = c >> CALLSITE_PROGRAM_POINT_SHIFT;
+                    if (pp != 0) {
+                        sb.append(" pp=").append(pp);
+                    }
+                    sb.append(NashornCallSiteDescriptor.toString(c & FLAGS_MASK));
+                } else {
+                    sb.append(cst);
+                }
+                sb.append(", ");
+            }
+            sb.setLength(sb.length() - 2);
+        }
+
+        sb.append("]\n");
+        addText(sb);
+    }
+
+    private static final boolean noFallThru(final int opcode) {
+        switch (opcode) {
+        case Opcodes.GOTO:
+        case Opcodes.ATHROW:
+        case Opcodes.ARETURN:
+        case Opcodes.IRETURN:
+        case Opcodes.LRETURN:
+        case Opcodes.FRETURN:
+        case Opcodes.DRETURN:
+            return true;
+        default:
+            return false;
+        }
+    }
+
+    private void checkNoFallThru(final int opcode, final String to) {
+        if (noFallThru(opcode)) {
+            graph.setNoFallThru(currentBlock);
+        }
+
+        if (currentBlock != null && to != null) {
+            graph.addEdge(currentBlock, to);
+        }
+    }
+
+    @Override
+    public void visitJumpInsn(final int opcode, final Label label) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, opcode).append(' ');
+        final String to = appendLabel(sb, label);
+        sb.append('\n');
+        addText(sb);
+        checkNoFallThru(opcode, to);
+    }
+
+    private void addText(final Object t) {
+        text.add(t);
+        if (currentBlock != null) {
+            graph.addText(currentBlock, t.toString());
+        }
+    }
+
+    @Override
+    public void visitLabel(final Label label) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("\n");
+        final String name = appendLabel(sb, label);
+        sb.append(" [bci=");
+        sb.append(label.info);
+        sb.append("]");
+        sb.append("\n");
+
+        graph.addNode(name);
+        if (currentBlock != null && !graph.isNoFallThru(currentBlock)) {
+            graph.addEdge(currentBlock, name);
+        }
+        currentBlock = name;
+        addText(sb);
+    }
+
+    @Override
+    public void visitLdcInsn(final Object cst) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, Opcodes.LDC).append(' ');
+        if (cst instanceof String) {
+            appendStr(sb, (String) cst);
+        } else if (cst instanceof Type) {
+            sb.append(((Type) cst).getDescriptor()).append(".class");
+        } else {
+            sb.append(cst);
+        }
+        sb.append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitIincInsn(final int var, final int increment) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, Opcodes.IINC).append(' ');
+        sb.append(var).append(' ')
+                .append(increment).append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitTableSwitchInsn(final int min, final int max, final Label dflt, final Label... labels) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, Opcodes.TABLESWITCH).append(' ');
+        for (int i = 0; i < labels.length; ++i) {
+            sb.append(tab3).append(min + i).append(": ");
+            final String to = appendLabel(sb, labels[i]);
+            graph.addEdge(currentBlock, to);
+            sb.append('\n');
+        }
+        sb.append(tab3).append("default: ");
+        appendLabel(sb, dflt);
+        sb.append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitLookupSwitchInsn(final Label dflt, final int[] keys, final Label[] labels) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, Opcodes.LOOKUPSWITCH).append(' ');
+        for (int i = 0; i < labels.length; ++i) {
+            sb.append(tab3).append(keys[i]).append(": ");
+            final String to = appendLabel(sb, labels[i]);
+            graph.addEdge(currentBlock, to);
+            sb.append('\n');
+        }
+        sb.append(tab3).append("default: ");
+        final String to = appendLabel(sb, dflt);
+        graph.addEdge(currentBlock, to);
+        sb.append('\n');
+        addText(sb.toString());
+    }
+
+    @Override
+    public void visitMultiANewArrayInsn(final String desc, final int dims) {
+        final StringBuilder sb = new StringBuilder();
+        appendOpcode(sb, Opcodes.MULTIANEWARRAY).append(' ');
+        appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+        sb.append(' ').append(dims).append('\n');
+        addText(sb);
+    }
+
+    @Override
+    public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(tab2).append("try ");
+        final String from = appendLabel(sb, start);
+        sb.append(' ');
+        appendLabel(sb, end);
+        sb.append(' ');
+        final String to = appendLabel(sb, handler);
+        sb.append(' ');
+        appendDescriptor(sb, INTERNAL_NAME, type);
+        sb.append('\n');
+        addText(sb);
+        graph.setIsCatch(to, type);
+        graph.addTryCatch(from, to);
+    }
+
+    @Override
+    public void visitLocalVariable(final String name, final String desc,final String signature, final Label start, final Label end, final int index) {
+
+        final StringBuilder sb = new StringBuilder();
+        if (!localVarsStarted) {
+            text.add("\n");
+            localVarsStarted = true;
+            graph.addNode("vars");
+            currentBlock = "vars";
+        }
+
+        sb.append(tab2).append("local ").append(name).append(' ');
+        final int len = sb.length();
+        for (int i = 0; i < 25 - len; i++) {
+            sb.append(' ');
+        }
+        String label;
+
+        label = appendLabel(sb, start);
+        for (int i = 0; i < 5 - label.length(); i++) {
+            sb.append(' ');
+        }
+        label = appendLabel(sb, end);
+        for (int i = 0; i < 5 - label.length(); i++) {
+            sb.append(' ');
+        }
+
+        sb.append(index).append(tab2);
+
+        appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+        sb.append('\n');
+
+        if (signature != null) {
+            sb.append(tab2);
+            appendDescriptor(sb, FIELD_SIGNATURE, signature);
+
+            final TraceSignatureVisitor sv = new TraceSignatureVisitor(0);
+            final SignatureReader r = new SignatureReader(signature);
+            r.acceptType(sv);
+            sb.append(tab2).append("// declaration: ")
+                    .append(sv.getDeclaration()).append('\n');
+        }
+        addText(sb.toString());
+    }
+
+    @Override
+    public void visitLineNumber(final int line, final Label start) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("<line ");
+        sb.append(line);
+        sb.append(">\n");
+        addText(sb.toString());
+    }
+
+    @Override
+    public void visitMaxs(final int maxStack, final int maxLocals) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append('\n');
+        sb.append(tab2).append("max stack  = ").append(maxStack);
+        sb.append(", max locals = ").append(maxLocals).append('\n');
+        addText(sb.toString());
+    }
+
+    private void printToDir(final Graph g) {
+        if (env._print_code_dir != null) {
+            final File dir = new File(env._print_code_dir);
+            if (!dir.exists() && !dir.mkdirs()) {
+                throw new RuntimeException(dir.toString());
+            }
+
+            File file;
+            int uniqueId = 0;
+            do {
+                final String fileName = g.getName() + (uniqueId == 0 ? "" : "_" + uniqueId) +  ".dot";
+                file = new File(dir, fileName);
+                uniqueId++;
+            } while (file.exists());
+
+            try (PrintWriter pw = new PrintWriter(new FileOutputStream(file))) {
+                pw.println(g);
+            } catch (final FileNotFoundException e) {
+                throw new RuntimeException(e);
+            }
+        }
+    }
+
+    @Override
+    public void visitMethodEnd() {
+        //here we need to do several bytecode guesses best upon the ldc instructions.
+        //for each instruction, assign bci. for an ldc/w/2w, guess a byte and keep
+        //iterating. if the next label is wrong, backtrack.
+        if (env._print_code_func == null || env._print_code_func.equals(graph.getName())) {
+            if (env._print_code_dir != null) {
+                printToDir(graph);
+            }
+        }
+    }
+
+    /**
+     * Creates a new TraceVisitor instance.
+     *
+     * @return a new TraceVisitor.
+     */
+    protected NashornTextifier createNashornTextifier() {
+        return new NashornTextifier(env, cr, labelIter, graph);
+    }
+
+    private static void appendDescriptor(final StringBuilder sb, final int type, final String desc) {
+        if (desc != null) {
+            if (type == CLASS_SIGNATURE || type == FIELD_SIGNATURE || type == METHOD_SIGNATURE) {
+                sb.append("// signature ").append(desc).append('\n');
+            } else {
+                appendShortDescriptor(sb, desc);
+            }
+        }
+    }
+
+    private String appendLabel(final StringBuilder sb, final Label l) {
+        if (labelNames == null) {
+            labelNames = new HashMap<>();
+        }
+        String name = labelNames.get(l);
+        if (name == null) {
+            name = "L" + labelNames.size();
+            labelNames.put(l, name);
+        }
+        sb.append(name);
+        return name;
+    }
+
+    private static void appendHandle(final StringBuilder sb, final Handle h) {
+        switch (h.getTag()) {
+        case Opcodes.H_GETFIELD:
+            sb.append("getfield");
+            break;
+        case Opcodes.H_GETSTATIC:
+            sb.append("getstatic");
+            break;
+        case Opcodes.H_PUTFIELD:
+            sb.append("putfield");
+            break;
+        case Opcodes.H_PUTSTATIC:
+            sb.append("putstatic");
+            break;
+        case Opcodes.H_INVOKEINTERFACE:
+            sb.append("interface");
+            break;
+        case Opcodes.H_INVOKESPECIAL:
+            sb.append("special");
+            break;
+        case Opcodes.H_INVOKESTATIC:
+            sb.append("static");
+            break;
+        case Opcodes.H_INVOKEVIRTUAL:
+            sb.append("virtual");
+            break;
+        case Opcodes.H_NEWINVOKESPECIAL:
+            sb.append("new_special");
+            break;
+        default:
+            assert false;
+            break;
+        }
+        sb.append(" '");
+        sb.append(h.getName());
+        sb.append("'");
+    }
+
+    private static void appendAccess(final StringBuilder sb, final int access) {
+        if ((access & Opcodes.ACC_PUBLIC) != 0) {
+            sb.append("public ");
+        }
+        if ((access & Opcodes.ACC_PRIVATE) != 0) {
+            sb.append("private ");
+        }
+        if ((access & Opcodes.ACC_PROTECTED) != 0) {
+            sb.append("protected ");
+        }
+        if ((access & Opcodes.ACC_FINAL) != 0) {
+            sb.append("final ");
+        }
+        if ((access & Opcodes.ACC_STATIC) != 0) {
+            sb.append("static ");
+        }
+        if ((access & Opcodes.ACC_SYNCHRONIZED) != 0) {
+            sb.append("synchronized ");
+        }
+        if ((access & Opcodes.ACC_VOLATILE) != 0) {
+            sb.append("volatile ");
+        }
+        if ((access & Opcodes.ACC_TRANSIENT) != 0) {
+            sb.append("transient ");
+        }
+        if ((access & Opcodes.ACC_ABSTRACT) != 0) {
+            sb.append("abstract ");
+        }
+        if ((access & Opcodes.ACC_STRICT) != 0) {
+            sb.append("strictfp ");
+        }
+        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {
+            sb.append("synthetic ");
+        }
+        if ((access & Opcodes.ACC_MANDATED) != 0) {
+            sb.append("mandated ");
+        }
+        if ((access & Opcodes.ACC_ENUM) != 0) {
+            sb.append("enum ");
+        }
+    }
+
+    private void appendFrameTypes(final StringBuilder sb, final int n, final Object[] o) {
+        for (int i = 0; i < n; ++i) {
+            if (i > 0) {
+                sb.append(' ');
+            }
+            if (o[i] instanceof String) {
+                final String desc = (String) o[i];
+                if (desc.startsWith("[")) {
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, desc);
+                } else {
+                    appendDescriptor(sb, INTERNAL_NAME, desc);
+                }
+            } else if (o[i] instanceof Integer) {
+                switch (((Integer)o[i]).intValue()) {
+                case 0:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "T");
+                    break;
+                case 1:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "I");
+                    break;
+                case 2:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "F");
+                    break;
+                case 3:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "D");
+                    break;
+                case 4:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "J");
+                    break;
+                case 5:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "N");
+                    break;
+                case 6:
+                    appendDescriptor(sb, FIELD_DESCRIPTOR, "U");
+                    break;
+                default:
+                    assert false;
+                    break;
+                }
+            } else {
+                appendLabel(sb, (Label) o[i]);
+            }
+        }
+    }
+
+    private static void appendShortDescriptor(final StringBuilder sb, final String desc) {
+        //final StringBuilder buf = new StringBuilder();
+        if (desc.charAt(0) == '(') {
+            for (int i = 0; i < desc.length(); i++) {
+                if (desc.charAt(i) == 'L') {
+                    int slash = i;
+                    while (desc.charAt(i) != ';') {
+                        i++;
+                        if (desc.charAt(i) == '/') {
+                            slash = i;
+                        }
+                    }
+                    sb.append(desc.substring(slash + 1, i)).append(';');
+                } else {
+                    sb.append(desc.charAt(i));
+                }
+            }
+        } else {
+            final int lastSlash = desc.lastIndexOf('/');
+            final int lastBracket = desc.lastIndexOf('[');
+            if(lastBracket != -1) {
+                sb.append(desc, 0, lastBracket + 1);
+            }
+            sb.append(lastSlash == -1 ? desc : desc.substring(lastSlash + 1));
+        }
+    }
+
+    private static void appendStr(final StringBuilder sb, final String s) {
+        sb.append('\"');
+        for (int i = 0; i < s.length(); ++i) {
+            final char c = s.charAt(i);
+            if (c == '\n') {
+                sb.append("\\n");
+            } else if (c == '\r') {
+                sb.append("\\r");
+            } else if (c == '\\') {
+                sb.append("\\\\");
+            } else if (c == '"') {
+                sb.append("\\\"");
+            } else if (c < 0x20 || c > 0x7f) {
+                sb.append("\\u");
+                if (c < 0x10) {
+                    sb.append("000");
+                } else if (c < 0x100) {
+                    sb.append("00");
+                } else if (c < 0x1000) {
+                    sb.append('0');
+                }
+                sb.append(Integer.toString(c, 16));
+            } else {
+                sb.append(c);
+            }
+        }
+        sb.append('\"');
+    }
+
+    private static class Graph {
+        private final LinkedHashSet<String> nodes;
+        private final Map<String, StringBuilder> contents;
+        private final Map<String, Set<String>> edges;
+        private final Set<String> hasPreds;
+        private final Set<String> noFallThru;
+        private final Map<String, String> catches;
+        private final Map<String, Set<String>> exceptionMap; //maps catch nodes to all their trys that can reach them
+        private final String name;
+
+        private static final String LEFT_ALIGN      = "\\l";
+        private static final String COLOR_CATCH     = "\"#ee9999\"";
+        private static final String COLOR_ORPHAN    = "\"#9999bb\"";
+        private static final String COLOR_DEFAULT   = "\"#99bb99\"";
+        private static final String COLOR_LOCALVARS = "\"#999999\"";
+
+        Graph(final String name) {
+            this.name         = name;
+            this.nodes        = new LinkedHashSet<>();
+            this.contents     = new HashMap<>();
+            this.edges        = new HashMap<>();
+            this.hasPreds     = new HashSet<>();
+            this.catches      = new HashMap<>();
+            this.noFallThru   = new HashSet<>();
+            this.exceptionMap = new HashMap<>();
+         }
+
+        void addEdge(final String from, final String to) {
+            Set<String> edgeSet = edges.get(from);
+            if (edgeSet == null) {
+                edgeSet = new LinkedHashSet<>();
+                edges.put(from, edgeSet);
+            }
+            edgeSet.add(to);
+            hasPreds.add(to);
+        }
+
+        void addTryCatch(final String tryNode, final String catchNode) {
+            Set<String> tryNodes = exceptionMap.get(catchNode);
+            if (tryNodes == null) {
+                tryNodes = new HashSet<>();
+                exceptionMap.put(catchNode, tryNodes);
+            }
+            if (!tryNodes.contains(tryNode)) {
+                addEdge(tryNode, catchNode);
+            }
+            tryNodes.add(tryNode);
+        }
+
+        void addNode(final String node) {
+            assert !nodes.contains(node);
+            nodes.add(node);
+        }
+
+        void setNoFallThru(final String node) {
+            noFallThru.add(node);
+        }
+
+        boolean isNoFallThru(final String node) {
+            return noFallThru.contains(node);
+        }
+
+        void setIsCatch(final String node, final String exception) {
+            catches.put(node, exception);
+        }
+
+        String getName() {
+            return name;
+        }
+
+        void addText(final String node, final String text) {
+            StringBuilder sb = contents.get(node);
+            if (sb == null) {
+                sb = new StringBuilder();
+            }
+
+            for (int i = 0; i < text.length(); i++) {
+                switch (text.charAt(i)) {
+                case '\n':
+                    sb.append(LEFT_ALIGN);
+                    break;
+                case '"':
+                    sb.append("'");
+                    break;
+                default:
+                    sb.append(text.charAt(i));
+                    break;
+                }
+           }
+
+            contents.put(node, sb);
+        }
+
+        private static String dottyFriendly(final String name) {
+            return name.replace(':', '_');
+        }
+
+        @Override
+        public String toString() {
+
+            final StringBuilder sb = new StringBuilder();
+            sb.append("digraph " + dottyFriendly(name) + " {");
+            sb.append("\n");
+            sb.append("\tgraph [fontname=courier]\n");
+            sb.append("\tnode [style=filled,color="+COLOR_DEFAULT+",fontname=courier]\n");
+            sb.append("\tedge [fontname=courier]\n\n");
+
+            for (final String node : nodes) {
+                sb.append("\t");
+                sb.append(node);
+                sb.append(" [");
+                sb.append("id=");
+                sb.append(node);
+                sb.append(", label=\"");
+                String c = contents.get(node).toString();
+                if (c.startsWith(LEFT_ALIGN)) {
+                    c = c.substring(LEFT_ALIGN.length());
+                }
+                final String ex = catches.get(node);
+                if (ex != null) {
+                    sb.append("*** CATCH: ").append(ex).append(" ***\n");
+                }
+                sb.append(c);
+                sb.append("\"]\n");
+            }
+
+            for (final String from : edges.keySet()) {
+                for (final String to : edges.get(from)) {
+                    sb.append("\t");
+                    sb.append(from);
+                    sb.append(" -> ");
+                    sb.append(to);
+                    sb.append("[label=\"");
+                    sb.append(to);
+                    sb.append("\"");
+                    if (catches.get(to) != null) {
+                        sb.append(", color=red, style=dashed");
+                    }
+                    sb.append(']');
+                    sb.append(";\n");
+                }
+            }
+
+            sb.append("\n");
+            for (final String node : nodes) {
+                sb.append("\t");
+                sb.append(node);
+                sb.append(" [shape=box");
+                if (catches.get(node) != null) {
+                    sb.append(", color=" + COLOR_CATCH);
+                } else if ("vars".equals(node)) {
+                    sb.append(", shape=hexagon, color=" + COLOR_LOCALVARS);
+                } else if (!hasPreds.contains(node)) {
+                    sb.append(", color=" + COLOR_ORPHAN);
+                }
+                sb.append("]\n");
+            }
+
+            sb.append("}\n");
+            return sb.toString();
+        }
+    }
+
+    static class NashornLabel extends Label {
+        final Label label;
+        final int   bci;
+        final int   opcode;
+
+        NashornLabel(final Label label, final int bci) {
+            this.label = label;
+            this.bci   = bci;
+            this.opcode = -1;
+        }
+
+        //not an ASM label
+        NashornLabel(final int opcode, final int bci) {
+            this.opcode = opcode;
+            this.bci = bci;
+            this.label = null;
+        }
+
+        Label getLabel() {
+            return label;
+        }
+
+        @Override
+        public int getOffset() {
+            return bci;
+        }
+
+        @Override
+        public String toString() {
+            return "label " + bci;
+        }
+    }
+
+    @Override
+    public Printer visitAnnotationDefault() {
+        throw new AssertionError();
+    }
+
+    @Override
+    public Printer visitClassAnnotation(final String arg0, final boolean arg1) {
+        return this;
+    }
+
+    @Override
+    public void visitClassAttribute(final Attribute arg0) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public Printer visitFieldAnnotation(final String arg0, final boolean arg1) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public void visitFieldAttribute(final Attribute arg0) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public Printer visitMethodAnnotation(final String arg0, final boolean arg1) {
+        return this;
+    }
+
+    @Override
+    public void visitMethodAttribute(final Attribute arg0) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public Printer visitParameterAnnotation(final int arg0, final String arg1, final boolean arg2) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public void visit(final String arg0, final Object arg1) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public Printer visitAnnotation(final String arg0, final String arg1) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public void visitAnnotationEnd() {
+        //empty
+    }
+
+    @Override
+    public Printer visitArray(final String arg0) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public void visitEnum(final String arg0, final String arg1, final String arg2) {
+        throw new AssertionError();
+    }
+
+    @Override
+    public void visitInnerClass(final String arg0, final String arg1, final String arg2, final int arg3) {
+        throw new AssertionError();
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java b/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
index 89269d5..53a09a6 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/ObjectSizeCalculator.java
@@ -52,9 +52,7 @@
  * this fact and will report incorrect sizes, as it will presume the default JVM
  * behavior.
  */
-
-@SuppressWarnings("StaticNonFinalUsedInInitialization")
-public class ObjectSizeCalculator {
+public final class ObjectSizeCalculator {
 
     /**
      * Describes constant memory overheads for various constructs in a JVM implementation.
@@ -307,7 +305,7 @@
         public ClassSizeInfo(final Class<?> clazz) {
             long newFieldsSize = 0;
             final List<Field> newReferenceFields = new LinkedList<>();
-            for (Field f : clazz.getDeclaredFields()) {
+            for (final Field f : clazz.getDeclaredFields()) {
                 if (Modifier.isStatic(f.getModifiers())) {
                     continue;
                 }
@@ -338,10 +336,10 @@
         }
 
         public void enqueueReferencedObjects(final Object obj, final ObjectSizeCalculator calc) {
-            for (Field f : referenceFields) {
+            for (final Field f : referenceFields) {
                 try {
                     calc.enqueue(f.get(obj));
-                } catch (IllegalAccessException e) {
+                } catch (final IllegalAccessException e) {
                     final AssertionError ae = new AssertionError(
                             "Unexpected denial of access to " + f);
                     ae.initCause(e);
diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java b/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
index 09af647..52e9b66 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/debug/PrintVisitor.java
@@ -29,18 +29,25 @@
 import jdk.nashorn.internal.ir.BinaryNode;
 import jdk.nashorn.internal.ir.Block;
 import jdk.nashorn.internal.ir.BlockStatement;
+import jdk.nashorn.internal.ir.BreakNode;
 import jdk.nashorn.internal.ir.CaseNode;
 import jdk.nashorn.internal.ir.CatchNode;
+import jdk.nashorn.internal.ir.ContinueNode;
 import jdk.nashorn.internal.ir.ExpressionStatement;
 import jdk.nashorn.internal.ir.ForNode;
 import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
+import jdk.nashorn.internal.ir.JoinPredecessor;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.LocalVariableConversion;
 import jdk.nashorn.internal.ir.Node;
 import jdk.nashorn.internal.ir.SplitNode;
 import jdk.nashorn.internal.ir.Statement;
 import jdk.nashorn.internal.ir.SwitchNode;
+import jdk.nashorn.internal.ir.ThrowNode;
 import jdk.nashorn.internal.ir.TryNode;
 import jdk.nashorn.internal.ir.UnaryNode;
 import jdk.nashorn.internal.ir.VarNode;
@@ -70,25 +77,30 @@
     /** Print line numbers */
     private final boolean printLineNumbers;
 
+    /** Print inferred and optimistic types */
+    private final boolean printTypes;
+
     private int lastLineNumber = -1;
 
     /**
      * Constructor.
      */
     public PrintVisitor() {
-        this(true);
+        this(true, true);
     }
 
     /**
      * Constructor
      *
      * @param printLineNumbers  should line number nodes be included in the output?
+     * @param printTypes        should we print optimistic and inferred types?
      */
-    public PrintVisitor(final boolean printLineNumbers) {
+    public PrintVisitor(final boolean printLineNumbers, final boolean printTypes) {
         super(new LexicalContext());
         this.EOLN             = System.lineSeparator();
         this.sb               = new StringBuilder();
         this.printLineNumbers = printLineNumbers;
+        this.printTypes       = printTypes;
     }
 
     /**
@@ -97,7 +109,7 @@
      * @param root  a node from which to start printing code
      */
     public PrintVisitor(final Node root) {
-        this(root, true);
+        this(root, true, true);
     }
 
     /**
@@ -105,9 +117,10 @@
      *
      * @param root              a node from which to start printing code
      * @param printLineNumbers  should line numbers nodes be included in the output?
+     * @param printTypes        should we print optimistic and inferred types?
      */
-    public PrintVisitor(final Node root, final boolean printLineNumbers) {
-        this(printLineNumbers);
+    public PrintVisitor(final Node root, final boolean printLineNumbers, final boolean printTypes) {
+        this(printLineNumbers, printTypes);
         visit(root);
     }
 
@@ -135,7 +148,28 @@
 
     @Override
     public boolean enterDefault(final Node node) {
-        node.toString(sb);
+        node.toString(sb, printTypes);
+        return false;
+    }
+
+    @Override
+    public boolean enterContinueNode(final ContinueNode node) {
+        node.toString(sb, printTypes);
+        printLocalVariableConversion(node);
+        return false;
+    }
+
+    @Override
+    public boolean enterBreakNode(final BreakNode node) {
+        node.toString(sb, printTypes);
+        printLocalVariableConversion(node);
+        return false;
+    }
+
+    @Override
+    public boolean enterThrowNode(final ThrowNode node) {
+        node.toString(sb, printTypes);
+        printLocalVariableConversion(node);
         return false;
     }
 
@@ -148,9 +182,9 @@
 
         final List<Statement> statements = block.getStatements();
 
-        for (final Node statement : statements) {
-            if (printLineNumbers && (statement instanceof Statement)) {
-                final int lineNumber = ((Statement)statement).getLineNumber();
+        for (final Statement statement : statements) {
+            if (printLineNumbers) {
+                final int lineNumber = statement.getLineNumber();
                 sb.append('\n');
                 if (lineNumber != lastLineNumber) {
                     indent();
@@ -162,10 +196,6 @@
 
             statement.accept(this);
 
-            if (statement instanceof FunctionNode) {
-                continue;
-            }
-
             int  lastIndex = sb.length() - 1;
             char lastChar  = sb.charAt(lastIndex);
             while (Character.isWhitespace(lastChar) && lastIndex >= 0) {
@@ -190,6 +220,7 @@
         sb.append(EOLN);
         indent();
         sb.append('}');
+        printLocalVariableConversion(block);
 
         return false;
     }
@@ -211,13 +242,31 @@
     }
 
     @Override
+    public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression expr) {
+        expr.getExpression().accept(this);
+        printLocalVariableConversion(expr);
+        return false;
+    }
+
+    @Override
+    public boolean enterIdentNode(final IdentNode identNode) {
+        identNode.toString(sb, printTypes);
+        printLocalVariableConversion(identNode);
+        return true;
+    }
+
+    private void printLocalVariableConversion(final JoinPredecessor joinPredecessor) {
+        LocalVariableConversion.toString(joinPredecessor.getLocalVariableConversion(), sb);
+    }
+
+    @Override
     public boolean enterUnaryNode(final UnaryNode unaryNode) {
         unaryNode.toString(sb, new Runnable() {
             @Override
             public void run() {
-                unaryNode.rhs().accept(PrintVisitor.this);
+                unaryNode.getExpression().accept(PrintVisitor.this);
             }
-        });
+        }, printTypes);
         return false;
     }
 
@@ -229,21 +278,21 @@
 
     @Override
     public boolean enterForNode(final ForNode forNode) {
-        forNode.toString(sb);
+        forNode.toString(sb, printTypes);
         forNode.getBody().accept(this);
         return false;
     }
 
     @Override
     public boolean enterFunctionNode(final FunctionNode functionNode) {
-        functionNode.toString(sb);
+        functionNode.toString(sb, printTypes);
         enterBlock(functionNode.getBody());
         return false;
     }
 
     @Override
     public boolean enterIfNode(final IfNode ifNode) {
-        ifNode.toString(sb);
+        ifNode.toString(sb, printTypes);
         ifNode.getPass().accept(this);
 
         final Block fail = ifNode.getFail();
@@ -252,7 +301,12 @@
             sb.append(" else ");
             fail.accept(this);
         }
-
+        if(ifNode.getLocalVariableConversion() != null) {
+            assert fail == null;
+            sb.append(" else ");
+            printLocalVariableConversion(ifNode);
+            sb.append(";");
+        }
         return false;
     }
 
@@ -261,15 +315,15 @@
         indent -= TABWIDTH;
         indent();
         indent += TABWIDTH;
-        labeledNode.toString(sb);
+        labeledNode.toString(sb, printTypes);
         labeledNode.getBody().accept(this);
-
+        printLocalVariableConversion(labeledNode);
         return false;
     }
 
     @Override
     public boolean enterSplitNode(final SplitNode splitNode) {
-        splitNode.toString(sb);
+        splitNode.toString(sb, printTypes);
         sb.append(EOLN);
         indent += TABWIDTH;
         indent();
@@ -287,7 +341,7 @@
 
     @Override
     public boolean enterSwitchNode(final SwitchNode switchNode) {
-        switchNode.toString(sb);
+        switchNode.toString(sb, printTypes);
         sb.append(" {");
 
         final List<CaseNode> cases = switchNode.getCases();
@@ -295,13 +349,20 @@
         for (final CaseNode caseNode : cases) {
             sb.append(EOLN);
             indent();
-            caseNode.toString(sb);
+            caseNode.toString(sb, printTypes);
+            printLocalVariableConversion(caseNode);
             indent += TABWIDTH;
             caseNode.getBody().accept(this);
             indent -= TABWIDTH;
             sb.append(EOLN);
         }
-
+        if(switchNode.getLocalVariableConversion() != null) {
+            sb.append(EOLN);
+            indent();
+            sb.append("default: ");
+            printLocalVariableConversion(switchNode);
+            sb.append("{}");
+        }
         sb.append(EOLN);
         indent();
         sb.append("}");
@@ -311,14 +372,15 @@
 
     @Override
     public boolean enterTryNode(final TryNode tryNode) {
-        tryNode.toString(sb);
+        tryNode.toString(sb, printTypes);
+        printLocalVariableConversion(tryNode);
         tryNode.getBody().accept(this);
 
         final List<Block> catchBlocks = tryNode.getCatchBlocks();
 
         for (final Block catchBlock : catchBlocks) {
             final CatchNode catchNode = (CatchNode)catchBlock.getStatements().get(0);
-            catchNode.toString(sb);
+            catchNode.toString(sb, printTypes);
             catchNode.getBody().accept(this);
         }
 
@@ -335,7 +397,8 @@
     @Override
     public boolean enterVarNode(final VarNode varNode) {
         sb.append("var ");
-        varNode.getName().toString(sb);
+        varNode.getName().toString(sb, printTypes);
+        printLocalVariableConversion(varNode.getName());
         final Node init = varNode.getInit();
         if (init != null) {
             sb.append(" = ");
@@ -347,13 +410,14 @@
 
     @Override
     public boolean enterWhileNode(final WhileNode whileNode) {
+        printLocalVariableConversion(whileNode);
         if (whileNode.isDoWhile()) {
             sb.append("do");
             whileNode.getBody().accept(this);
             sb.append(' ');
-            whileNode.toString(sb);
+            whileNode.toString(sb, printTypes);
         } else {
-            whileNode.toString(sb);
+            whileNode.toString(sb, printTypes);
             whileNode.getBody().accept(this);
         }
 
@@ -362,7 +426,7 @@
 
     @Override
     public boolean enterWithNode(final WithNode withNode) {
-        withNode.toString(sb);
+        withNode.toString(sb, printTypes);
         withNode.getBody().accept(this);
 
         return false;
diff --git a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
index 2b1de7c..1582f30 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeOperatorVisitor.java
@@ -53,8 +53,6 @@
             return enterBIT_NOT(unaryNode);
         case DELETE:
             return enterDELETE(unaryNode);
-        case DISCARD:
-            return enterDISCARD(unaryNode);
         case NEW:
             return enterNEW(unaryNode);
         case NOT:
@@ -84,8 +82,6 @@
             return leaveBIT_NOT(unaryNode);
         case DELETE:
             return leaveDELETE(unaryNode);
-        case DISCARD:
-            return leaveDISCARD(unaryNode);
         case NEW:
             return leaveNEW(unaryNode);
         case NOT:
@@ -359,26 +355,6 @@
     }
 
     /**
-     * Unary enter - callback for entering a discard operator
-     *
-     * @param  unaryNode the node
-     * @return true if traversal should continue and node children be traversed, false otherwise
-     */
-    public boolean enterDISCARD(final UnaryNode unaryNode) {
-        return enterDefault(unaryNode);
-    }
-
-    /**
-     * Unary leave - callback for leaving a discard operator
-     *
-     * @param  unaryNode the node
-     * @return processed node, which will replace the original one, or the original node
-     */
-     public Node leaveDISCARD(final UnaryNode unaryNode) {
-        return leaveDefault(unaryNode);
-    }
-
-    /**
      * Unary enter - callback for entering a new operator
      *
      * @param  unaryNode the node
diff --git a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
index 4dc55b3..5bf760b 100644
--- a/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
+++ b/nashorn/src/jdk/nashorn/internal/ir/visitor/NodeVisitor.java
@@ -41,6 +41,7 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
@@ -689,6 +690,27 @@
     }
 
     /**
+     * Callback for entering a {@link JoinPredecessorExpression}.
+     *
+     * @param  expr the join predecessor expression
+     * @return true if traversal should continue and node children be traversed, false otherwise
+     */
+    public boolean enterJoinPredecessorExpression(final JoinPredecessorExpression expr) {
+        return enterDefault(expr);
+    }
+
+    /**
+     * Callback for leaving a {@link JoinPredecessorExpression}.
+     *
+     * @param  expr the join predecessor expression
+     * @return processed node, which will replace the original one, or the original node
+     */
+    public Node leaveJoinPredecessorExpression(final JoinPredecessorExpression expr) {
+        return leaveDefault(expr);
+    }
+
+
+    /**
      * Callback for entering a VarNode
      *
      * @param  varNode   the node
diff --git a/nashorn/src/jdk/nashorn/internal/lookup/Lookup.java b/nashorn/src/jdk/nashorn/internal/lookup/Lookup.java
index 0dd2741..5772850 100644
--- a/nashorn/src/jdk/nashorn/internal/lookup/Lookup.java
+++ b/nashorn/src/jdk/nashorn/internal/lookup/Lookup.java
@@ -68,6 +68,12 @@
     /** Method handle to the most generic of setters, the one that takes an Object */
     public static final MethodType SET_OBJECT_TYPE = MH.type(void.class, Object.class, Object.class);
 
+    /** Method handle to the primitive getters, the one that returns an long/int/double */
+    public static final MethodType GET_PRIMITIVE_TYPE = MH.type(long.class, Object.class);
+
+    /** Method handle to the primitive getters, the one that returns an long/int/double */
+    public static final MethodType SET_PRIMITIVE_TYPE = MH.type(void.class, Object.class, long.class);
+
     private Lookup() {
     }
 
@@ -123,6 +129,53 @@
     }
 
     /**
+     * This method filters primitive argument types using JavaScript semantics. For example,
+     * an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it.
+     * If you are returning values to JavaScript that have to be of a specific type, this is
+     * the correct return value filter to use, as the explicitCastArguments just uses the
+     * Java boxing equivalents
+     *
+     * @param mh   method handle for which to filter argument value
+     * @param n    argument index
+     * @param from old argument type, the new one is given by the sent method handle
+     * @return method handle for appropriate argument type conversion
+     */
+    public static MethodHandle filterArgumentType(final MethodHandle mh, final int n, final Class<?> from) {
+        final Class<?> to = mh.type().parameterType(n);
+
+        if (from == int.class) {
+            //fallthru
+        } else if (from == long.class) {
+            if (to == int.class) {
+                return MH.filterArguments(mh, n, JSType.TO_INT32_L.methodHandle());
+            }
+            //fallthru
+        } else if (from == double.class) {
+            if (to == int.class) {
+                return MH.filterArguments(mh, n, JSType.TO_INT32_D.methodHandle());
+            } else if (to == long.class) {
+                return MH.filterArguments(mh, n, JSType.TO_UINT32_D.methodHandle());
+            }
+            //fallthru
+        } else if (!from.isPrimitive()) {
+            if (to == int.class) {
+                return MH.filterArguments(mh, n, JSType.TO_INT32.methodHandle());
+            } else if (to == long.class) {
+                return MH.filterArguments(mh, n, JSType.TO_UINT32.methodHandle());
+            } else if (to == double.class) {
+                return MH.filterArguments(mh, n, JSType.TO_NUMBER.methodHandle());
+            } else if (!to.isPrimitive()) {
+                return mh;
+            }
+
+            assert false : "unsupported Lookup.filterReturnType type " + from + " -> " + to;
+        }
+
+        //use a standard cast - we don't need to check JavaScript special cases
+        return MH.explicitCastArguments(mh, mh.type().changeParameterType(n, from));
+    }
+
+    /**
      * This method filters primitive return types using JavaScript semantics. For example,
      * an (int) cast of a double in Java land is not the same thing as invoking toInt32 on it.
      * If you are returning values to JavaScript that have to be of a specific type, this is
@@ -139,6 +192,9 @@
         if (retType == int.class) {
             //fallthru
         } else if (retType == long.class) {
+            if (type == int.class) {
+                return MH.filterReturnValue(mh, JSType.TO_INT32_L.methodHandle());
+            }
             //fallthru
         } else if (retType == double.class) {
             if (type == int.class) {
diff --git a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
index 34fe2eb..8ef13d7 100644
--- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
+++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java
@@ -37,9 +37,12 @@
 import java.util.List;
 import java.util.logging.Level;
 import jdk.nashorn.internal.runtime.ConsString;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
-import jdk.nashorn.internal.runtime.DebugLogger;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -96,27 +99,9 @@
         return obj.toString();
     }
 
-    private static final MethodHandleFunctionality STANDARD = new StandardMethodHandleFunctionality();
-    private static final MethodHandleFunctionality FUNC;
-
-    private static final String DEBUG_PROPERTY = "nashorn.methodhandles.debug";
-    private static final DebugLogger LOG = new DebugLogger("methodhandles", DEBUG_PROPERTY);
-
-    static {
-        if (LOG.isEnabled() || Options.getBooleanProperty(DEBUG_PROPERTY)) {
-            if (Options.getStringProperty(DEBUG_PROPERTY, "").equals("create")) {
-                FUNC = new TraceCreateMethodHandleFunctionality();
-            } else {
-                FUNC = new TraceMethodHandleFunctionality();
-            }
-        } else {
-            FUNC  = STANDARD;
-        }
-    }
-
+    private static final MethodHandleFunctionality FUNC = new StandardMethodHandleFunctionality();
     private static final boolean PRINT_STACKTRACE = Options.getBooleanProperty("nashorn.methodhandles.debug.stacktrace");
 
-
     /**
      * Return the method handle functionality used for all method handle operations
      * @return a method handle functionality implementation
@@ -125,8 +110,11 @@
         return FUNC;
     }
 
-    private static final MethodHandle TRACE        = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs",   MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
-    private static final MethodHandle TRACE_RETURN = STANDARD.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
+    private static final MethodHandle TRACE             = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceArgs",   MethodType.methodType(void.class, DebugLogger.class, String.class, int.class, Object[].class));
+    private static final MethodHandle TRACE_RETURN      = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturn", MethodType.methodType(Object.class, DebugLogger.class, Object.class));
+    private static final MethodHandle TRACE_RETURN_VOID = FUNC.findStatic(LOOKUP, MethodHandleFactory.class, "traceReturnVoid", MethodType.methodType(void.class, DebugLogger.class));
+
+    private static final String VOID_TAG = "[VOID]";
 
     /**
      * Tracer that is applied before a value is returned from the traced function. It will output the return
@@ -136,11 +124,20 @@
      * @return return value unmodified
      */
     static Object traceReturn(final DebugLogger logger, final Object value) {
-        final String str = "\treturn: " + stripName(value) + " [type=" + (value == null ? "null" : stripName(value.getClass()) + ']');
-        logger.log(TRACE_LEVEL, str);
+        if (logger.isEnabled()) {
+            final String str = "    return" +
+                    (VOID_TAG.equals(value) ?
+                        ";" :
+                        " " + stripName(value) + "; // [type=" + (value == null ? "null]" : stripName(value.getClass()) + ']'));
+            logger.log(TRACE_LEVEL, str);
+        }
         return value;
     }
 
+    static void traceReturnVoid(final DebugLogger logger) {
+        traceReturn(logger, VOID_TAG);
+    }
+
     /**
      * Tracer that is applied before a function is called, printing the arguments
      *
@@ -203,7 +200,7 @@
 
         if (arg instanceof ScriptObject) {
             return arg.toString() +
-                " (map=" + Debug.id((((ScriptObject)arg).getMap())) +
+                " (map=" + Debug.id(((ScriptObject)arg).getMap()) +
                 ")";
         }
 
@@ -214,29 +211,32 @@
      * Add a debug printout to a method handle, tracing parameters and return values
      *
      * @param logger a specific logger to which to write the output
+     * @param level level over which to print
      * @param mh  method handle to trace
      * @param tag start of trace message
      * @return traced method handle
      */
-    public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final Object tag) {
-        return addDebugPrintout(logger, mh, 0, true, tag);
+    public static MethodHandle addDebugPrintout(final DebugLogger logger, final Level level, final MethodHandle mh, final Object tag) {
+        return addDebugPrintout(logger, level, mh, 0, true, tag);
     }
 
-
     /**
      * Add a debug printout to a method handle, tracing parameters and return values
      *
      * @param logger a specific logger to which to write the output
+     * @param level level over which to print
      * @param mh  method handle to trace
      * @param paramStart first param to print/trace
      * @param printReturnValue should we print/trace return value if available?
      * @param tag start of trace message
      * @return  traced method handle
      */
-    public static MethodHandle addDebugPrintout(final DebugLogger logger, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) {
+    public static MethodHandle addDebugPrintout(final DebugLogger logger, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Object tag) {
         final MethodType type = mh.type();
 
-        if (logger != null && logger.levelAbove(TRACE_LEVEL)) {
+        //if there is no logger, or if it's set to log only coarser events
+        //than the trace level, skip and return
+        if (logger != null && logger.levelCoarserThan(level)) {
             return mh;
         }
 
@@ -253,191 +253,49 @@
                 asType(type.changeReturnType(void.class)));
 
         final Class<?> retType = type.returnType();
-        if (retType != void.class && printReturnValue) {
-            final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
-            trace = MethodHandles.filterReturnValue(trace,
-                    traceReturn.asType(
-                        traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
+        if (printReturnValue) {
+            if (retType != void.class) {
+                final MethodHandle traceReturn = MethodHandles.insertArguments(TRACE_RETURN, 0, logger);
+                trace = MethodHandles.filterReturnValue(trace,
+                        traceReturn.asType(
+                            traceReturn.type().changeParameterType(0, retType).changeReturnType(retType)));
+            } else {
+                trace = MethodHandles.filterReturnValue(trace, MethodHandles.insertArguments(TRACE_RETURN_VOID, 0, logger));
+            }
         }
 
         return trace;
     }
 
     /**
-     * The standard class that marshalls all method handle operations to the java.lang.invoke
+     * Class that marshalls all method handle operations to the java.lang.invoke
      * package. This exists only so that it can be subclassed and method handles created from
      * Nashorn made possible to instrument.
      *
      * All Nashorn classes should use the MethodHandleFactory for their method handle operations
      */
-    private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality {
+    @Logger(name="methodhandles")
+    private static class StandardMethodHandleFunctionality implements MethodHandleFunctionality, Loggable {
 
-        @Override
-        public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
-            return MethodHandles.filterArguments(target, pos, filters);
+        // for bootstrapping reasons, because a lot of static fields use MH for lookups, we
+        // need to set the logger when the Global object is finished. This means that we don't
+        // get instrumentation for public static final MethodHandle SOMETHING = MH... in the builtin
+        // classes, but that doesn't matter, because this is usually not where we want it
+        private DebugLogger log = DebugLogger.DISABLED_LOGGER;
+
+        public StandardMethodHandleFunctionality() {
         }
 
         @Override
-        public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
-            return MethodHandles.filterReturnValue(target, filter);
+        public DebugLogger initLogger(final Context context) {
+            return this.log = context.getLogger(this.getClass());
         }
 
         @Override
-        public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
-            return MethodHandles.guardWithTest(test, target, fallback);
+        public DebugLogger getLogger() {
+            return log;
         }
 
-        @Override
-        public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
-            return MethodHandles.insertArguments(target, pos, values);
-        }
-
-        @Override
-        public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... valueTypes) {
-            return MethodHandles.dropArguments(target, pos, valueTypes);
-        }
-
-        @Override
-        public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> valueTypes) {
-            return MethodHandles.dropArguments(target, pos, valueTypes);
-        }
-
-        @Override
-        public MethodHandle asType(final MethodHandle handle, final MethodType type) {
-            return handle.asType(type);
-        }
-
-        @Override
-        public MethodHandle bindTo(final MethodHandle handle, final Object x) {
-            return handle.bindTo(x);
-        }
-
-        @Override
-        public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
-            return MethodHandles.foldArguments(target, combiner);
-        }
-
-        @Override
-        public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
-            return MethodHandles.explicitCastArguments(target, type);
-        }
-
-        @Override
-        public MethodHandle arrayElementGetter(final Class<?> type) {
-            return MethodHandles.arrayElementGetter(type);
-        }
-
-        @Override
-        public MethodHandle arrayElementSetter(final Class<?> type) {
-            return MethodHandles.arrayElementSetter(type);
-        }
-
-        @Override
-        public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
-            return MethodHandles.throwException(returnType, exType);
-        }
-
-        @Override
-        public MethodHandle constant(final Class<?> type, final Object value) {
-            return MethodHandles.constant(type, value);
-        }
-
-        @Override
-        public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
-            return handle.asCollector(arrayType, arrayLength);
-        }
-
-        @Override
-        public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
-            return handle.asSpreader(arrayType, arrayLength);
-        }
-
-        @Override
-        public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            try {
-                return explicitLookup.findGetter(clazz, name, type);
-            } catch (final NoSuchFieldException | IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-        @Override
-        public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            try {
-                return explicitLookup.findStaticGetter(clazz, name, type);
-            } catch (final NoSuchFieldException | IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-
-        @Override
-        public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            try {
-                return explicitLookup.findSetter(clazz, name, type);
-            } catch (final NoSuchFieldException | IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-        @Override
-        public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            try {
-                return explicitLookup.findStaticSetter(clazz, name, type);
-            } catch (final NoSuchFieldException | IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-        @Override
-        public MethodHandle find(final Method method) {
-            try {
-                return PUBLIC_LOOKUP.unreflect(method);
-            } catch (final IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-        @Override
-        public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
-            try {
-                return explicitLookup.findStatic(clazz, name, type);
-            } catch (final NoSuchMethodException | IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-        @Override
-        public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
-            try {
-                return explicitLookup.findVirtual(clazz, name, type);
-            } catch (final NoSuchMethodException | IllegalAccessException e) {
-                throw new LookupException(e);
-            }
-        }
-
-        @Override
-        public SwitchPoint createSwitchPoint() {
-            return new SwitchPoint();
-        }
-
-        @Override
-        public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
-            return sp.guardWithTest(before, after);
-        }
-
-        @Override
-        public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
-            return MethodType.methodType(returnType, paramTypes);
-        }
-
-    }
-
-    /**
-     * Class used for instrumenting and debugging Nashorn generated method handles
-     */
-    private static class TraceMethodHandleFunctionality extends StandardMethodHandleFunctionality {
-
         protected static String describe(final Object... data) {
             final StringBuilder sb = new StringBuilder();
 
@@ -470,177 +328,215 @@
         }
 
         public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
-            return addDebugPrintout(LOG, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
+            if (log.isEnabled()) {
+                if (PRINT_STACKTRACE) {
+                    stacktrace(log);
+                }
+                return addDebugPrintout(log, Level.INFO, master, Integer.MAX_VALUE, false, str + ' ' + describe(args));
+            }
+            return master;
         }
 
         @Override
         public MethodHandle filterArguments(final MethodHandle target, final int pos, final MethodHandle... filters) {
-            final MethodHandle mh = super.filterArguments(target, pos, filters);
+            final MethodHandle mh = MethodHandles.filterArguments(target, pos, filters);
             return debug(mh, "filterArguments", target, pos, filters);
         }
 
         @Override
         public MethodHandle filterReturnValue(final MethodHandle target, final MethodHandle filter) {
-            final MethodHandle mh = super.filterReturnValue(target, filter);
+            final MethodHandle mh = MethodHandles.filterReturnValue(target, filter);
             return debug(mh, "filterReturnValue", target, filter);
         }
 
         @Override
         public MethodHandle guardWithTest(final MethodHandle test, final MethodHandle target, final MethodHandle fallback) {
-            final MethodHandle mh = super.guardWithTest(test, target, fallback);
+            final MethodHandle mh = MethodHandles.guardWithTest(test, target, fallback);
             return debug(mh, "guardWithTest", test, target, fallback);
         }
 
         @Override
         public MethodHandle insertArguments(final MethodHandle target, final int pos, final Object... values) {
-            final MethodHandle mh = super.insertArguments(target, pos, values);
+            final MethodHandle mh = MethodHandles.insertArguments(target, pos, values);
             return debug(mh, "insertArguments", target, pos, values);
         }
 
         @Override
         public MethodHandle dropArguments(final MethodHandle target, final int pos, final Class<?>... values) {
-            final MethodHandle mh = super.dropArguments(target, pos, values);
+            final MethodHandle mh = MethodHandles.dropArguments(target, pos, values);
             return debug(mh, "dropArguments", target, pos, values);
         }
 
         @Override
         public MethodHandle dropArguments(final MethodHandle target, final int pos, final List<Class<?>> values) {
-            final MethodHandle mh = super.dropArguments(target, pos, values);
+            final MethodHandle mh = MethodHandles.dropArguments(target, pos, values);
             return debug(mh, "dropArguments", target, pos, values);
         }
 
         @Override
         public MethodHandle asType(final MethodHandle handle, final MethodType type) {
-            final MethodHandle mh = super.asType(handle, type);
+            final MethodHandle mh = handle.asType(type);
             return debug(mh, "asType", handle, type);
         }
 
         @Override
         public MethodHandle bindTo(final MethodHandle handle, final Object x) {
-            final MethodHandle mh = super.bindTo(handle, x);
+            final MethodHandle mh = handle.bindTo(x);
             return debug(mh, "bindTo", handle, x);
         }
 
         @Override
         public MethodHandle foldArguments(final MethodHandle target, final MethodHandle combiner) {
-            final MethodHandle mh = super.foldArguments(target, combiner);
+            final MethodHandle mh = MethodHandles.foldArguments(target, combiner);
             return debug(mh, "foldArguments", target, combiner);
         }
 
         @Override
         public MethodHandle explicitCastArguments(final MethodHandle target, final MethodType type) {
-            final MethodHandle mh = super.explicitCastArguments(target, type);
+            final MethodHandle mh = MethodHandles.explicitCastArguments(target, type);
             return debug(mh, "explicitCastArguments", target, type);
         }
 
         @Override
         public MethodHandle arrayElementGetter(final Class<?> type) {
-            final MethodHandle mh = super.arrayElementGetter(type);
+            final MethodHandle mh = MethodHandles.arrayElementGetter(type);
             return debug(mh, "arrayElementGetter", type);
         }
 
         @Override
         public MethodHandle arrayElementSetter(final Class<?> type) {
-            final MethodHandle mh = super.arrayElementSetter(type);
+            final MethodHandle mh = MethodHandles.arrayElementSetter(type);
             return debug(mh, "arrayElementSetter", type);
         }
 
         @Override
         public MethodHandle throwException(final Class<?> returnType, final Class<? extends Throwable> exType) {
-            final MethodHandle mh = super.throwException(returnType, exType);
+            final MethodHandle mh = MethodHandles.throwException(returnType, exType);
             return debug(mh, "throwException", returnType, exType);
         }
 
         @Override
+        public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler) {
+            final MethodHandle mh = MethodHandles.catchException(target, exType, handler);
+            return debug(mh, "catchException", exType);
+        }
+
+        @Override
         public MethodHandle constant(final Class<?> type, final Object value) {
-            final MethodHandle mh = super.constant(type, value);
+            final MethodHandle mh = MethodHandles.constant(type, value);
             return debug(mh, "constant", type, value);
         }
 
         @Override
         public MethodHandle asCollector(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
-            final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength);
+            final MethodHandle mh = handle.asCollector(arrayType, arrayLength);
             return debug(mh, "asCollector", handle, arrayType, arrayLength);
         }
 
         @Override
         public MethodHandle asSpreader(final MethodHandle handle, final Class<?> arrayType, final int arrayLength) {
-            final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength);
+            final MethodHandle mh = handle.asSpreader(arrayType, arrayLength);
             return debug(mh, "asSpreader", handle, arrayType, arrayLength);
         }
 
         @Override
         public MethodHandle getter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            final MethodHandle mh = super.getter(explicitLookup, clazz, name, type);
-            return debug(mh, "getter", explicitLookup, clazz, name, type);
+            try {
+                final MethodHandle mh = explicitLookup.findGetter(clazz, name, type);
+                return debug(mh, "getter", explicitLookup, clazz, name, type);
+            } catch (final NoSuchFieldException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public MethodHandle staticGetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            final MethodHandle mh = super.staticGetter(explicitLookup, clazz, name, type);
-            return debug(mh, "static getter", explicitLookup, clazz, name, type);
+            try {
+                final MethodHandle mh = explicitLookup.findStaticGetter(clazz, name, type);
+                return debug(mh, "static getter", explicitLookup, clazz, name, type);
+            } catch (final NoSuchFieldException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public MethodHandle setter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            final MethodHandle mh = super.setter(explicitLookup, clazz, name, type);
-            return debug(mh, "setter", explicitLookup, clazz, name, type);
+            try {
+                final MethodHandle mh = explicitLookup.findSetter(clazz, name, type);
+                return debug(mh, "setter", explicitLookup, clazz, name, type);
+            } catch (final NoSuchFieldException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public MethodHandle staticSetter(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final Class<?> type) {
-            final MethodHandle mh = super.staticSetter(explicitLookup, clazz, name, type);
-            return debug(mh, "static setter", explicitLookup, clazz, name, type);
+            try {
+                final MethodHandle mh = explicitLookup.findStaticSetter(clazz, name, type);
+                return debug(mh, "static setter", explicitLookup, clazz, name, type);
+            } catch (final NoSuchFieldException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public MethodHandle find(final Method method) {
-            final MethodHandle mh = super.find(method);
-            return debug(mh, "find", method);
+            try {
+                final MethodHandle mh = PUBLIC_LOOKUP.unreflect(method);
+                return debug(mh, "find", method);
+            } catch (final IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public MethodHandle findStatic(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
-            final MethodHandle mh = super.findStatic(explicitLookup, clazz, name, type);
-            return debug(mh, "findStatic", explicitLookup, clazz, name, type);
+            try {
+                final MethodHandle mh = explicitLookup.findStatic(clazz, name, type);
+                return debug(mh, "findStatic", explicitLookup, clazz, name, type);
+            } catch (final NoSuchMethodException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
+        }
+
+        @Override
+        public MethodHandle findSpecial(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type, final Class<?> thisClass) {
+            try {
+                final MethodHandle mh = explicitLookup.findSpecial(clazz, name, type, thisClass);
+                return debug(mh, "findSpecial", explicitLookup, clazz, name, type);
+            } catch (final NoSuchMethodException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public MethodHandle findVirtual(final MethodHandles.Lookup explicitLookup, final Class<?> clazz, final String name, final MethodType type) {
-            final MethodHandle mh = super.findVirtual(explicitLookup, clazz, name, type);
-            return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
+            try {
+                final MethodHandle mh = explicitLookup.findVirtual(clazz, name, type);
+                return debug(mh, "findVirtual", explicitLookup, clazz, name, type);
+            } catch (final NoSuchMethodException | IllegalAccessException e) {
+                throw new LookupException(e);
+            }
         }
 
         @Override
         public SwitchPoint createSwitchPoint() {
-            final SwitchPoint sp = super.createSwitchPoint();
-            LOG.log(TRACE_LEVEL, "createSwitchPoint ", sp);
+            final SwitchPoint sp = new SwitchPoint();
+            log.log(TRACE_LEVEL, "createSwitchPoint ", sp);
             return sp;
         }
 
         @Override
         public MethodHandle guardWithTest(final SwitchPoint sp, final MethodHandle before, final MethodHandle after) {
-            final MethodHandle mh = super.guardWithTest(sp, before, after);
+            final MethodHandle mh = sp.guardWithTest(before, after);
             return debug(mh, "guardWithTest", sp, before, after);
         }
 
         @Override
         public MethodType type(final Class<?> returnType, final Class<?>... paramTypes) {
-            final MethodType mt = super.type(returnType, paramTypes);
-            LOG.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
+            final MethodType mt = MethodType.methodType(returnType, paramTypes);
+            log.log(TRACE_LEVEL, "methodType ", returnType, " ", Arrays.toString(paramTypes), " ", mt);
             return mt;
         }
     }
-
-    /**
-     * Class used for debugging Nashorn generated method handles
-     */
-    private static class TraceCreateMethodHandleFunctionality extends TraceMethodHandleFunctionality {
-        @Override
-        public MethodHandle debug(final MethodHandle master, final String str, final Object... args) {
-            LOG.log(TRACE_LEVEL, str, " ", describe(args));
-            stacktrace(LOG);
-            return master;
-        }
-    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java
index c7dd83b..756c0b7 100644
--- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java
+++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFunctionality.java
@@ -152,6 +152,17 @@
     public MethodHandle throwException(Class<?> returnType, Class<? extends Throwable> exType);
 
     /**
+     * Wrapper for {@link java.lang.invoke.MethodHandles#catchException(MethodHandle, Class, MethodHandle)}
+     *
+     * @param target  target method
+     * @param exType  exception type
+     * @param handler the method handle to call when exception is thrown
+     *
+     * @return exception thrower method handle
+     */
+    public MethodHandle catchException(final MethodHandle target, final Class<? extends Throwable> exType, final MethodHandle handler);
+
+    /**
      * Wrapper for {@link java.lang.invoke.MethodHandles#constant(Class, Object)}
      *
      * @param type  type of constant
@@ -286,6 +297,19 @@
     public MethodHandle findVirtual(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type);
 
     /**
+     * Wrapper for {@link java.lang.invoke.MethodHandles.Lookup#findSpecial(Class, String, MethodType, Class)}
+     *
+     * @param explicitLookup explicit lookup to be used
+     * @param clazz          class to look in
+     * @param name           name of method
+     * @param type           method type
+     * @param thisClass      thisClass
+     *
+     * @return method handle for virtual method
+     */
+    public MethodHandle findSpecial(MethodHandles.Lookup explicitLookup, Class<?> clazz, String name, MethodType type, final Class<?> thisClass);
+
+    /**
      * Wrapper for SwitchPoint creation. Just like {@code new SwitchPoint()} but potentially
      * tracked
      *
@@ -313,5 +337,6 @@
      * @return the method type
      */
     public MethodType type(Class<?> returnType, Class<?>... paramTypes);
+
 }
 
diff --git a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
index e39c521..0e8ed35 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/AccessorPropertyDescriptor.java
@@ -209,6 +209,11 @@
     }
 
     @Override
+    public String toString() {
+        return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + " getter=" + get + " setter=" + set + "}]";
+    }
+
+    @Override
     public int hashCode() {
         int hash = 7;
         hash = 41 * hash + Objects.hashCode(this.configurable);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
index c29af85..445dc19 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/ArrayBufferView.java
@@ -26,7 +26,14 @@
 package jdk.nashorn.internal.objects;
 
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Getter;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -35,33 +42,46 @@
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 @ScriptClass("ArrayBufferView")
 abstract class ArrayBufferView extends ScriptObject {
+    private final NativeArrayBuffer buffer;
+    private final int byteOffset;
 
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
 
     private ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength, final Global global) {
         super($nasgenmap$);
-        checkConstructorArgs(buffer, byteOffset, elementLength);
-        this.setProto(getPrototype(global));
-        this.setArray(factory().createArrayData(buffer, byteOffset, elementLength));
+
+        final int bytesPerElement = bytesPerElement();
+
+        checkConstructorArgs(buffer.getByteLength(), bytesPerElement, byteOffset, elementLength);
+        setProto(getPrototype(global));
+
+        this.buffer     = buffer;
+        this.byteOffset = byteOffset;
+
+        assert byteOffset % bytesPerElement == 0;
+        final int start = byteOffset / bytesPerElement;
+        final ByteBuffer newNioBuffer = buffer.getNioBuffer().duplicate().order(ByteOrder.nativeOrder());
+        final ArrayData  data         = factory().createArrayData(newNioBuffer, start, start + elementLength);
+
+        setArray(data);
     }
 
-    ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
+    protected ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
         this(buffer, byteOffset, elementLength, Global.instance());
     }
 
-    private void checkConstructorArgs(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
+    private static void checkConstructorArgs(final int byteLength, final int bytesPerElement, final int byteOffset, final int elementLength) {
         if (byteOffset < 0 || elementLength < 0) {
-            throw new RuntimeException("byteOffset or length must not be negative");
-        }
-        if (byteOffset + elementLength * bytesPerElement() > buffer.getByteLength()) {
-            throw new RuntimeException("byteOffset + byteLength out of range");
-        }
-        if (byteOffset % bytesPerElement() != 0) {
-            throw new RuntimeException("byteOffset must be a multiple of the element size");
+            throw new RuntimeException("byteOffset or length must not be negative, byteOffset=" + byteOffset + ", elementLength=" + elementLength + ", bytesPerElement=" + bytesPerElement);
+        } else if (byteOffset + elementLength * bytesPerElement > byteLength) {
+            throw new RuntimeException("byteOffset + byteLength out of range, byteOffset=" + byteOffset + ", elementLength=" + elementLength + ", bytesPerElement=" + bytesPerElement);
+        } else if (byteOffset % bytesPerElement != 0) {
+            throw new RuntimeException("byteOffset must be a multiple of the element size, byteOffset=" + byteOffset + " bytesPerElement=" + bytesPerElement);
         }
     }
 
@@ -71,22 +91,22 @@
 
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
     public static Object buffer(final Object self) {
-        return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).buffer;
+        return ((ArrayBufferView)self).buffer;
     }
 
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
-    public static Object byteOffset(final Object self) {
-        return ((ArrayDataImpl)((ArrayBufferView)self).getArray()).byteOffset;
+    public static int byteOffset(final Object self) {
+        return ((ArrayBufferView)self).byteOffset;
     }
 
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
-    public static Object byteLength(final Object self) {
+    public static int byteLength(final Object self) {
         final ArrayBufferView view = (ArrayBufferView)self;
-        return ((ArrayDataImpl)view.getArray()).elementLength * view.bytesPerElement();
+        return ((TypedArrayData<?>)view.getArray()).getElementLength() * view.bytesPerElement();
     }
 
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
-    public static Object length(final Object self) {
+    public static int length(final Object self) {
         return ((ArrayBufferView)self).elementLength();
     }
 
@@ -96,182 +116,7 @@
     }
 
     private int elementLength() {
-        return ((ArrayDataImpl)getArray()).elementLength;
-    }
-
-    protected static abstract class ArrayDataImpl extends ArrayData {
-        protected final NativeArrayBuffer buffer;
-        protected final int byteOffset;
-        private final int elementLength;
-
-        protected ArrayDataImpl(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(elementLength);
-            this.buffer = buffer;
-            this.byteOffset = byteOffset;
-            this.elementLength = elementLength;
-        }
-
-        @Override
-        public ArrayData copy() {
-            throw new UnsupportedOperationException();   // Not used for ArrayBuffers
-        }
-
-        @Override
-        public Object[] asObjectArray() {
-            final Object[] array = new Object[elementLength];
-            for (int i = 0; i < elementLength; i++) {
-                array[i] = getObjectImpl(i);
-            }
-            return array;
-        }
-
-        @Override
-        public ArrayData ensure(final long safeIndex) {
-            return this;
-        }
-
-        @Override
-        public void setLength(final long length) {
-            //empty?
-            //TODO is this right?
-        }
-
-        @Override
-        public ArrayData shrink(final long newLength) {
-            return this;
-        }
-
-        @Override
-        public ArrayData set(final int index, final Object value, final boolean strict) {
-            if (has(index)) {
-                setImpl(index, value);
-            }
-            return this;
-        }
-
-        @Override
-        public ArrayData set(final int index, final int value, final boolean strict) {
-            if (has(index)) {
-                setImpl(index, value);
-            }
-            return this;
-        }
-
-        @Override
-        public ArrayData set(final int index, final long value, final boolean strict) {
-            if (has(index)) {
-                setImpl(index, value);
-            }
-            return this;
-        }
-
-        @Override
-        public ArrayData set(final int index, final double value, final boolean strict) {
-            if (has(index)) {
-                setImpl(index, value);
-            }
-            return this;
-        }
-
-        @Override
-        public int getInt(final int index) {
-            return getIntImpl(index);
-        }
-
-        @Override
-        public long getLong(final int index) {
-            return getLongImpl(index);
-        }
-
-        @Override
-        public double getDouble(final int index) {
-            return getDoubleImpl(index);
-        }
-
-        @Override
-        public Object getObject(final int index) {
-            return getObjectImpl(index);
-        }
-
-        @Override
-        public boolean has(final int index) {
-            return index >= 0 && index < elementLength;
-        }
-
-        @Override
-        public boolean canDelete(final int index, final boolean strict) {
-            return false;
-        }
-
-        @Override
-        public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
-            return false;
-        }
-
-        @Override
-        public ArrayData delete(final int index) {
-            return this;
-        }
-
-        @Override
-        public ArrayData delete(final long fromIndex, final long toIndex) {
-            return this;
-        }
-
-        @Override
-        protected ArrayData convert(final Class<?> type) {
-            return this;
-        }
-
-        @Override
-        public void shiftLeft(final int by) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public ArrayData shiftRight(final int by) {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Object pop() {
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public ArrayData slice(final long from, final long to) {
-            throw new UnsupportedOperationException();
-        }
-
-        protected abstract int getIntImpl(int key);
-
-        protected long getLongImpl(final int key) {
-            return getIntImpl(key);
-        }
-
-        protected double getDoubleImpl(final int key) {
-            return getIntImpl(key);
-        }
-
-        protected Object getObjectImpl(final int key) {
-            return getIntImpl(key);
-        }
-
-        protected abstract void setImpl(int key, int value);
-
-        protected void setImpl(final int key, final long value) {
-            setImpl(key, (int)value);
-        }
-
-        protected void setImpl(final int key, final double value) {
-            setImpl(key, JSType.toInt32(value));
-        }
-
-        protected void setImpl(final int key, final Object value) {
-            setImpl(key, JSType.toInt32(value));
-        }
-
-        protected abstract int byteIndex(int index);
+        return ((TypedArrayData<?>)getArray()).getElementLength();
     }
 
     protected static abstract class Factory {
@@ -279,12 +124,12 @@
         final int maxElementLength;
 
         public Factory(final int bytesPerElement) {
-            this.bytesPerElement = bytesPerElement;
+            this.bytesPerElement  = bytesPerElement;
             this.maxElementLength = Integer.MAX_VALUE / bytesPerElement;
         }
 
         public final ArrayBufferView construct(final int elementLength) {
-            if(elementLength > maxElementLength) {
+            if (elementLength > maxElementLength) {
                 throw rangeError("inappropriate.array.buffer.length", JSType.toString(elementLength));
             }
             return construct(new NativeArrayBuffer(elementLength * bytesPerElement), 0, elementLength);
@@ -292,25 +137,39 @@
 
         public abstract ArrayBufferView construct(NativeArrayBuffer buffer, int byteOffset, int elementLength);
 
-        public abstract ArrayData createArrayData(NativeArrayBuffer buffer, int byteOffset, int elementLength);
+        public abstract TypedArrayData<?> createArrayData(ByteBuffer nb, int start, int end);
+
+        public abstract String getClassName();
     }
 
     protected abstract Factory factory();
 
     protected abstract ScriptObject getPrototype(final Global global);
 
+    @Override
+    public final String getClassName() {
+        return factory().getClassName();
+    }
+
     protected boolean isFloatArray() {
         return false;
     }
 
-    protected static ArrayBufferView constructorImpl(final Object[] args, final Factory factory) {
-        final Object arg0 = args.length != 0 ? args[0] : 0;
-        final ArrayBufferView dst;
-        final int length;
+    protected static ArrayBufferView constructorImpl(final boolean newObj, final Object[] args, final Factory factory) {
+        final Object          arg0 = args.length != 0 ? args[0] : 0;
+        final ArrayBufferView dest;
+        final int             length;
+
+        if (!newObj) {
+            throw typeError("constructor.requires.new", factory.getClassName());
+        }
+
+
         if (arg0 instanceof NativeArrayBuffer) {
             // Constructor(ArrayBuffer buffer, optional unsigned long byteOffset, optional unsigned long length)
-            final NativeArrayBuffer buffer = (NativeArrayBuffer) arg0;
-            final int byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
+            final NativeArrayBuffer buffer     = (NativeArrayBuffer)arg0;
+            final int               byteOffset = args.length > 1 ? JSType.toInt32(args[1]) : 0;
+
             if (args.length > 2) {
                 length = JSType.toInt32(args[2]);
             } else {
@@ -319,27 +178,30 @@
                 }
                 length = (buffer.getByteLength() - byteOffset) / factory.bytesPerElement;
             }
+
             return factory.construct(buffer, byteOffset, length);
         } else if (arg0 instanceof ArrayBufferView) {
             // Constructor(TypedArray array)
             length = ((ArrayBufferView)arg0).elementLength();
-            dst = factory.construct(length);
+            dest   = factory.construct(length);
         } else if (arg0 instanceof NativeArray) {
             // Constructor(type[] array)
             length = lengthToInt(((NativeArray) arg0).getArray().length());
-            dst = factory.construct(length);
+            dest   = factory.construct(length);
         } else {
-            // Constructor(unsigned long length)
-            length = lengthToInt(JSType.toInt64(arg0));
+            // Constructor(unsigned long length). Treating infinity as 0 is a special case for ArrayBufferView.
+            final double dlen = JSType.toNumber(arg0);
+            length = lengthToInt(Double.isInfinite(dlen) ? 0L : JSType.toLong(dlen));
             return factory.construct(length);
         }
 
-        copyElements(dst, length, (ScriptObject)arg0, 0);
-        return dst;
+        copyElements(dest, length, (ScriptObject)arg0, 0);
+
+        return dest;
     }
 
     protected static Object setImpl(final Object self, final Object array, final Object offset0) {
-        final ArrayBufferView dest = ((ArrayBufferView)self);
+        final ArrayBufferView dest = (ArrayBufferView)self;
         final int length;
         if (array instanceof ArrayBufferView) {
             // void set(TypedArray array, optional unsigned long offset)
@@ -351,7 +213,7 @@
             throw new RuntimeException("argument is not of array type");
         }
 
-        final ScriptObject source = (ScriptObject) array;
+        final ScriptObject source = (ScriptObject)array;
         final int offset = JSType.toInt32(offset0); // default=0
 
         if (dest.elementLength() < length + offset || offset < 0) {
@@ -366,11 +228,11 @@
     private static void copyElements(final ArrayBufferView dest, final int length, final ScriptObject source, final int offset) {
         if (!dest.isFloatArray()) {
             for (int i = 0, j = offset; i < length; i++, j++) {
-                dest.set(j, source.getInt(i), false);
+                dest.set(j, source.getInt(i, INVALID_PROGRAM_POINT), false);
             }
         } else {
             for (int i = 0, j = offset; i < length; i++, j++) {
-                dest.set(j, source.getDouble(i), false);
+                dest.set(j, source.getDouble(i, INVALID_PROGRAM_POINT), false);
             }
         }
     }
@@ -379,15 +241,39 @@
         if (length > Integer.MAX_VALUE || length < 0) {
             throw rangeError("inappropriate.array.buffer.length", JSType.toString(length));
         }
-        return (int) (length & Integer.MAX_VALUE);
+        return (int)(length & Integer.MAX_VALUE);
     }
 
     protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
-        final ArrayBufferView arrayView = ((ArrayBufferView)self);
-        final int elementLength = arrayView.elementLength();
-        final int begin = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
-        final int end = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
-        final ArrayDataImpl arrayData = (ArrayDataImpl)arrayView.getArray();
-        return arrayView.factory().construct(arrayData.buffer, arrayData.byteIndex(begin), Math.max(end - begin, 0));
+        final ArrayBufferView arrayView       = (ArrayBufferView)self;
+        final int             byteOffset      = arrayView.byteOffset;
+        final int             bytesPerElement = arrayView.bytesPerElement();
+        final int             elementLength   = arrayView.elementLength();
+        final int             begin           = NativeArrayBuffer.adjustIndex(JSType.toInt32(begin0), elementLength);
+        final int             end             = NativeArrayBuffer.adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : elementLength, elementLength);
+        final int             length          = Math.max(end - begin, 0);
+
+        assert byteOffset % bytesPerElement == 0;
+
+        //second is byteoffset
+        return arrayView.factory().construct(arrayView.buffer, begin * bytesPerElement + byteOffset, length);
+    }
+
+    @Override
+    protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+        final GuardedInvocation inv = getArray().findFastGetIndexMethod(getArray().getClass(), desc, request);
+        if (inv != null) {
+            return inv;
+        }
+        return super.findGetIndexMethod(desc, request);
+    }
+
+    @Override
+    protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+        final GuardedInvocation inv = getArray().findFastSetIndexMethod(getArray().getClass(), desc, request);
+        if (inv != null) {
+            return inv;
+        }
+        return super.findSetIndexMethod(desc, request);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java b/nashorn/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
index d0e5b98..333790f 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/BoundScriptFunctionImpl.java
@@ -38,7 +38,7 @@
 final class BoundScriptFunctionImpl extends ScriptFunctionImpl {
     private final ScriptFunction targetFunction;
 
-    BoundScriptFunctionImpl(ScriptFunctionData data, ScriptFunction targetFunction) {
+    BoundScriptFunctionImpl(final ScriptFunctionData data, final ScriptFunction targetFunction) {
         super(data, Global.instance());
         setPrototype(ScriptRuntime.UNDEFINED);
         this.targetFunction = targetFunction;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
index e117c7e..2472293 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/DataPropertyDescriptor.java
@@ -197,6 +197,11 @@
     }
 
     @Override
+    public String toString() {
+        return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + " writable=" + writable + " value=" + value + "}]";
+    }
+
+    @Override
     public int hashCode() {
         int hash = 5;
         hash = 43 * hash + Objects.hashCode(this.configurable);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
index 19cc8b6..39d0b3e 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/GenericPropertyDescriptor.java
@@ -176,6 +176,11 @@
     }
 
     @Override
+    public String toString() {
+        return '[' + getClass().getSimpleName() + " {configurable=" + configurable + " enumerable=" + enumerable + "}]";
+    }
+
+    @Override
     public int hashCode() {
         int hash = 7;
         hash = 97 * hash + Objects.hashCode(this.configurable);
diff --git a/nashorn/src/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk/nashorn/internal/objects/Global.java
index 0614c4b..1fe7cdb 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/Global.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java
@@ -25,28 +25,42 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
 import java.lang.reflect.Field;
 import java.util.Arrays;
-import java.util.List;
+import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicReference;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.api.scripting.ClassFilter;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.codegen.ApplySpecialization;
+import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.runtime.ConsString;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.GlobalConstants;
 import jdk.nashorn.internal.runtime.GlobalFunctions;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.NativeJavaPackage;
@@ -55,7 +69,6 @@
 import jdk.nashorn.internal.runtime.Scope;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptFunction;
-import jdk.nashorn.internal.runtime.ScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.ScriptingFunctions;
@@ -70,9 +83,39 @@
  */
 @ScriptClass("Global")
 public final class Global extends ScriptObject implements Scope {
+    // Placeholder value used in place of a location property (__FILE__, __DIR__, __LINE__)
+    private static final Object LOCATION_PROPERTY_PLACEHOLDER = new Object();
     private final InvokeByName TO_STRING = new InvokeByName("toString", ScriptObject.class);
     private final InvokeByName VALUE_OF  = new InvokeByName("valueOf",  ScriptObject.class);
 
+    /**
+     * Optimistic builtin names that require switchpoint invalidation
+     * upon assignment. Overly conservative, but works for now, to avoid
+     * any complicated scope checks and especially heavy weight guards
+     * like
+     *
+     * <pre>
+     *     public boolean setterGuard(final Object receiver) {
+     *         final Global          global = Global.instance();
+     *         final ScriptObject    sobj   = global.getFunctionPrototype();
+     *         final Object          apply  = sobj.get("apply");
+     *         return apply == receiver;
+     *     }
+     * </pre>
+     *
+     * Naturally, checking for builtin classes like NativeFunction is cheaper,
+     * it's when you start adding property checks for said builtins you have
+     * problems with guard speed.
+     */
+    public final Map<String, SwitchPoint> optimisticFunctionMap;
+
+    /** Name invalidator for things like call/apply */
+    public static final Call BOOTSTRAP = staticCall(MethodHandles.lookup(), Global.class, "invalidateNameBootstrap", CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class);
+
+    /** Nashorn extension: arguments array */
+    @Property(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE)
+    public Object arguments;
+
     /** ECMA 15.1.2.2 parseInt (string , radix) */
     @Property(attributes = Attribute.NOT_ENUMERABLE)
     public Object parseInt;
@@ -135,11 +178,11 @@
 
     /** Value property NaN of the Global Object - ECMA 15.1.1.1 NaN */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object NaN = Double.NaN;
+    public final double NaN = Double.NaN;
 
     /** Value property Infinity of the Global Object - ECMA 15.1.1.2 Infinity */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public final Object Infinity = Double.POSITIVE_INFINITY;
+    public final double Infinity = Double.POSITIVE_INFINITY;
 
     /** Value property Undefined of the Global Object - ECMA 15.1.1.3 Undefined */
     @Property(attributes = Attribute.NON_ENUMERABLE_CONSTANT)
@@ -303,15 +346,15 @@
 
     /** Nashorn extension: current script's file name */
     @Property(name = "__FILE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public Object __FILE__;
+    public final Object __FILE__ = LOCATION_PROPERTY_PLACEHOLDER;
 
     /** Nashorn extension: current script's directory */
     @Property(name = "__DIR__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public Object __DIR__;
+    public final Object __DIR__ = LOCATION_PROPERTY_PLACEHOLDER;
 
     /** Nashorn extension: current source line number being executed */
     @Property(name = "__LINE__", attributes = Attribute.NON_ENUMERABLE_CONSTANT)
-    public Object __LINE__;
+    public final Object __LINE__ = LOCATION_PROPERTY_PLACEHOLDER;
 
     /** Used as Date.prototype's default value */
     public NativeDate   DEFAULT_DATE;
@@ -352,19 +395,19 @@
     private ScriptObject   builtinJavafx;
     private ScriptObject   builtinJavax;
     private ScriptObject   builtinOrg;
-    private ScriptObject   builtinJavaImporter;
+    private ScriptFunction builtinJavaImporter;
     private ScriptObject   builtinJavaApi;
-    private ScriptObject   builtinArrayBuffer;
-    private ScriptObject   builtinDataView;
-    private ScriptObject   builtinInt8Array;
-    private ScriptObject   builtinUint8Array;
-    private ScriptObject   builtinUint8ClampedArray;
-    private ScriptObject   builtinInt16Array;
-    private ScriptObject   builtinUint16Array;
-    private ScriptObject   builtinInt32Array;
-    private ScriptObject   builtinUint32Array;
-    private ScriptObject   builtinFloat32Array;
-    private ScriptObject   builtinFloat64Array;
+    private ScriptFunction builtinArrayBuffer;
+    private ScriptFunction builtinDataView;
+    private ScriptFunction builtinInt8Array;
+    private ScriptFunction builtinUint8Array;
+    private ScriptFunction builtinUint8ClampedArray;
+    private ScriptFunction builtinInt16Array;
+    private ScriptFunction builtinUint16Array;
+    private ScriptFunction builtinInt32Array;
+    private ScriptFunction builtinUint32Array;
+    private ScriptFunction builtinFloat32Array;
+    private ScriptFunction builtinFloat64Array;
 
     /*
      * ECMA section 13.2.3 The [[ThrowTypeError]] Function Object
@@ -377,12 +420,16 @@
     // Used to store the last RegExp result to support deprecated RegExp constructor properties
     private RegExpResult lastRegExpResult;
 
-    private static final MethodHandle EVAL              = findOwnMH("eval",              Object.class, Object.class, Object.class);
-    private static final MethodHandle PRINT             = findOwnMH("print",             Object.class, Object.class, Object[].class);
-    private static final MethodHandle PRINTLN           = findOwnMH("println",           Object.class, Object.class, Object[].class);
-    private static final MethodHandle LOAD              = findOwnMH("load",              Object.class, Object.class, Object.class);
-    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH("loadWithNewGlobal", Object.class, Object.class, Object[].class);
-    private static final MethodHandle EXIT              = findOwnMH("exit",              Object.class, Object.class, Object.class);
+    private static final MethodHandle EVAL              = findOwnMH_S("eval",                Object.class, Object.class, Object.class);
+    private static final MethodHandle NO_SUCH_PROPERTY  = findOwnMH_S(NO_SUCH_PROPERTY_NAME, Object.class, Object.class, Object.class);
+    private static final MethodHandle PRINT             = findOwnMH_S("print",               Object.class, Object.class, Object[].class);
+    private static final MethodHandle PRINTLN           = findOwnMH_S("println",             Object.class, Object.class, Object[].class);
+    private static final MethodHandle LOAD              = findOwnMH_S("load",                Object.class, Object.class, Object.class);
+    private static final MethodHandle LOADWITHNEWGLOBAL = findOwnMH_S("loadWithNewGlobal",   Object.class, Object.class, Object[].class);
+    private static final MethodHandle EXIT              = findOwnMH_S("exit",                Object.class, Object.class, Object.class);
+
+    /** Invalidate a reserved name, such as "apply" or "call" if assigned */
+    public MethodHandle INVALIDATE_RESERVED_NAME = MH.bindTo(findOwnMH_V("invalidateReservedName", void.class, String.class), this);
 
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
@@ -390,6 +437,23 @@
     // context to which this global belongs to
     private final Context context;
 
+    // current ScriptContext to use - can be null.
+    private ScriptContext scontext;
+    // associated Property object for "context" property.
+    private jdk.nashorn.internal.runtime.Property scontextProperty;
+
+    /**
+     * Set the current script context
+     * @param scontext script context
+     */
+    public void setScriptContext(final ScriptContext scontext) {
+        this.scontext = scontext;
+        scontextProperty.setValue(this, this, scontext, false);
+    }
+
+    // global constants for this global - they can be replaced with MethodHandle.constant until invalidated
+    private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
+
     @Override
     protected Context getContext() {
         return context;
@@ -407,12 +471,7 @@
         // null check on context
         context.getClass();
 
-        /*
-         * Duplicate global's map and use it. This way the initial Map filled
-         * by nasgen (referenced from static field in this class) is retained
-         * 'as is' (as that one is process wide singleton.
-         */
-        return $nasgenmap$.duplicate();
+        return $nasgenmap$;
     }
 
     /**
@@ -424,6 +483,12 @@
         super(checkAndGetMap(context));
         this.context = context;
         this.setIsScope();
+        this.optimisticFunctionMap = new HashMap<>();
+        //we can only share one instance of Global constants between globals, or we consume way too much
+        //memory - this is good enough for most programs
+        while (gcsInstance.get() == null) {
+            gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class)));
+        }
     }
 
     /**
@@ -432,11 +497,32 @@
      * @return the global singleton
      */
     public static Global instance() {
-        Global global = Context.getGlobal();
+        final Global global = Context.getGlobal();
         global.getClass(); // null check
         return global;
     }
 
+    private static Global instanceFrom(final Object self) {
+        return self instanceof Global? (Global)self : instance();
+    }
+
+    /**
+     * Return the global constants map for fields that
+     * can be accessed as MethodHandle.constant
+     * @return constant map
+     */
+    public static GlobalConstants getConstants() {
+        return gcsInstance.get();
+    }
+
+    /**
+     * Check if we have a Global instance
+     * @return true if one exists
+     */
+    public static boolean hasInstance() {
+        return Context.getGlobal() != null;
+    }
+
     /**
      * Script access to {@link ScriptEnvironment}
      *
@@ -458,6 +544,14 @@
     // Runtime interface to Global
 
     /**
+     * Is there a class filter in the current Context?
+     * @return class filter
+     */
+    public ClassFilter getClassFilter() {
+        return context.getClassFilter();
+    }
+
+    /**
      * Is this global of the given Context?
      * @param ctxt the context
      * @return true if this global belongs to the given Context
@@ -478,28 +572,16 @@
      * Initialize standard builtin objects like "Object", "Array", "Function" etc.
      * as well as our extension builtin objects like "Java", "JSAdapter" as properties
      * of the global scope object.
+     *
+     * @param engine ScriptEngine to initialize
      */
-    public void initBuiltinObjects() {
+    public void initBuiltinObjects(final ScriptEngine engine) {
         if (this.builtinObject != null) {
             // already initialized, just return
             return;
         }
 
-        init();
-    }
-
-    /**
-     * Create a new ScriptFunction object
-     *
-     * @param name   function name
-     * @param handle invocation handle for function
-     * @param scope  the scope
-     * @param strict are we in strict mode
-     *
-     * @return new script function
-     */
-    public ScriptFunction newScriptFunction(final String name, final MethodHandle handle, final ScriptObject scope, final boolean strict) {
-        return new ScriptFunctionImpl(name, handle, scope, null, strict ? ScriptFunctionData.IS_STRICT_CONSTRUCTOR : ScriptFunctionData.IS_CONSTRUCTOR);
+        init(engine);
     }
 
     /**
@@ -537,7 +619,7 @@
      *
      * @return guarded invocation
      */
-    public GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
+    public static GuardedInvocation primitiveLookup(final LinkRequest request, final Object self) {
         if (self instanceof String || self instanceof ConsString) {
             return NativeString.lookupPrimitive(request, self);
         } else if (self instanceof Number) {
@@ -729,6 +811,7 @@
      * @param value of the data property
      * @param configurable is the property configurable?
      * @param enumerable is the property enumerable?
+     * @param writable is the property writable?
      * @return newly created DataPropertyDescriptor object
      */
     public PropertyDescriptor newDataDescriptor(final Object value, final boolean configurable, final boolean enumerable, final boolean writable) {
@@ -758,7 +841,6 @@
         return desc;
     }
 
-
     private static <T> T getLazilyCreatedValue(final Object key, final Callable<T> creator, final Map<Object, T> map) {
         final T obj = map.get(key);
         if (obj != null) {
@@ -800,6 +882,32 @@
     }
 
     /**
+     * Hook to search missing variables in ScriptContext if available
+     * @param self used to detect if scope call or not (this function is 'strict')
+     * @param name name of the variable missing
+     * @return value of the missing variable or undefined (or TypeError for scope search)
+     */
+    public static Object __noSuchProperty__(final Object self, final Object name) {
+        final Global global = Global.instance();
+        final ScriptContext sctxt = global.scontext;
+        final String nameStr = name.toString();
+
+        if (sctxt != null) {
+            final int scope = sctxt.getAttributesScope(nameStr);
+            if (scope != -1) {
+                return ScriptObjectMirror.unwrap(sctxt.getAttribute(nameStr, scope), global);
+            }
+        }
+
+        if (self == UNDEFINED) {
+            // scope access and so throw ReferenceError
+            throw referenceError(global, "not.defined", nameStr);
+        }
+
+        return UNDEFINED;
+    }
+
+    /**
      * This is the eval used when 'indirect' eval call is made.
      *
      * var global = this;
@@ -811,7 +919,7 @@
      * @return the result of eval
      */
     public static Object eval(final Object self, final Object str) {
-        return directEval(self, str, UNDEFINED, UNDEFINED, UNDEFINED);
+        return directEval(self, str, UNDEFINED, UNDEFINED, false);
     }
 
     /**
@@ -827,14 +935,14 @@
      *
      * This is directly invoked from generated when eval(code) is called in user code
      */
-    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final Object strict) {
+    public static Object directEval(final Object self, final Object str, final Object callThis, final Object location, final boolean strict) {
         if (!(str instanceof String || str instanceof ConsString)) {
             return str;
         }
-        final Global global = Global.instance();
-        final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+        final Global global = Global.instanceFrom(self);
+        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
 
-        return global.getContext().eval(scope, str.toString(), callThis, location, Boolean.TRUE.equals(strict));
+        return global.getContext().eval(scope, str.toString(), callThis, location, strict, true);
     }
 
     /**
@@ -846,7 +954,7 @@
      * @return result of print (undefined)
      */
     public static Object print(final Object self, final Object... objects) {
-        return printImpl(false, objects);
+        return Global.instanceFrom(self).printImpl(false, objects);
     }
 
     /**
@@ -858,7 +966,7 @@
      * @return result of println (undefined)
      */
     public static Object println(final Object self, final Object... objects) {
-        return printImpl(true, objects);
+        return Global.instanceFrom(self).printImpl(true, objects);
     }
 
     /**
@@ -872,8 +980,8 @@
      * @throws IOException if source could not be read
      */
     public static Object load(final Object self, final Object source) throws IOException {
-        final Global global = Global.instance();
-        final ScriptObject scope = (self instanceof ScriptObject) ? (ScriptObject)self : global;
+        final Global global = Global.instanceFrom(self);
+        final ScriptObject scope = self instanceof ScriptObject ? (ScriptObject)self : global;
         return global.getContext().load(scope, source);
     }
 
@@ -888,7 +996,7 @@
      * @throws IOException if source could not be read
      */
     public static Object loadWithNewGlobal(final Object self, final Object...args) throws IOException {
-        final Global global = Global.instance();
+        final Global global = Global.instanceFrom(self);
         final int length = args.length;
         final boolean hasArgs = 0 < length;
         final Object from = hasArgs ? args[0] : UNDEFINED;
@@ -903,7 +1011,7 @@
      * @param self  self reference
      * @param code  exit code
      *
-     * @return undefined (will never be reacheD)
+     * @return undefined (will never be reached)
      */
     public static Object exit(final Object self, final Object code) {
         System.exit(JSType.toInt32(code));
@@ -1457,6 +1565,26 @@
     }
 
     /**
+     * Called from generated to replace a location property placeholder with the actual location property value.
+     *
+     * @param  placeholder the value tested for being a placeholder for a location property
+     * @param  locationProperty the actual value for the location property
+     * @return locationProperty if placeholder is indeed a placeholder for a location property, the placeholder otherwise
+     */
+    public static Object replaceLocationPropertyPlaceholder(final Object placeholder, final Object locationProperty) {
+        return isLocationPropertyPlaceholder(placeholder) ? locationProperty : placeholder;
+    }
+
+    /**
+     * Called from runtime internals to check if the passed value is a location property placeholder.
+     * @param  placeholder the value tested for being a placeholder for a location property
+     * @return true if the value is a placeholder, false otherwise.
+     */
+    public static boolean isLocationPropertyPlaceholder(final Object placeholder) {
+        return placeholder == LOCATION_PROPERTY_PLACEHOLDER;
+    }
+
+    /**
      * Create a new RegExp object.
      *
      * @param expression Regular expression.
@@ -1494,11 +1622,13 @@
      * not the case
      *
      * @param obj and object to check
+     * @return the script object
      */
-    public static void checkObject(final Object obj) {
+    public static ScriptObject checkObject(final Object obj) {
         if (!(obj instanceof ScriptObject)) {
             throw typeError("not.an.object", ScriptRuntime.safeToString(obj));
         }
+        return (ScriptObject)obj;
     }
 
     /**
@@ -1533,7 +1663,7 @@
         splitState = state;
     }
 
-    private void init() {
+    private void init(final ScriptEngine engine) {
         assert Context.getGlobal() == this : "this global is not set as current";
 
         final ScriptEnvironment env = getContext().getEnv();
@@ -1547,7 +1677,8 @@
         // initialize global function properties
         this.eval = this.builtinEval = ScriptFunctionImpl.makeFunction("eval", EVAL);
 
-        this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT);
+        this.parseInt           = ScriptFunctionImpl.makeFunction("parseInt",   GlobalFunctions.PARSEINT,
+                new MethodHandle[] { GlobalFunctions.PARSEINT_OI, GlobalFunctions.PARSEINT_O });
         this.parseFloat         = ScriptFunctionImpl.makeFunction("parseFloat", GlobalFunctions.PARSEFLOAT);
         this.isNaN              = ScriptFunctionImpl.makeFunction("isNaN",      GlobalFunctions.IS_NAN);
         this.isFinite           = ScriptFunctionImpl.makeFunction("isFinite",   GlobalFunctions.IS_FINITE);
@@ -1564,15 +1695,15 @@
         this.quit               = ScriptFunctionImpl.makeFunction("quit",       EXIT);
 
         // built-in constructors
-        this.builtinArray     = (ScriptFunction)initConstructor("Array");
-        this.builtinBoolean   = (ScriptFunction)initConstructor("Boolean");
-        this.builtinDate      = (ScriptFunction)initConstructor("Date");
-        this.builtinJSON      = initConstructor("JSON");
-        this.builtinJSAdapter = (ScriptFunction)initConstructor("JSAdapter");
-        this.builtinMath      = initConstructor("Math");
-        this.builtinNumber    = (ScriptFunction)initConstructor("Number");
-        this.builtinRegExp    = (ScriptFunction)initConstructor("RegExp");
-        this.builtinString    = (ScriptFunction)initConstructor("String");
+        this.builtinArray     = initConstructor("Array", ScriptFunction.class);
+        this.builtinBoolean   = initConstructor("Boolean", ScriptFunction.class);
+        this.builtinDate      = initConstructor("Date", ScriptFunction.class);
+        this.builtinJSON      = initConstructor("JSON", ScriptObject.class);
+        this.builtinJSAdapter = initConstructor("JSAdapter", ScriptFunction.class);
+        this.builtinMath      = initConstructor("Math", ScriptObject.class);
+        this.builtinNumber    = initConstructor("Number", ScriptFunction.class);
+        this.builtinRegExp    = initConstructor("RegExp", ScriptFunction.class);
+        this.builtinString    = initConstructor("String", ScriptFunction.class);
 
         // initialize String.prototype.length to 0
         // add String.prototype.length
@@ -1632,25 +1763,28 @@
 
         copyBuiltins();
 
-        // initialized with strings so that typeof will work as expected.
-        this.__FILE__ = "";
-        this.__DIR__  = "";
-        this.__LINE__ = 0.0;
-
         // expose script (command line) arguments as "arguments" property of global
-        final List<String> arguments = env.getArguments();
-        final Object argsObj = wrapAsObject(arguments.toArray());
-
-        addOwnProperty("arguments", Attribute.NOT_ENUMERABLE, argsObj);
+        arguments = wrapAsObject(env.getArguments().toArray());
         if (env._scripting) {
             // synonym for "arguments" in scripting mode
-            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, argsObj);
+            addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
+        }
+
+        if (engine != null) {
+            final int NOT_ENUMERABLE_NOT_CONFIG = Attribute.NOT_ENUMERABLE | Attribute.NOT_CONFIGURABLE;
+            scontextProperty = addOwnProperty("context", NOT_ENUMERABLE_NOT_CONFIG, null);
+            addOwnProperty("engine", NOT_ENUMERABLE_NOT_CONFIG, engine);
+            // default file name
+            addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
+            // __noSuchProperty__ hook for ScriptContext search of missing variables
+            final ScriptFunction noSuchProp = ScriptFunctionImpl.makeStrictFunction(NO_SUCH_PROPERTY_NAME, NO_SUCH_PROPERTY);
+            addOwnProperty(NO_SUCH_PROPERTY_NAME, Attribute.NOT_ENUMERABLE, noSuchProp);
         }
     }
 
     private void initErrorObjects() {
         // Error objects
-        this.builtinError = (ScriptFunction)initConstructor("Error");
+        this.builtinError = initConstructor("Error", ScriptFunction.class);
         final ScriptObject errorProto = getErrorPrototype();
 
         // Nashorn specific accessors on Error.prototype - stack, lineNumber, columnNumber and fileName
@@ -1683,12 +1817,12 @@
     }
 
     private ScriptFunction initErrorSubtype(final String name, final ScriptObject errorProto) {
-        final ScriptObject cons = initConstructor(name);
+        final ScriptFunction cons = initConstructor(name, ScriptFunction.class);
         final ScriptObject prototype = ScriptFunction.getPrototype(cons);
         prototype.set(NativeError.NAME, name, false);
         prototype.set(NativeError.MESSAGE, "", false);
         prototype.setInitialProto(errorProto);
-        return (ScriptFunction)cons;
+        return cons;
     }
 
     private void initJavaAccess() {
@@ -1700,8 +1834,8 @@
         this.builtinJavafx = new NativeJavaPackage("javafx", objectProto);
         this.builtinJavax = new NativeJavaPackage("javax", objectProto);
         this.builtinOrg = new NativeJavaPackage("org", objectProto);
-        this.builtinJavaImporter = initConstructor("JavaImporter");
-        this.builtinJavaApi = initConstructor("Java");
+        this.builtinJavaImporter = initConstructor("JavaImporter", ScriptFunction.class);
+        this.builtinJavaApi = initConstructor("Java", ScriptObject.class);
     }
 
     private void initScripting(final ScriptEnvironment scriptEnv) {
@@ -1744,7 +1878,7 @@
     }
 
     private static void copyOptions(final ScriptObject options, final ScriptEnvironment scriptEnv) {
-        for (Field f : scriptEnv.getClass().getFields()) {
+        for (final Field f : scriptEnv.getClass().getFields()) {
             try {
                 options.set(f.getName(), f.get(scriptEnv), false);
             } catch (final IllegalArgumentException | IllegalAccessException exp) {
@@ -1754,17 +1888,17 @@
     }
 
     private void initTypedArray() {
-        this.builtinArrayBuffer       = initConstructor("ArrayBuffer");
-        this.builtinDataView          = initConstructor("DataView");
-        this.builtinInt8Array         = initConstructor("Int8Array");
-        this.builtinUint8Array        = initConstructor("Uint8Array");
-        this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray");
-        this.builtinInt16Array        = initConstructor("Int16Array");
-        this.builtinUint16Array       = initConstructor("Uint16Array");
-        this.builtinInt32Array        = initConstructor("Int32Array");
-        this.builtinUint32Array       = initConstructor("Uint32Array");
-        this.builtinFloat32Array      = initConstructor("Float32Array");
-        this.builtinFloat64Array      = initConstructor("Float64Array");
+        this.builtinArrayBuffer       = initConstructor("ArrayBuffer", ScriptFunction.class);
+        this.builtinDataView          = initConstructor("DataView", ScriptFunction.class);
+        this.builtinInt8Array         = initConstructor("Int8Array", ScriptFunction.class);
+        this.builtinUint8Array        = initConstructor("Uint8Array", ScriptFunction.class);
+        this.builtinUint8ClampedArray = initConstructor("Uint8ClampedArray", ScriptFunction.class);
+        this.builtinInt16Array        = initConstructor("Int16Array", ScriptFunction.class);
+        this.builtinUint16Array       = initConstructor("Uint16Array", ScriptFunction.class);
+        this.builtinInt32Array        = initConstructor("Int32Array", ScriptFunction.class);
+        this.builtinUint32Array       = initConstructor("Uint32Array", ScriptFunction.class);
+        this.builtinFloat32Array      = initConstructor("Float32Array", ScriptFunction.class);
+        this.builtinFloat64Array      = initConstructor("Float64Array", ScriptFunction.class);
     }
 
     private void copyBuiltins() {
@@ -1809,20 +1943,20 @@
     }
 
     private void initDebug() {
-        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug"));
+        this.addOwnProperty("Debug", Attribute.NOT_ENUMERABLE, initConstructor("Debug", ScriptObject.class));
     }
 
-    @SuppressWarnings("resource")
-    private static Object printImpl(final boolean newLine, final Object... objects) {
-        final PrintWriter out = Global.getEnv().getOut();
+    private Object printImpl(final boolean newLine, final Object... objects) {
+        @SuppressWarnings("resource")
+        final PrintWriter out = scontext != null? new PrintWriter(scontext.getWriter()) : getContext().getEnv().getOut();
         final StringBuilder sb = new StringBuilder();
 
-        for (final Object object : objects) {
+        for (final Object obj : objects) {
             if (sb.length() != 0) {
                 sb.append(' ');
             }
 
-            sb.append(JSType.toString(object));
+            sb.append(JSType.toString(obj));
         }
 
         // Print all at once to ensure thread friendly result.
@@ -1841,7 +1975,7 @@
      * These classes are generated by nasgen tool and so we have to use
      * reflection to load and create new instance of these classes.
      */
-    private ScriptObject initConstructor(final String name) {
+    private <T extends ScriptObject> T initConstructor(final String name, final Class<T> clazz) {
         try {
             // Assuming class name pattern for built-in JS constructors.
             final StringBuilder sb = new StringBuilder("jdk.nashorn.internal.objects.");
@@ -1850,8 +1984,8 @@
             sb.append(name);
             sb.append("$Constructor");
 
-            final Class<?>     funcClass = Class.forName(sb.toString());
-            final ScriptObject res       = (ScriptObject)funcClass.newInstance();
+            final Class<?> funcClass = Class.forName(sb.toString());
+            final T res = clazz.cast(funcClass.newInstance());
 
             if (res instanceof ScriptFunction) {
                 // All global constructor prototypes are not-writable,
@@ -1864,8 +1998,8 @@
                 res.setInitialProto(getObjectPrototype());
             }
 
+            res.setIsBuiltin();
             return res;
-
         } catch (final ClassNotFoundException | InstantiationException | IllegalAccessException e) {
             throw new RuntimeException(e);
         }
@@ -1879,10 +2013,10 @@
     // to play with object references carefully!!
     private void initFunctionAndObject() {
         // First-n-foremost is Function
-        this.builtinFunction = (ScriptFunction)initConstructor("Function");
+        this.builtinFunction      = initConstructor("Function", ScriptFunction.class);
 
         // create global anonymous function
-        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction(this);
+        final ScriptFunction anon = ScriptFunctionImpl.newAnonymousFunction();
         // need to copy over members of Function.prototype to anon function
         anon.addBoundProperties(getFunctionPrototype());
 
@@ -1901,7 +2035,7 @@
         typeErrorThrower.preventExtensions();
 
         // now initialize Object
-        this.builtinObject = (ScriptFunction)initConstructor("Object");
+        this.builtinObject = initConstructor("Object", ScriptFunction.class);
         final ScriptObject ObjectPrototype = getObjectPrototype();
         // Object.getPrototypeOf(Function.prototype) === Object.prototype
         anon.setInitialProto(ObjectPrototype);
@@ -1912,7 +2046,6 @@
         final ScriptFunction setProto = ScriptFunctionImpl.makeFunction("setProto", NativeObject.SET__PROTO__);
         ObjectPrototype.addOwnProperty("__proto__", Attribute.NOT_ENUMERABLE, getProto, setProto);
 
-
         // Function valued properties of Function.prototype were not properly
         // initialized. Because, these were created before global.function and
         // global.object were not initialized.
@@ -1946,15 +2079,22 @@
             }
         }
 
+        //make sure apply and call have the same invalidation switchpoint
+        final SwitchPoint sp = new SwitchPoint();
+        optimisticFunctionMap.put("apply", sp);
+        optimisticFunctionMap.put("call", sp);
+        getFunctionPrototype().getProperty("apply").setChangeCallback(sp);
+        getFunctionPrototype().getProperty("call").setChangeCallback(sp);
+
         properties = getObjectPrototype().getMap().getProperties();
+
         for (final jdk.nashorn.internal.runtime.Property property : properties) {
             final Object key   = property.getKey();
-            final Object value = ObjectPrototype.get(key);
-
             if (key.equals("constructor")) {
                 continue;
             }
 
+            final Object value = ObjectPrototype.get(key);
             if (value instanceof ScriptFunction) {
                 final ScriptFunction func = (ScriptFunction)value;
                 final ScriptObject prototype = ScriptFunction.getPrototype(func);
@@ -1965,7 +2105,11 @@
         }
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findVirtual(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
+    }
+
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), Global.class, name, MH.type(rtype, types));
     }
 
@@ -1977,4 +2121,66 @@
         this.lastRegExpResult = regExpResult;
     }
 
+    @Override
+    protected boolean isGlobal() {
+        return true;
+    }
+
+    /**
+     * Check if there is a switchpoint for a reserved name. If there
+     * is, it must be invalidated upon properties with this name
+     * @param name property name
+     * @return switchpoint for invalidating this property, or null if not registered
+     */
+    public SwitchPoint getChangeCallback(final String name) {
+        return optimisticFunctionMap.get(name);
+    }
+
+    /**
+     * Is this a special name, that might be subject to invalidation
+     * on write, such as "apply" or "call"
+     * @param name name to check
+     * @return true if special name
+     */
+    public boolean isSpecialName(final String name) {
+        return getChangeCallback(name) != null;
+    }
+
+    /**
+     * Check if a reserved property name is invalidated
+     * @param name property name
+     * @return true if someone has written to it since Global was instantiated
+     */
+    public boolean isSpecialNameValid(final String name) {
+        final SwitchPoint sp = getChangeCallback(name);
+        return sp != null && !sp.hasBeenInvalidated();
+    }
+
+    /**
+     * Tag a reserved name as invalidated - used when someone writes
+     * to a property with this name - overly conservative, but link time
+     * is too late to apply e.g. apply-&gt;call specialization
+     * @param name property name
+     */
+    public void invalidateReservedName(final String name) {
+        final SwitchPoint sp = getChangeCallback(name);
+        if (sp != null) {
+            getContext().getLogger(ApplySpecialization.class).info("Overwrote special name '" + name +"' - invalidating switchpoint");
+            SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+        }
+    }
+
+    /**
+     * Bootstrapper for invalidating a builtin name
+     * @param lookup lookup
+     * @param name   name to invalidate
+     * @param type   methodhandle type
+     * @return callsite for invalidator
+     */
+    public static CallSite invalidateNameBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type) {
+        final MethodHandle target = MH.insertArguments(Global.instance().INVALIDATE_RESERVED_NAME, 0, name);
+        return new ConstantCallSite(target);
+    }
+
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
index 6f07cb9..776803b 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java
@@ -29,9 +29,9 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
+import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.arrayLikeIterator;
 import static jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator.reverseArrayLikeIterator;
-import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
 
 import java.lang.invoke.MethodHandle;
 import java.util.ArrayList;
@@ -41,7 +41,9 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.concurrent.Callable;
-
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -50,7 +52,10 @@
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Setter;
 import jdk.nashorn.internal.objects.annotations.SpecializedConstructor;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyDescriptor;
 import jdk.nashorn.internal.runtime.PropertyMap;
@@ -81,6 +86,87 @@
     private static final Object CALL_CMP                 = new Object();
     private static final Object TO_LOCALE_STRING         = new Object();
 
+    /*
+     * Constructors.
+     */
+    NativeArray() {
+        this(ArrayData.initialArray());
+    }
+
+    NativeArray(final long length) {
+        // TODO assert valid index in long before casting
+        this(ArrayData.allocate((int)length));
+    }
+
+    NativeArray(final int[] array) {
+        this(ArrayData.allocate(array));
+    }
+
+    NativeArray(final long[] array) {
+        this(ArrayData.allocate(array));
+    }
+
+    NativeArray(final double[] array) {
+        this(ArrayData.allocate(array));
+    }
+
+    NativeArray(final Object[] array) {
+        this(ArrayData.allocate(array.length));
+
+        ArrayData arrayData = this.getArray();
+        arrayData.ensure(array.length - 1);
+
+        for (int index = 0; index < array.length; index++) {
+            final Object value = array[index];
+
+            if (value == ScriptRuntime.EMPTY) {
+                arrayData = arrayData.delete(index);
+            } else {
+                arrayData = arrayData.set(index, value, false);
+            }
+        }
+
+        this.setArray(arrayData);
+    }
+
+    NativeArray(final ArrayData arrayData) {
+        this(arrayData, Global.instance());
+    }
+
+    NativeArray(final ArrayData arrayData, final Global global) {
+        super(global.getArrayPrototype(), $nasgenmap$);
+        setArray(arrayData);
+        setIsArray();
+    }
+
+    @Override
+    protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+        final GuardedInvocation inv = getArray().findFastGetMethod(getArray().getClass(), desc, request, operator);
+        if (inv != null) {
+            return inv;
+        }
+        return super.findGetMethod(desc, request, operator);
+    }
+
+    @Override
+    protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+        final GuardedInvocation inv = getArray().findFastGetIndexMethod(getArray().getClass(), desc, request);
+        if (inv != null) {
+            return inv;
+        }
+        return super.findGetIndexMethod(desc, request);
+    }
+
+    @Override
+    protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
+        final GuardedInvocation inv = getArray().findFastSetIndexMethod(getArray().getClass(), desc, request);
+        if (inv != null) {
+            return inv;
+        }
+
+        return super.findSetIndexMethod(desc, request);
+    }
+
     private static InvokeByName getJOIN() {
         return Global.instance().getInvokeByName(JOIN,
                 new Callable<InvokeByName>() {
@@ -157,59 +243,6 @@
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
 
-    /*
-     * Constructors.
-     */
-    NativeArray() {
-        this(ArrayData.initialArray());
-    }
-
-    NativeArray(final long length) {
-        // TODO assert valid index in long before casting
-        this(ArrayData.allocate((int) length));
-    }
-
-    NativeArray(final int[] array) {
-        this(ArrayData.allocate(array));
-    }
-
-    NativeArray(final long[] array) {
-        this(ArrayData.allocate(array));
-    }
-
-    NativeArray(final double[] array) {
-        this(ArrayData.allocate(array));
-    }
-
-    NativeArray(final Object[] array) {
-        this(ArrayData.allocate(array.length));
-
-        ArrayData arrayData = this.getArray();
-        arrayData.ensure(array.length - 1);
-
-        for (int index = 0; index < array.length; index++) {
-            final Object value = array[index];
-
-            if (value == ScriptRuntime.EMPTY) {
-                arrayData = arrayData.delete(index);
-            } else {
-                arrayData = arrayData.set(index, value, false);
-            }
-        }
-
-        this.setArray(arrayData);
-    }
-
-    NativeArray(final ArrayData arrayData) {
-        this(arrayData, Global.instance());
-    }
-
-    NativeArray(final ArrayData arrayData, final Global global) {
-        super(global.getArrayPrototype(), $nasgenmap$);
-        this.setArray(arrayData);
-        this.setIsArray();
-    }
-
     @Override
     public String getClassName() {
         return "Array";
@@ -217,7 +250,11 @@
 
     @Override
     public Object getLength() {
-        return getArray().length() & JSType.MAX_UINT;
+        final long length = getArray().length() & JSType.MAX_UINT;
+        if(length < Integer.MAX_VALUE) {
+            return (int)length;
+        }
+        return length;
     }
 
     /**
@@ -271,7 +308,7 @@
             }
 
             // Step 3h and 3i
-            final boolean newWritable = (!newLenDesc.has(WRITABLE) || newLenDesc.isWritable());
+            final boolean newWritable = !newLenDesc.has(WRITABLE) || newLenDesc.isWritable();
             if (!newWritable) {
                 newLenDesc.setWritable(true);
             }
@@ -482,6 +519,19 @@
     }
 
     /**
+     * Assert that an array is numeric, if not throw type error
+     * @param self self array to check
+     * @return true if numeric
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE)
+    public static Object assertNumeric(final Object self) {
+        if(!(self instanceof NativeArray && ((NativeArray)self).getArray().getOptimisticType().isNumeric())) {
+            throw typeError("not.a.numeric.array", ScriptRuntime.safeToString(self));
+        }
+        return Boolean.TRUE;
+    }
+
+    /**
      * ECMA 15.4.4.3 Array.prototype.toLocaleString ( )
      *
      * @param self self reference
@@ -594,6 +644,21 @@
     /**
      * ECMA 15.4.2.2 new Array (len)
      *
+     * Specialized constructor for zero arguments - empty array
+     *
+     * @param newObj  was the new operator used to instantiate this array
+     * @param self    self reference
+     * @param element first element
+     * @return the new NativeArray
+     */
+    @SpecializedConstructor
+    public static Object construct(final boolean newObj, final Object self, final boolean element) {
+        return new NativeArray(new Object[] { element });
+    }
+
+    /**
+     * ECMA 15.4.2.2 new Array (len)
+     *
      * Specialized constructor for one integer argument (length)
      *
      * @param newObj was the new operator used to instantiate this array
@@ -669,16 +734,16 @@
         return new NativeArray(list.toArray());
     }
 
-    @SuppressWarnings("null")
     private static void concatToList(final ArrayList<Object> list, final Object obj) {
-        final boolean isScriptArray = isArray(obj);
+        final boolean isScriptArray  = isArray(obj);
         final boolean isScriptObject = isScriptArray || obj instanceof ScriptObject;
         if (isScriptArray || obj instanceof Iterable || (obj != null && obj.getClass().isArray())) {
             final Iterator<Object> iter = arrayLikeIterator(obj, true);
             if (iter.hasNext()) {
                 for (int i = 0; iter.hasNext(); ++i) {
                     final Object value = iter.next();
-                    if (value == ScriptRuntime.UNDEFINED && isScriptObject && !((ScriptObject)obj).has(i)) {
+                    final boolean lacksIndex = obj != null && !((ScriptObject)obj).has(i);
+                    if (value == ScriptRuntime.UNDEFINED && isScriptObject && lacksIndex) {
                         // TODO: eventually rewrite arrayLikeIterator to use a three-state enum for handling
                         // UNDEFINED instead of an "includeUndefined" boolean with states SKIP, INCLUDE,
                         // RETURN_EMPTY. Until then, this is how we'll make sure that empty elements don't make it
@@ -764,20 +829,17 @@
      *
      * @param self self reference
      * @param args arguments to push
-     * @return array after pushes
+     * @return array length after pushes
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static Object push(final Object self, final Object... args) {
         try {
             final ScriptObject sobj   = (ScriptObject)self;
 
-            if (bulkable(sobj)) {
-                if (sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
-                    final ArrayData newData = sobj.getArray().push(true, args);
-                    sobj.setArray(newData);
-                    return newData.length();
-                }
-                //fallthru
+            if (bulkable(sobj) && sobj.getArray().length() + args.length <= JSType.MAX_UINT) {
+                final ArrayData newData = sobj.getArray().push(true, args);
+                sobj.setArray(newData);
+                return newData.length();
             }
 
             long len = JSType.toUint32(sobj.getLength());
@@ -788,6 +850,88 @@
 
             return len;
         } catch (final ClassCastException | NullPointerException e) {
+            throw typeError(Context.getGlobal(), e, "not.an.object", ScriptRuntime.safeToString(self));
+        }
+    }
+
+    /**
+     * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single int argument
+     *
+     * @param self self reference
+     * @param arg argument to push
+     * @return array after pushes
+     */
+/*    @SpecializedFunction
+    public static long push(final Object self, final int arg) {
+        try {
+            final ScriptObject sobj = (ScriptObject)self;
+            final ArrayData arrayData = sobj.getArray();
+            final long length = arrayData.length();
+
+            if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) {
+                sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true));
+                return length + 1;
+            }
+
+            long len = JSType.toUint32(sobj.getLength());
+            sobj.set(len++, arg, true);
+            sobj.set("length", len, true);
+            return len;
+        } catch (final ClassCastException | NullPointerException e) {
+            throw typeError("not.an.object", ScriptRuntime.safeToString(self));
+        }
+    }
+*/
+    /**
+     * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single number argument
+     *
+     * @param self self reference
+     * @param arg argument to push
+     * @return array after pushes
+     */
+ /*   @SpecializedFunction
+    public static long push(final Object self, final double arg) {
+        try {
+            final ScriptObject sobj = (ScriptObject)self;        final ArrayData arrayData = sobj.getArray();
+            final long length = arrayData.length();
+
+            if (bulkable(sobj) && length + 1 <= JSType.MAX_UINT) {
+                sobj.setArray(arrayData.ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true));
+                return length + 1;
+            }
+
+            long len = JSType.toUint32(sobj.getLength());
+            sobj.set(len++, arg, true);
+            sobj.set("length", len, true);
+            return len;
+        } catch (final ClassCastException | NullPointerException e) {
+            throw typeError("not.an.object", ScriptRuntime.safeToString(self));
+        }
+    }
+*/
+    /**
+     * ECMA 15.4.4.7 Array.prototype.push (args...) specialized for single object argument
+     *
+     * @param self self reference
+     * @param arg argument to push
+     * @return array after pushes
+     */
+    @SpecializedFunction
+    public static long push(final Object self, final Object arg) {
+        try {
+            final ScriptObject sobj = (ScriptObject)self;
+            final ArrayData arrayData = sobj.getArray();
+            final long length = arrayData.length();
+            if (bulkable(sobj) && length < JSType.MAX_UINT) {
+                sobj.setArray(arrayData.push(true, arg)); //ensure(length).set(ArrayIndex.getArrayIndex(length), arg, true));
+                return length + 1;
+            }
+
+            long len = JSType.toUint32(sobj.getLength());
+            sobj.set(len++, arg, true);
+            sobj.set("length", len, true);
+            return len;
+        } catch (final ClassCastException | NullPointerException e) {
             throw typeError("not.an.object", ScriptRuntime.safeToString(self));
         }
     }
@@ -857,7 +1001,7 @@
             } else {
                 boolean hasPrevious = true;
                 for (long k = 1; k < len; k++) {
-                    boolean hasCurrent = sobj.has(k);
+                    final boolean hasCurrent = sobj.has(k);
                     if (hasCurrent) {
                         sobj.set(k - 1, sobj.get(k), true);
                     } else if (hasPrevious) {
@@ -894,7 +1038,7 @@
         final ScriptObject sobj                = (ScriptObject)obj;
         final long         len                 = JSType.toUint32(sobj.getLength());
         final long         relativeStart       = JSType.toLong(start);
-        final long         relativeEnd         = (end == ScriptRuntime.UNDEFINED) ? len : JSType.toLong(end);
+        final long         relativeEnd         = end == ScriptRuntime.UNDEFINED ? len : JSType.toLong(end);
 
         long k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
         final long finale = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
@@ -1001,7 +1145,7 @@
                 }
 
                 sobj.setArray(array);
-           }
+            }
 
             return sobj;
         } catch (final ClassCastException | NullPointerException e) {
@@ -1024,8 +1168,8 @@
             return ScriptRuntime.UNDEFINED;
         }
 
-        final Object start = (args.length > 0) ? args[0] : ScriptRuntime.UNDEFINED;
-        final Object deleteCount = (args.length > 1) ? args[1] : ScriptRuntime.UNDEFINED;
+        final Object start = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
+        final Object deleteCount = args.length > 1 ? args[1] : ScriptRuntime.UNDEFINED;
 
         Object[] items;
 
@@ -1054,7 +1198,7 @@
                 for (int i = 0; i < items.length; i++, k++) {
                     sobj.defineOwnProperty(k, items[i]);
                 }
-            } catch (UnsupportedOperationException uoe) {
+            } catch (final UnsupportedOperationException uoe) {
                 returnValue = slowSplice(sobj, actualStart, actualDeleteCount, items, len);
             }
         } else {
@@ -1077,7 +1221,7 @@
         }
 
         if (items.length < deleteCount) {
-            for (long k = start; k < (len - deleteCount); k++) {
+            for (long k = start; k < len - deleteCount; k++) {
                 final long from = k + deleteCount;
                 final long to   = k + items.length;
 
@@ -1088,7 +1232,7 @@
                 }
             }
 
-            for (long k = len; k > (len - deleteCount + items.length); k--) {
+            for (long k = len; k > len - deleteCount + items.length; k--) {
                 sobj.delete(k - 1, true);
             }
         } else if (items.length > deleteCount) {
@@ -1158,7 +1302,7 @@
             }
 
             for (int j = 0; j < items.length; j++) {
-                 sobj.set(j, items[j], true);
+                sobj.set(j, items[j], true);
             }
         }
 
@@ -1191,7 +1335,7 @@
             }
 
 
-            for (long k = Math.max(0, (n < 0) ? (len - Math.abs(n)) : n); k < len; k++) {
+            for (long k = Math.max(0, n < 0 ? len - Math.abs(n) : n); k < len; k++) {
                 if (sobj.has(k)) {
                     if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
                         return k;
@@ -1222,10 +1366,10 @@
                 return -1;
             }
 
-            final Object searchElement = (args.length > 0) ? args[0] : ScriptRuntime.UNDEFINED;
-            final long   n             = (args.length > 1) ? JSType.toLong(args[1]) : (len - 1);
+            final Object searchElement = args.length > 0 ? args[0] : ScriptRuntime.UNDEFINED;
+            final long   n             = args.length > 1 ? JSType.toLong(args[1]) : len - 1;
 
-            for (long k = (n < 0) ? (len - Math.abs(n)) : Math.min(n, len - 1); k >= 0; k--) {
+            for (long k = n < 0 ? len - Math.abs(n) : Math.min(n, len - 1); k >= 0; k--) {
                 if (sobj.has(k)) {
                     if (ScriptRuntime.EQ_STRICT(sobj.get(k), searchElement)) {
                         return k;
@@ -1258,7 +1402,7 @@
 
             @Override
             protected boolean forEach(final Object val, final long i) throws Throwable {
-                return (result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self));
+                return result = (boolean)everyInvoker.invokeExact(callbackfn, thisArg, val, i, self);
             }
         }.apply();
     }
@@ -1435,4 +1579,9 @@
 
         return false;
     }
+
+    @Override
+    public String toString() {
+        return "NativeArray@" + Debug.id(this) + '@' + getArray().getClass().getSimpleName();
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
index 70c97da..4d16ca5 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArrayBuffer.java
@@ -25,27 +25,81 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.nio.ByteBuffer;
-import java.util.Arrays;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Getter;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
+/**
+ * NativeArrayBuffer - ArrayBuffer as described in the JS typed
+ * array spec
+ */
 @ScriptClass("ArrayBuffer")
-final class NativeArrayBuffer extends ScriptObject {
-    private final byte[] buffer;
+public final class NativeArrayBuffer extends ScriptObject {
+    private final ByteBuffer nb;
 
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
 
+    /**
+     * Constructor
+     * @param nb native byte buffer to wrap
+     * @param global global instance
+     */
+    protected NativeArrayBuffer(final ByteBuffer nb, final Global global) {
+        super(global.getArrayBufferPrototype(), $nasgenmap$);
+        this.nb = nb;
+    }
+
+    /**
+     * Constructor
+     * @param nb native byte buffer to wrap
+     */
+    protected NativeArrayBuffer(final ByteBuffer nb) {
+        this(nb, Global.instance());
+    }
+
+    /**
+     * Constructor
+     * @param byteLength byteLength for buffer
+     */
+    protected NativeArrayBuffer(final int byteLength) {
+        this(ByteBuffer.allocateDirect(byteLength));
+    }
+
+    /**
+     * Clone constructor
+     * Used only for slice
+     * @param other original buffer
+     * @param begin begin byte index
+     * @param end   end byte index
+     */
+    protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
+        this(cloneBuffer(other.getNioBuffer(), begin, end));
+    }
+
+    /**
+     * Constructor
+     * @param newObj is this invoked with new
+     * @param self   self reference
+     * @param args   arguments to constructor
+     * @return new NativeArrayBuffer
+     */
     @Constructor(arity = 1)
     public static NativeArrayBuffer constructor(final boolean newObj, final Object self, final Object... args) {
+        if (!newObj) {
+            throw typeError("constructor.requires.new", "ArrayBuffer");
+        }
+
         if (args.length == 0) {
             throw new RuntimeException("missing length argument");
         }
@@ -53,21 +107,19 @@
         return new NativeArrayBuffer(JSType.toInt32(args[0]));
     }
 
-    protected NativeArrayBuffer(final byte[] byteArray, final Global global) {
-        super(global.getArrayBufferPrototype(), $nasgenmap$);
-        this.buffer = byteArray;
+    private static ByteBuffer cloneBuffer(final ByteBuffer original, final int begin, final int end) {
+        final ByteBuffer clone = ByteBuffer.allocateDirect(original.capacity());
+        original.rewind();//copy from the beginning
+        clone.put(original);
+        original.rewind();
+        clone.flip();
+        clone.position(begin);
+        clone.limit(end);
+        return clone.slice();
     }
 
-    protected NativeArrayBuffer(final byte[] byteArray) {
-        this(byteArray, Global.instance());
-    }
-
-    protected NativeArrayBuffer(final int byteLength) {
-        this(new byte[byteLength]);
-    }
-
-    protected NativeArrayBuffer(final NativeArrayBuffer other, final int begin, final int end) {
-        this(Arrays.copyOfRange(other.buffer, begin, end));
+    ByteBuffer getNioBuffer() {
+        return nb;
     }
 
     @Override
@@ -75,19 +127,55 @@
         return "ArrayBuffer";
     }
 
+    /**
+     * Byte length for native array buffer
+     * @param self native array buffer
+     * @return byte length
+     */
     @Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
-    public static Object byteLength(final Object self) {
-        return ((NativeArrayBuffer)self).buffer.length;
+    public static int byteLength(final Object self) {
+        return ((NativeArrayBuffer)self).getByteLength();
     }
 
+    /**
+     * Slice function
+     * @param self   native array buffer
+     * @param begin0 start byte index
+     * @param end0   end byte index
+     * @return new array buffer, sliced
+     */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static NativeArrayBuffer slice(final Object self, final Object begin0, final Object end0) {
         final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
-        int begin = JSType.toInt32(begin0);
-        int end = end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : arrayBuffer.getByteLength();
-        begin = adjustIndex(begin, arrayBuffer.getByteLength());
-        end = adjustIndex(end, arrayBuffer.getByteLength());
-        return new NativeArrayBuffer((NativeArrayBuffer) self, begin, Math.max(end, begin));
+        final int               byteLength  = arrayBuffer.getByteLength();
+        final int               begin       = adjustIndex(JSType.toInt32(begin0), byteLength);
+        final int               end         = adjustIndex(end0 != ScriptRuntime.UNDEFINED ? JSType.toInt32(end0) : byteLength, byteLength);
+        return new NativeArrayBuffer(arrayBuffer, begin, Math.max(end, begin));
+    }
+
+    /**
+     * Specialized slice function
+     * @param self   native array buffer
+     * @param begin  start byte index
+     * @param end    end byte index
+     * @return new array buffer, sliced
+     */
+    @SpecializedFunction
+    public static Object slice(final Object self, final int begin, final int end) {
+        final NativeArrayBuffer arrayBuffer = (NativeArrayBuffer)self;
+        final int byteLength  = arrayBuffer.getByteLength();
+        return new NativeArrayBuffer(arrayBuffer, adjustIndex(begin, byteLength), Math.max(adjustIndex(end, byteLength), begin));
+    }
+
+    /**
+     * Specialized slice function
+     * @param self   native array buffer
+     * @param begin  start byte index
+     * @return new array buffer, sliced
+     */
+    @SpecializedFunction
+    public static Object slice(final Object self, final int begin) {
+        return slice(self, begin, ((NativeArrayBuffer)self).getByteLength());
     }
 
     /**
@@ -100,10 +188,7 @@
      * @return valid index index in the range [0, length).
      */
     static int adjustIndex(final int index, final int length) {
-        if (index < 0) {
-            return clamp(index + length, length);
-        }
-        return clamp(index, length);
+        return index < 0 ? clamp(index + length, length) : clamp(index, length);
     }
 
     /**
@@ -118,23 +203,19 @@
         return index;
     }
 
-    public byte[] getByteArray() {
-        return buffer;
-    }
-
-    public int getByteLength() {
-        return buffer.length;
+    int getByteLength() {
+        return nb.limit();
     }
 
     ByteBuffer getBuffer() {
-       return ByteBuffer.wrap(buffer);
+       return nb;
     }
 
     ByteBuffer getBuffer(final int offset) {
-        return ByteBuffer.wrap(buffer, offset, buffer.length - offset);
+        return (ByteBuffer)nb.duplicate().position(offset);
     }
 
     ByteBuffer getBuffer(final int offset, final int length) {
-        return ByteBuffer.wrap(buffer, offset, length);
+        return (ByteBuffer)getBuffer(offset).limit(length);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
index d645d6d..a6581b5 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeBoolean.java
@@ -25,8 +25,8 @@
 
 package jdk.nashorn.internal.objects;
 
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java
index 414ff8ae..470803e 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDataView.java
@@ -24,9 +24,9 @@
  */
 package jdk.nashorn.internal.objects;
 
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -88,15 +88,15 @@
     // underlying ByteBuffer
     private final ByteBuffer buf;
 
-    private NativeDataView(NativeArrayBuffer arrBuf) {
+    private NativeDataView(final NativeArrayBuffer arrBuf) {
         this(arrBuf, arrBuf.getBuffer(), 0);
     }
 
-    private NativeDataView(NativeArrayBuffer arrBuf, int offset) {
+    private NativeDataView(final NativeArrayBuffer arrBuf, final int offset) {
         this(arrBuf, bufferFrom(arrBuf, offset), offset);
     }
 
-    private NativeDataView(NativeArrayBuffer arrBuf, int offset, int length) {
+    private NativeDataView(final NativeArrayBuffer arrBuf, final int offset, final int length) {
         this(arrBuf, bufferFrom(arrBuf, offset, length), offset, length);
     }
 
@@ -204,8 +204,8 @@
     public static int getInt8(final Object self, final Object byteOffset) {
         try {
             return getBuffer(self).get(JSType.toInt32(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -220,8 +220,8 @@
     public static int getInt8(final Object self, final int byteOffset) {
         try {
             return getBuffer(self).get(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -235,9 +235,9 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static int getUint8(final Object self, final Object byteOffset) {
         try {
-            return (0xFF & getBuffer(self).get(JSType.toInt32(byteOffset)));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return 0xFF & getBuffer(self).get(JSType.toInt32(byteOffset));
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -251,9 +251,9 @@
     @SpecializedFunction
     public static int getUint8(final Object self, final int byteOffset) {
         try {
-            return (0xFF & getBuffer(self).get(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return 0xFF & getBuffer(self).get(byteOffset);
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -269,8 +269,8 @@
     public static int getInt16(final Object self, final Object byteOffset, final Object littleEndian) {
         try {
             return getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -285,8 +285,8 @@
     public static int getInt16(final Object self, final int byteOffset) {
         try {
             return getBuffer(self, false).getShort(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -302,8 +302,8 @@
     public static int getInt16(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
             return getBuffer(self, littleEndian).getShort(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -318,9 +318,9 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static int getUint16(final Object self, final Object byteOffset, final Object littleEndian) {
         try {
-            return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset)));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return 0xFFFF & getBuffer(self, littleEndian).getShort(JSType.toInt32(byteOffset));
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -334,9 +334,9 @@
     @SpecializedFunction
     public static int getUint16(final Object self, final int byteOffset) {
         try {
-            return (int) (0xFFFF & getBuffer(self, false).getShort(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return 0xFFFF & getBuffer(self, false).getShort(byteOffset);
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -351,9 +351,9 @@
     @SpecializedFunction
     public static int getUint16(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
-            return (int) (0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return 0xFFFF & getBuffer(self, littleEndian).getShort(byteOffset);
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -369,8 +369,8 @@
     public static int getInt32(final Object self, final Object byteOffset, final Object littleEndian) {
         try {
             return getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -385,8 +385,8 @@
     public static int getInt32(final Object self, final int byteOffset) {
         try {
             return getBuffer(self, false).getInt(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -402,8 +402,8 @@
     public static int getInt32(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
             return getBuffer(self, littleEndian).getInt(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -418,9 +418,9 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static long getUint32(final Object self, final Object byteOffset, final Object littleEndian) {
         try {
-            return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return 0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -434,9 +434,9 @@
     @SpecializedFunction
     public static long getUint32(final Object self, final int byteOffset) {
         try {
-            return (long) (0xFFFFFFFFL & getBuffer(self, false).getInt(JSType.toInt32(byteOffset)));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return JSType.MAX_UINT & getBuffer(self, false).getInt(JSType.toInt32(byteOffset));
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -451,9 +451,9 @@
     @SpecializedFunction
     public static long getUint32(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
-            return (long) (0xFFFFFFFFL & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset)));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+            return JSType.MAX_UINT & getBuffer(self, littleEndian).getInt(JSType.toInt32(byteOffset));
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -469,8 +469,8 @@
     public static double getFloat32(final Object self, final Object byteOffset, final Object littleEndian) {
         try {
             return getBuffer(self, littleEndian).getFloat(JSType.toInt32(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -485,8 +485,8 @@
     public static double getFloat32(final Object self, final int byteOffset) {
         try {
             return getBuffer(self, false).getFloat(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -502,8 +502,8 @@
     public static double getFloat32(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
             return getBuffer(self, littleEndian).getFloat(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -519,8 +519,8 @@
     public static double getFloat64(final Object self, final Object byteOffset, final Object littleEndian) {
         try {
             return getBuffer(self, littleEndian).getDouble(JSType.toInt32(byteOffset));
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -535,8 +535,8 @@
     public static double getFloat64(final Object self, final int byteOffset) {
         try {
             return getBuffer(self, false).getDouble(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -552,8 +552,8 @@
     public static double getFloat64(final Object self, final int byteOffset, final boolean littleEndian) {
         try {
             return getBuffer(self, littleEndian).getDouble(byteOffset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -582,8 +582,8 @@
         try {
             getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -600,8 +600,8 @@
         try {
             getBuffer(self).put(byteOffset, (byte)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -618,8 +618,8 @@
         try {
             getBuffer(self).put(JSType.toInt32(byteOffset), (byte)JSType.toInt32(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -636,8 +636,8 @@
         try {
             getBuffer(self).put(byteOffset, (byte)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -655,8 +655,8 @@
         try {
             getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -673,8 +673,8 @@
         try {
             getBuffer(self, false).putShort(byteOffset, (short)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -692,8 +692,8 @@
         try {
             getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -711,8 +711,8 @@
         try {
             getBuffer(self, littleEndian).putShort(JSType.toInt32(byteOffset), (short)JSType.toInt32(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -729,8 +729,8 @@
         try {
             getBuffer(self, false).putShort(byteOffset, (short)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -748,8 +748,8 @@
         try {
             getBuffer(self, littleEndian).putShort(byteOffset, (short)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -765,10 +765,10 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 2)
     public static Object setInt32(final Object self, final Object byteOffset, final Object value, final Object littleEndian) {
         try {
-            getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toInt32(value));
+            getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), JSType.toInt32(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -785,8 +785,8 @@
         try {
             getBuffer(self, false).putInt(byteOffset, value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -804,8 +804,8 @@
         try {
             getBuffer(self, littleEndian).putInt(byteOffset, value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -823,8 +823,8 @@
         try {
             getBuffer(self, littleEndian).putInt(JSType.toInt32(byteOffset), (int)JSType.toUint32(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -841,8 +841,8 @@
         try {
             getBuffer(self, false).putInt(byteOffset, (int)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -860,8 +860,8 @@
         try {
             getBuffer(self, littleEndian).putInt(byteOffset, (int)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -879,8 +879,8 @@
         try {
             getBuffer(self, littleEndian).putFloat((int)JSType.toUint32(byteOffset), (float)JSType.toNumber(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -897,8 +897,8 @@
         try {
             getBuffer(self, false).putFloat(byteOffset, (float)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -916,8 +916,8 @@
         try {
             getBuffer(self, littleEndian).putFloat(byteOffset, (float)value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -935,8 +935,8 @@
         try {
             getBuffer(self, littleEndian).putDouble((int)JSType.toUint32(byteOffset), JSType.toNumber(value));
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -953,8 +953,8 @@
         try {
             getBuffer(self, false).putDouble(byteOffset, value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -972,8 +972,8 @@
         try {
             getBuffer(self, littleEndian).putDouble(byteOffset, value);
             return UNDEFINED;
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.offset");
         }
     }
 
@@ -981,16 +981,16 @@
     private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset) {
         try {
             return nab.getBuffer(offset);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.constructor.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.constructor.offset");
         }
     }
 
     private static ByteBuffer bufferFrom(final NativeArrayBuffer nab, final int offset, final int length) {
         try {
             return nab.getBuffer(offset, length);
-        } catch (final IndexOutOfBoundsException ioe) {
-            throw rangeError(ioe, "dataview.constructor.offset");
+        } catch (final IllegalArgumentException iae) {
+            throw rangeError(iae, "dataview.constructor.offset");
         }
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
index b3661df..eac59c4 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java
@@ -909,6 +909,7 @@
         sb.append(n);
     }
 
+    @SuppressWarnings("fallthrough")
     private static String toStringImpl(final Object self, final int format) {
         final NativeDate nd = getNativeDate(self);
 
@@ -934,7 +935,6 @@
                     }
                     sb.append(' ');
 
-                    //$FALL-THROUGH$
                 case FORMAT_TIME:
                     final TimeZone tz = nd.getTimeZone();
                     final double utcTime = nd.getTime();
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
index 5d80c37..dc6ba04 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDebug.java
@@ -28,16 +28,19 @@
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.io.PrintWriter;
+import java.util.LinkedList;
 import java.util.Objects;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyListeners;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.events.RuntimeEvent;
 import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
 
 /**
@@ -93,21 +96,6 @@
     }
 
     /**
-     * Nashorn extension: get spill vector from {@link ScriptObject}
-     *
-     * @param self self reference
-     * @param obj script object
-     * @return the spill vector for the given ScriptObject
-     */
-    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
-    public static Object spill(final Object self, final Object obj) {
-        if (obj instanceof ScriptObject) {
-            return ((ScriptObject)obj).spill;
-        }
-        return UNDEFINED;
-    }
-
-    /**
      * Check object identity comparison regardless of type
      *
      * @param self self reference
@@ -121,6 +109,31 @@
     }
 
     /**
+     * Returns true if if the two objects are both property maps, and they have identical properties in the same order,
+     * but allows the properties to differ in their types.
+     * @param self self
+     * @param m1 first property map
+     * @param m2 second property map
+     * @return true if they have identical properties in same order, with possibly different types.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object equalWithoutType(final Object self, final Object m1, final Object m2) {
+        return ((PropertyMap)m1).equalsWithoutType((PropertyMap)m2);
+    }
+
+    /**
+     * Returns a diagnostic string representing the difference of two property maps.
+     * @param self self
+     * @param m1 first property map
+     * @param m2 second property map
+     * @return a diagnostic string representing the difference of two property maps.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object diffPropertyMaps(final Object self, final Object m1, final Object m2) {
+        return PropertyMap.diff((PropertyMap)m1, (PropertyMap)m2);
+    }
+
+    /**
      * Object util - getClass
      *
      * @param self self reference
@@ -196,7 +209,6 @@
      * @param self self reference
      * @return undefined
      */
-    @SuppressWarnings("resource")
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object dumpCounters(final Object self) {
         final PrintWriter out = Context.getCurrentErr();
@@ -210,7 +222,6 @@
         out.println("ScriptFunction allocations " + ScriptFunction.getAllocations());
         out.println("PropertyMap count " + PropertyMap.getCount());
         out.println("PropertyMap cloned " + PropertyMap.getClonedCount());
-        out.println("PropertyMap duplicated " + PropertyMap.getDuplicatedCount());
         out.println("PropertyMap history hit " + PropertyMap.getHistoryHit());
         out.println("PropertyMap proto invalidations " + PropertyMap.getProtoInvalidations());
         out.println("PropertyMap proto history hit " + PropertyMap.getProtoHistoryHit());
@@ -223,4 +234,133 @@
 
         return UNDEFINED;
     }
+
+    /*
+     * Framework for logging runtime events
+     */
+
+    private static final String EVENT_QUEUE          = "__eventQueue__";
+    private static final String EVENT_QUEUE_CAPACITY = "__eventQueueCapacity__";
+
+    /**
+     * Get the capacity of the event queue
+     * @param self self reference
+     * @return capacity of event queue as an integer
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object getEventQueueCapacity(final Object self) {
+        final ScriptObject sobj = (ScriptObject)self;
+        Integer cap;
+        if (sobj.has(EVENT_QUEUE_CAPACITY)) {
+            cap = JSType.toInt32(sobj.get(EVENT_QUEUE_CAPACITY));
+        } else {
+            setEventQueueCapacity(self, cap = RuntimeEvent.RUNTIME_EVENT_QUEUE_SIZE);
+        }
+        return cap;
+    }
+
+    /**
+     * Set the event queue capacity
+     * @param self
+     * @param newCapacity
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static void setEventQueueCapacity(final Object self, final Object newCapacity) {
+        ((ScriptObject)self).set(EVENT_QUEUE_CAPACITY, newCapacity, true);
+    }
+
+    /**
+     * Add a runtime event to the runtime event queue. The queue has a fixed
+     * size {@link RuntimeEvent#RUNTIME_EVENT_QUEUE_SIZE} and the oldest
+     * entry will be thrown out of the queue is about to overflow
+     * @param self self reference
+     * @param event event to add
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static void addRuntimeEvent(final Object self, final Object event) {
+        final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+        final int cap = (Integer)getEventQueueCapacity(self);
+        while (q.size() >= cap) {
+            q.removeFirst();
+        }
+        q.addLast(getEvent(event));
+    }
+
+    /**
+     * Expands the event queue capacity, or truncates if capacity is lower than
+     * current capacity. Then only the newest entries are kept
+     * @param self self reference
+     * @param newCapacity new capacity
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static void expandEventQueueCapacity(final Object self, final Object newCapacity) {
+        final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+        final int nc = JSType.toInt32(newCapacity);
+        while (q.size() > nc) {
+            q.removeFirst();
+        }
+        setEventQueueCapacity(self, nc);
+    }
+
+    /**
+     * Clear the runtime event queue
+     * @param self self reference
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static void clearRuntimeEvents(final Object self) {
+        final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+        q.clear();
+    }
+
+    /**
+     * Remove a specific runtime event from the event queue
+     * @param self self reference
+     * @param event event to remove
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static void removeRuntimeEvent(final Object self, final Object event) {
+        final LinkedList<RuntimeEvent<?>> q  = getEventQueue(self);
+        final RuntimeEvent<?>             re = getEvent(event);
+        if (!q.remove(re)) {
+            throw new IllegalStateException("runtime event " + re + " was not in event queue");
+        }
+    }
+
+    /**
+     * Return all runtime events in the queue as an array
+     * @param self self reference
+     * @return array of events
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object getRuntimeEvents(final Object self) {
+        final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+        return q.toArray(new RuntimeEvent<?>[q.size()]);
+    }
+
+    /**
+     * Return the last runtime event in the queue
+     * @param self self reference
+     * @return the freshest event, null if queue is empty
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object getLastRuntimeEvent(final Object self) {
+        final LinkedList<RuntimeEvent<?>> q = getEventQueue(self);
+        return q.isEmpty() ? null : q.getLast();
+    }
+
+    @SuppressWarnings("unchecked")
+    private static LinkedList<RuntimeEvent<?>> getEventQueue(final Object self) {
+        final ScriptObject sobj = (ScriptObject)self;
+        LinkedList<RuntimeEvent<?>> q;
+        if (sobj.has(EVENT_QUEUE)) {
+            q = (LinkedList<RuntimeEvent<?>>)((ScriptObject)self).get(EVENT_QUEUE);
+        } else {
+            ((ScriptObject)self).set(EVENT_QUEUE, q = new LinkedList<>(), true);
+        }
+        return q;
+    }
+
+    private static RuntimeEvent<?> getEvent(final Object event) {
+        return (RuntimeEvent<?>)event;
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
index 18aa11e..e1d95ce 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeError.java
@@ -25,12 +25,11 @@
 
 package jdk.nashorn.internal.objects;
 
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
-
 import jdk.nashorn.api.scripting.NashornException;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -41,8 +40,8 @@
 import jdk.nashorn.internal.runtime.ECMAException;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
@@ -147,8 +146,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object captureStackTrace(final Object self, final Object errorObj) {
-        Global.checkObject(errorObj);
-        final ScriptObject sobj = (ScriptObject)errorObj;
+        final ScriptObject sobj = Global.checkObject(errorObj);
         initException(sobj);
         sobj.delete(STACK, false);
         if (! sobj.has("stack")) {
@@ -184,8 +182,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object printStackTrace(final Object self) {
-        Global.checkObject(self);
-        return ECMAException.printStackTrace((ScriptObject)self);
+        return ECMAException.printStackTrace(Global.checkObject(self));
     }
 
     /**
@@ -199,8 +196,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object getStackTrace(final Object self) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         final Object exception = ECMAException.getException(sobj);
         Object[] res;
         if (exception instanceof Throwable) {
@@ -220,8 +216,7 @@
      * @return line number from which error was thrown
      */
     public static Object getLineNumber(final Object self) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         return sobj.has(LINENUMBER) ? sobj.get(LINENUMBER) : ECMAException.getLineNumber(sobj);
     }
 
@@ -234,8 +229,7 @@
      * @return value that was set
      */
     public static Object setLineNumber(final Object self, final Object value) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         if (sobj.hasOwnProperty(LINENUMBER)) {
             sobj.put(LINENUMBER, value, false);
         } else {
@@ -252,8 +246,7 @@
      * @return column number from which error was thrown
      */
     public static Object getColumnNumber(final Object self) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         return sobj.has(COLUMNNUMBER) ? sobj.get(COLUMNNUMBER) : ECMAException.getColumnNumber((ScriptObject)self);
     }
 
@@ -266,8 +259,7 @@
      * @return value that was set
      */
     public static Object setColumnNumber(final Object self, final Object value) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         if (sobj.hasOwnProperty(COLUMNNUMBER)) {
             sobj.put(COLUMNNUMBER, value, false);
         } else {
@@ -284,8 +276,7 @@
      * @return file name from which error was thrown
      */
     public static Object getFileName(final Object self) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         return sobj.has(FILENAME) ? sobj.get(FILENAME) : ECMAException.getFileName((ScriptObject)self);
     }
 
@@ -298,8 +289,7 @@
      * @return value that was set
      */
     public static Object setFileName(final Object self, final Object value) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         if (sobj.hasOwnProperty(FILENAME)) {
             sobj.put(FILENAME, value, false);
         } else {
@@ -318,15 +308,14 @@
      * @return      value of "stack" property
      */
     public static Object getStack(final Object self) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         if (sobj.has(STACK)) {
             return sobj.get(STACK);
         }
 
         final Object exception = ECMAException.getException(sobj);
         if (exception instanceof Throwable) {
-            Object value = getScriptStackString(sobj, (Throwable)exception);
+            final Object value = getScriptStackString(sobj, (Throwable)exception);
             if (sobj.hasOwnProperty(STACK)) {
                 sobj.put(STACK, value, false);
             } else {
@@ -349,14 +338,12 @@
      * @return value that was set
      */
     public static Object setStack(final Object self, final Object value) {
-        Global.checkObject(self);
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
         if (sobj.hasOwnProperty(STACK)) {
             sobj.put(STACK, value, false);
         } else {
             sobj.addOwnProperty(STACK, Attribute.NOT_ENUMERABLE, value);
         }
-
         return value;
     }
 
@@ -370,9 +357,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object toString(final Object self) {
         // Step 1 and 2 : check if 'self' is object it not throw TypeError
-        Global.checkObject(self);
-
-        final ScriptObject sobj = (ScriptObject)self;
+        final ScriptObject sobj = Global.checkObject(self);
 
         // Step 3 & 4 : get "name" and convert to String.
         // But if message is undefined make it "Error".
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
index a9dfb7a..b2639c4 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat32Array.java
@@ -25,6 +25,12 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.FloatBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +41,7 @@
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Float32 array for the TypedArray extension
@@ -56,73 +63,103 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeFloat32Array(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Float32ArrayData(buffer, byteOffset, length);
+        public Float32ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Float32ArrayData(nb.asFloatBuffer(), start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Float32Array";
         }
     };
 
-    private static final class Float32ArrayData extends ArrayDataImpl {
-        private Float32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Float32ArrayData extends TypedArrayData<FloatBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Float32ArrayData.class, "getElem", double.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Float32ArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+        private Float32ArrayData(final FloatBuffer nb, final int start, final int end) {
+            super(((FloatBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected double getDoubleImpl(final int index) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            final int bits = byteArray[byteIndex  ]       & 0x0000_00ff |
-                             byteArray[byteIndex+1] <<  8 & 0x0000_ff00 |
-                             byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
-                             byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
-            return Float.intBitsToFloat(bits);
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private double getElem(final int index) {
+            try {
+                return nb.get(index);
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final double elem) {
+            try {
+                nb.put(index, (float)elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            return (int)getDoubleImpl(index);
+        public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+            if (returnType == int.class || returnType == long.class) {
+                return null;
+            }
+            return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
         }
 
         @Override
-        protected long getLongImpl(final int key) {
-            return (long)getDoubleImpl(key);
+        public int getInt(final int index) {
+            return (int)getDouble(index);
         }
 
         @Override
-        protected Object getObjectImpl(final int key) {
-            return getDoubleImpl(key);
+        public long getLong(final int index) {
+            return (long)getDouble(index);
         }
 
         @Override
-        protected void setImpl(final int index, final double value) {
-            final int bits = Float.floatToRawIntBits((float)value);
-            final int byteIndex = byteIndex(index);
-            @SuppressWarnings("MismatchedReadAndWriteOfArray")
-            final byte[] byteArray = buffer.getByteArray();
-            byteArray[byteIndex  ] = (byte)(bits        & 0xff);
-            byteArray[byteIndex+1] = (byte)(bits >>>  8 & 0xff);
-            byteArray[byteIndex+2] = (byte)(bits >>> 16 & 0xff);
-            byteArray[byteIndex+3] = (byte)(bits >>> 24 & 0xff);
+        public double getDouble(final int index) {
+            return getElem(index);
         }
 
         @Override
-        protected void setImpl(final int key, final int value) {
-            setImpl(key, (double)value);
+        public Object getObject(final int index) {
+            return getDouble(index);
         }
 
         @Override
-        protected void setImpl(final int key, final long value) {
-            setImpl(key, (double)value);
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toNumber(value), strict);
         }
 
         @Override
-        protected void setImpl(final int key, final Object value) {
-            setImpl(key, JSType.toNumber(value));
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            return set(index, (double)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (double)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            setElem(index, value);
+            return this;
         }
     }
 
@@ -137,7 +174,7 @@
      */
     @Constructor(arity = 1)
     public static NativeFloat32Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeFloat32Array)constructorImpl(args, FACTORY);
+        return (NativeFloat32Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeFloat32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -145,11 +182,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Float32Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
index 61b5880..9316295 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFloat64Array.java
@@ -25,6 +25,12 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.DoubleBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +41,7 @@
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Float64 array for the TypedArray extension
@@ -56,83 +63,103 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeFloat64Array(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Float64ArrayData(buffer, byteOffset, length);
+        public Float64ArrayData createArrayData(final ByteBuffer nb, final int start, final int length) {
+            return new Float64ArrayData(nb.asDoubleBuffer(), start, length);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Float64Array";
         }
     };
 
-    private static final class Float64ArrayData extends ArrayDataImpl {
-        private Float64ArrayData(final NativeArrayBuffer buffer,
-                final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Float64ArrayData extends TypedArrayData<DoubleBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Float64ArrayData.class, "getElem", double.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Float64ArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+        private Float64ArrayData(final DoubleBuffer nb, final int start, final int end) {
+            super(((DoubleBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected double getDoubleImpl(final int index) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            final long bits;
-            bits =       byteArray[byteIndex  ]       & 0x0000_0000_0000_00ffL |
-                   (long)byteArray[byteIndex+1] <<  8 & 0x0000_0000_0000_ff00L |
-                   (long)byteArray[byteIndex+2] << 16 & 0x0000_0000_00ff_0000L |
-                   (long)byteArray[byteIndex+3] << 24 & 0x0000_0000_ff00_0000L |
-                   (long)byteArray[byteIndex+4] << 32 & 0x0000_00ff_0000_0000L |
-                   (long)byteArray[byteIndex+5] << 40 & 0x0000_ff00_0000_0000L |
-                   (long)byteArray[byteIndex+6] << 48 & 0x00ff_0000_0000_0000L |
-                   (long)byteArray[byteIndex+7] << 56 & 0xff00_0000_0000_0000L ;
-            return Double.longBitsToDouble(bits);
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private double getElem(final int index) {
+            try {
+                return nb.get(index);
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final double elem) {
+            try {
+                nb.put(index, elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+             }
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            return (int)getDoubleImpl(index);
+        public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+            if (returnType == int.class || returnType == long.class) {
+                return null;
+            }
+            return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
         }
 
         @Override
-        protected long getLongImpl(final int key) {
-            return (long)getDoubleImpl(key);
+        public int getInt(final int index) {
+            return (int)getDouble(index);
         }
 
         @Override
-        protected Object getObjectImpl(final int key) {
-            return getDoubleImpl(key);
+        public long getLong(final int index) {
+            return (long)getDouble(index);
         }
 
         @Override
-        protected void setImpl(final int index, final double value) {
-            final long bits = Double.doubleToRawLongBits(value);
-            final int byteIndex = byteIndex(index);
-            @SuppressWarnings("MismatchedReadAndWriteOfArray")
-            final byte[] byteArray = buffer.getByteArray();
-            byteArray[byteIndex  ] = (byte)(bits        & 0xff);
-            byteArray[byteIndex+1] = (byte)(bits >>>  8 & 0xff);
-            byteArray[byteIndex+2] = (byte)(bits >>> 16 & 0xff);
-            byteArray[byteIndex+3] = (byte)(bits >>> 24 & 0xff);
-            byteArray[byteIndex+4] = (byte)(bits >>> 32 & 0xff);
-            byteArray[byteIndex+5] = (byte)(bits >>> 40 & 0xff);
-            byteArray[byteIndex+6] = (byte)(bits >>> 48 & 0xff);
-            byteArray[byteIndex+7] = (byte)(bits >>> 56 & 0xff);
+        public double getDouble(final int index) {
+            return getElem(index);
         }
 
         @Override
-        protected void setImpl(final int key, final int value) {
-            setImpl(key, (double)value);
+        public Object getObject(final int index) {
+            return getDouble(index);
         }
 
         @Override
-        protected void setImpl(final int key, final long value) {
-            setImpl(key, (double)value);
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toNumber(value), strict);
         }
 
         @Override
-        protected void setImpl(final int key, final Object value) {
-            setImpl(key, JSType.toNumber(value));
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            return set(index, (double)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (double)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            setElem(index, value);
+            return this;
         }
     }
 
@@ -147,7 +174,7 @@
      */
     @Constructor(arity = 1)
     public static NativeFloat64Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeFloat64Array)constructorImpl(args, FACTORY);
+        return (NativeFloat64Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeFloat64Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -155,11 +182,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Float64Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
index 013683e..c4a79a5 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java
@@ -25,12 +25,15 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.util.List;
-
+import jdk.internal.dynalink.support.Lookup;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
@@ -41,10 +44,10 @@
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
-import jdk.nashorn.internal.runtime.Source;
 
 /**
  * ECMA 15.3 Function Objects
@@ -56,6 +59,9 @@
 @ScriptClass("Function")
 public final class NativeFunction {
 
+    /** apply arg converter handle */
+    public static final MethodHandle TO_APPLY_ARGS = Lookup.findOwnStatic(MethodHandles.lookup(), "toApplyArgs", Object[].class, Object.class);
+
     // initialized by nasgen
     @SuppressWarnings("unused")
     private static PropertyMap $nasgenmap$;
@@ -89,50 +95,75 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static Object apply(final Object self, final Object thiz, final Object array) {
-        if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) {
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
-        }
+        checkCallable(self);
 
-        Object[] args = null;
-
-        if (array instanceof ScriptObject) {
-            // look for array-like object
-            final ScriptObject sobj = (ScriptObject)array;
-            final Object       len  = sobj.getLength();
-            final int n = (int)JSType.toUint32(len);
-
-            args = new Object[n];
-            for (int i = 0; i < args.length; i++) {
-                args[i] = sobj.get(i);
-            }
-        } else if (array instanceof Object[]) {
-            args = (Object[])array;
-        } else if (array instanceof List) {
-            final List<?> list = (List<?>)array;
-            list.toArray(args = new Object[list.size()]);
-        } else if (array == null || array == UNDEFINED) {
-            args = ScriptRuntime.EMPTY_ARRAY;
-        } else if (array instanceof JSObject) {
-            // look for array-like JSObject object
-            final JSObject jsObj = (JSObject)array;
-            final Object       len  = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0);
-            final int n = (int)JSType.toUint32(len);
-
-            args = new Object[n];
-            for (int i = 0; i < args.length; i++) {
-                args[i] = jsObj.hasSlot(i)? jsObj.getSlot(i) : UNDEFINED;
-            }
-        } else {
-            throw typeError("function.apply.expects.array");
-        }
+        final Object[] args = toApplyArgs(array);
 
         if (self instanceof ScriptFunction) {
             return ScriptRuntime.apply((ScriptFunction)self, thiz, args);
         } else if (self instanceof JSObject) {
             return ((JSObject)self).call(thiz, args);
         }
+        throw new AssertionError("Should not reach here");
+    }
 
-        throw new AssertionError("should not reach here");
+     /**
+     * Given an array-like object, converts it into a Java object array suitable for invocation of ScriptRuntime.apply
+     * or for direct invocation of the applied function.
+     * @param array the array-like object. Can be null in which case a zero-length array is created.
+     * @return the Java array
+     */
+    public static Object[] toApplyArgs(final Object array) {
+        if (array instanceof NativeArguments) {
+            return ((NativeArguments)array).getArray().asObjectArray();
+        } else if (array instanceof ScriptObject) {
+            // look for array-like object
+            final ScriptObject sobj = (ScriptObject)array;
+            final int n = lengthToInt(sobj.getLength());
+
+            final Object[] args = new Object[n];
+            for (int i = 0; i < args.length; i++) {
+                args[i] = sobj.get(i);
+            }
+            return args;
+        } else if (array instanceof Object[]) {
+            return (Object[])array;
+        } else if (array instanceof List) {
+            final List<?> list = (List<?>)array;
+            return list.toArray(new Object[list.size()]);
+        } else if (array == null || array == UNDEFINED) {
+            return ScriptRuntime.EMPTY_ARRAY;
+        } else if (array instanceof JSObject) {
+            // look for array-like JSObject object
+            final JSObject jsObj = (JSObject)array;
+            final Object   len  = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0);
+            final int n = lengthToInt(len);
+
+            final Object[] args = new Object[n];
+            for (int i = 0; i < args.length; i++) {
+                args[i] = jsObj.hasSlot(i)? jsObj.getSlot(i) : UNDEFINED;
+            }
+            return args;
+        } else {
+            throw typeError("function.apply.expects.array");
+        }
+    }
+
+    private static int lengthToInt(final Object len) {
+        final long ln = JSType.toUint32(len);
+        // NOTE: ECMASCript 5.1 section 15.3.4.3 says length should be treated as Uint32, but we wouldn't be able to
+        // allocate a Java array of more than MAX_VALUE elements anyway, so at this point we have to throw an error.
+        // People applying a function to more than 2^31 arguments will unfortunately be out of luck.
+        if (ln > Integer.MAX_VALUE) {
+            throw rangeError("range.error.inappropriate.array.length", JSType.toString(len));
+        }
+        return (int)ln;
+    }
+
+    private static void checkCallable(final Object self) {
+        if (!(self instanceof ScriptFunction || (self instanceof JSObject && ((JSObject)self).isFunction()))) {
+            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
+        }
     }
 
     /**
@@ -144,11 +175,9 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1)
     public static Object call(final Object self, final Object... args) {
-        if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) {
-            throw typeError("not.a.function", ScriptRuntime.safeToString(self));
-        }
+        checkCallable(self);
 
-        Object thiz = (args.length == 0) ? UNDEFINED : args[0];
+        final Object thiz = (args.length == 0) ? UNDEFINED : args[0];
         Object[] arguments;
 
         if (args.length > 1) {
@@ -236,7 +265,7 @@
             funcBody = JSType.toString(args[args.length - 1]);
 
             final String paramList = paramListBuf.toString();
-            if (! paramList.isEmpty()) {
+            if (!paramList.isEmpty()) {
                 checkFunctionParameters(paramList);
                 sb.append(paramList);
             }
@@ -258,8 +287,7 @@
     }
 
     private static void checkFunctionParameters(final String params) {
-        final Source src = sourceFor("<function>", params);
-        final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
+        final Parser parser = getParser(params);
         try {
             parser.parseFormalParameterList();
         } catch (final ParserException pe) {
@@ -268,12 +296,16 @@
     }
 
     private static void checkFunctionBody(final String funcBody) {
-        final Source src = sourceFor("<function>", funcBody);
-        final Parser parser = new Parser(Global.getEnv(), src, new Context.ThrowErrorManager());
+        final Parser parser = getParser(funcBody);
         try {
             parser.parseFunctionBody();
         } catch (final ParserException pe) {
             pe.throwAsEcmaException();
         }
     }
+
+    private static Parser getParser(final String sourceText) {
+        final ScriptEnvironment env = Global.getEnv();
+        return new Parser(env, sourceFor("<function>", sourceText), new Context.ThrowErrorManager(), env._strict, null);
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
index f6aa205..ad61cbd 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt16Array.java
@@ -25,15 +25,23 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.ShortBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Int16 array for the TypedArray extension
@@ -56,37 +64,95 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeInt16Array(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Int16ArrayData(buffer, byteOffset, length);
+        public Int16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Int16ArrayData(nb.asShortBuffer(), start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Int16Array";
         }
     };
 
-    private static final class Int16ArrayData extends ArrayDataImpl {
-        private Int16ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Int16ArrayData extends TypedArrayData<ShortBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "getElem", int.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+        private Int16ArrayData(final ShortBuffer nb, final int start, final int end) {
+            super(((ShortBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            return byteArray[byteIndex  ]       & (short)0x00ff |
-                   byteArray[byteIndex+1] <<  8 & (short)0xff00 ;
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private int getElem(final int index) {
+            try {
+                return nb.get(index);
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                nb.put(index, (short)elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected void setImpl(final int index, final int value) {
-            final int byteIndex = byteIndex(index);
-            @SuppressWarnings("MismatchedReadAndWriteOfArray")
-            final byte[] byteArray = buffer.getByteArray();
-            byteArray[byteIndex  ] = (byte)(value       & 0xff);
-            byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
+        public int getInt(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public long getLong(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toInt32(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, (int)value, strict);
         }
     }
 
@@ -101,7 +167,7 @@
      */
     @Constructor(arity = 1)
     public static NativeInt16Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeInt16Array)constructorImpl(args, FACTORY);
+        return (NativeInt16Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeInt16Array(final NativeArrayBuffer buffer, final int byteOffset, final int byteLength) {
@@ -109,11 +175,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Int16Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
index 643bd81..b018f04 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt32Array.java
@@ -25,15 +25,23 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.IntBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Int32 array for the TypedArray extension
@@ -55,41 +63,94 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeInt32Array(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Int32ArrayData(buffer, byteOffset, length);
+        public Int32ArrayData createArrayData(final ByteBuffer nb, final int start, final int length) {
+            return new Int32ArrayData(nb.asIntBuffer(), start, length);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Int32Array";
         }
     };
 
-    private static final class Int32ArrayData extends ArrayDataImpl {
-        private Int32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Int32ArrayData extends TypedArrayData<IntBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int32ArrayData.class, "getElem", int.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+        private Int32ArrayData(final IntBuffer nb, final int start, final int end) {
+            super(((IntBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            return byteArray[byteIndex  ]       & 0x0000_00ff |
-                   byteArray[byteIndex+1] <<  8 & 0x0000_ff00 |
-                   byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
-                   byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private int getElem(final int index) {
+            try {
+                return nb.get(index);
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                nb.put(index, elem);
+               } catch (final IndexOutOfBoundsException e) {
+                   if (index < 0) {
+                      throw new ClassCastException();
+                 }
+            }
         }
 
         @Override
-        protected void setImpl(final int index, final int value) {
-            final int byteIndex = byteIndex(index);
-            @SuppressWarnings("MismatchedReadAndWriteOfArray")
-            final byte[] byteArray = buffer.getByteArray();
-            byteArray[byteIndex  ] = (byte)(value        & 0xff);
-            byteArray[byteIndex+1] = (byte)(value >>>  8 & 0xff);
-            byteArray[byteIndex+2] = (byte)(value >>> 16 & 0xff);
-            byteArray[byteIndex+3] = (byte)(value >>> 24 & 0xff);
+        public int getInt(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public long getLong(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toInt32(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, (int)value, strict);
         }
     }
 
@@ -104,7 +165,7 @@
      */
     @Constructor(arity = 1)
     public static NativeInt32Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeInt32Array)constructorImpl(args, FACTORY);
+        return (NativeInt32Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeInt32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -112,11 +173,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Int32Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
index 5822c6d..6f9f6e7 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeInt8Array.java
@@ -25,15 +25,22 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Int8Array for the TypedArray extension
@@ -57,32 +64,97 @@
         }
 
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Int8ArrayData(buffer, byteOffset, length);
+        public Int8ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Int8ArrayData(nb, start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Int8Array";
         }
     };
 
-    private static final class Int8ArrayData extends ArrayDataImpl {
-        private Int8ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Int8ArrayData extends TypedArrayData<ByteBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Int8ArrayData.class, "getElem", int.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Int8ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+        private Int8ArrayData(final ByteBuffer nb, final int start, final int end) {
+            super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            return buffer.getByteArray()[byteIndex(index)];
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private int getElem(final int index) {
+            try {
+                return nb.get(index);
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                nb.put(index, (byte)elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected void setImpl(final int index, final int value) {
-            buffer.getByteArray()[byteIndex(index)] = (byte)value;
+        public int getInt(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public long getLong(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toInt32(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, (int)value, strict);
         }
     }
 
+
     /**
      * Constructor
      *
@@ -94,7 +166,7 @@
      */
     @Constructor(arity = 1)
     public static NativeInt8Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeInt8Array)constructorImpl(args, FACTORY);
+        return (NativeInt8Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeInt8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -102,11 +174,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Int8Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
index 84036a3..134ff8d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSAdapter.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -38,6 +38,7 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.runtime.FindProperty;
@@ -46,8 +47,8 @@
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
-import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.scripts.JO;
 
 /**
@@ -168,63 +169,63 @@
     }
 
     @Override
-    public int getInt(final Object key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+    public int getInt(final Object key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
     }
 
     @Override
-    public int getInt(final double key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+    public int getInt(final double key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
     }
 
     @Override
-    public int getInt(final long key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+    public int getInt(final long key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
     }
 
     @Override
-    public int getInt(final int key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key) : callAdapteeInt(__get__, key);
+    public int getInt(final int key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getInt(key, programPoint) : callAdapteeInt(programPoint, __get__, key);
     }
 
     @Override
-    public long getLong(final Object key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+    public long getLong(final Object key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
     }
 
     @Override
-    public long getLong(final double key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+    public long getLong(final double key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
     }
 
     @Override
-    public long getLong(final long key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+    public long getLong(final long key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
     }
 
     @Override
-    public long getLong(final int key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key) : callAdapteeLong(__get__, key);
+    public long getLong(final int key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getLong(key, programPoint) : callAdapteeLong(programPoint, __get__, key);
     }
 
     @Override
-    public double getDouble(final Object key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+    public double getDouble(final Object key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
     }
 
     @Override
-    public double getDouble(final double key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+    public double getDouble(final double key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
     }
 
     @Override
-    public double getDouble(final long key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+    public double getDouble(final long key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
     }
 
     @Override
-    public double getDouble(final int key) {
-        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key) : callAdapteeDouble(__get__, key);
+    public double getDouble(final int key, final int programPoint) {
+        return (overrides && super.hasOwnProperty(key)) ? super.getDouble(key, programPoint) : callAdapteeDouble(programPoint, __get__, key);
     }
 
     @Override
@@ -577,7 +578,7 @@
     }
 
     @Override
-    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         return findHook(desc, __new__, false);
     }
 
@@ -625,8 +626,8 @@
                     // to name. Probably not a big deal, but if we can ever make it leaner, it'd be nice.
                     return new GuardedInvocation(MH.dropArguments(MH.constant(Object.class,
                             func.makeBoundFunction(this, new Object[] { name })), 0, Object.class),
-                            adaptee.getProtoSwitchPoint(__call__, find.getOwner()),
-                            testJSAdaptor(adaptee, null, null, null));
+                            testJSAdaptor(adaptee, null, null, null),
+                            adaptee.getProtoSwitchPoint(__call__, find.getOwner()));
                 }
             }
             throw typeError("no.such.function", desc.getNameToken(2), ScriptRuntime.safeToString(this));
@@ -658,16 +659,16 @@
         return callAdaptee(UNDEFINED, name, args);
     }
 
-    private double callAdapteeDouble(final String name, final Object... args) {
-        return JSType.toNumber(callAdaptee(name, args));
+    private double callAdapteeDouble(final int programPoint, final String name, final Object... args) {
+        return JSType.toNumberMaybeOptimistic(callAdaptee(name, args), programPoint);
     }
 
-    private long callAdapteeLong(final String name, final Object... args) {
-        return JSType.toLong(callAdaptee(name, args));
+    private long callAdapteeLong(final int programPoint, final String name, final Object... args) {
+        return JSType.toLongMaybeOptimistic(callAdaptee(name, args), programPoint);
     }
 
-    private int callAdapteeInt(final String name, final Object... args) {
-        return JSType.toInt32(callAdaptee(name, args));
+    private int callAdapteeInt(final int programPoint, final String name, final Object... args) {
+        return JSType.toInt32MaybeOptimistic(callAdaptee(name, args), programPoint);
     }
 
     private Object callAdaptee(final Object retValue, final String name, final Object... args) {
@@ -696,8 +697,8 @@
                 if (methodHandle != null) {
                     return new GuardedInvocation(
                             methodHandle,
-                            adaptee.getProtoSwitchPoint(hook, findData.getOwner()),
-                            testJSAdaptor(adaptee, findData.getGetter(Object.class), findData.getOwner(), func));
+                            testJSAdaptor(adaptee, findData.getGetter(Object.class, UnwarrantedOptimismException.INVALID_PROGRAM_POINT), findData.getOwner(), func),
+                            adaptee.getProtoSwitchPoint(hook, findData.getOwner()));
                 }
              }
         }
@@ -709,7 +710,7 @@
             final MethodHandle methodHandle = hook.equals(__put__) ?
             MH.asType(Lookup.EMPTY_SETTER, type) :
             Lookup.emptyGetter(type.returnType());
-            return new GuardedInvocation(methodHandle, adaptee.getProtoSwitchPoint(hook, null), testJSAdaptor(adaptee, null, null, null));
+            return new GuardedInvocation(methodHandle, testJSAdaptor(adaptee, null, null, null), adaptee.getProtoSwitchPoint(hook, null));
         }
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java
index 344b6da..2578d39 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java
@@ -171,7 +171,7 @@
         }
 
         if (modSpace instanceof Number) {
-            int indent = Math.min(10, JSType.toInteger(modSpace));
+            final int indent = Math.min(10, JSType.toInteger(modSpace));
             if (indent < 1) {
                 gap = "";
             } else {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
index 7879bab..4395e08 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java
@@ -36,6 +36,7 @@
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.api.scripting.JSObject;
+import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
@@ -44,6 +45,7 @@
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ListAdapter;
 import jdk.nashorn.internal.runtime.PropertyMap;
+import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -80,6 +82,73 @@
     }
 
     /**
+     * Returns synchronized wrapper version of the given ECMAScript function.
+     * @param self not used
+     * @param func the ECMAScript function whose synchronized version is returned.
+     * @param obj the object (i.e, lock) on which the function synchronizes.
+     * @return synchronized wrapper version of the given ECMAScript function.
+     */
+    @Function(name="synchronized", attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static Object synchronizedFunc(final Object self, final Object func, final Object obj) {
+        return ScriptUtils.makeSynchronizedFunction(func, obj);
+    }
+
+    /**
+     * Returns true if the specified object is a Java method.
+     * @param self not used
+     * @param obj the object that is checked if it is a Java method object or not
+     * @return tells whether given object is a Java method object or not.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isJavaMethod(final Object self, final Object obj) {
+        return Bootstrap.isDynamicMethod(obj);
+    }
+
+    /**
+     * Returns true if the specified object is a java function (but not script function)
+     * @param self not used
+     * @param obj the object that is checked if it is a Java function or not
+     * @return tells whether given object is a Java function or not
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isJavaFunction(final Object self, final Object obj) {
+        return Bootstrap.isCallable(obj) && !(obj instanceof ScriptFunction);
+    }
+
+    /**
+     * Returns true if the specified object is a Java object but not a script object
+     * @param self not used
+     * @param obj the object that is checked
+     * @return tells whether given object is a Java object but not a script object
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isJavaObject(final Object self, final Object obj) {
+        return obj != null && !(obj instanceof ScriptObject);
+    }
+
+    /**
+     * Returns true if the specified object is a ECMAScript object, that is an instance of {@link ScriptObject}.
+     * @param self not used
+     * @param obj the object that is checked if it is a ECMAScript object or not
+     * @return tells whether given object is a ECMAScript object or not.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isScriptObject(final Object self, final Object obj) {
+        return obj instanceof ScriptObject;
+    }
+
+    /**
+     * Returns true if the specified object is a ECMAScript function, that is an instance of {@link ScriptFunction}.
+     * @param self not used
+     * @param obj the object that is checked if it is a ECMAScript function or not
+     * @return tells whether given object is a ECMAScript function or not.
+     */
+    @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
+    public static boolean isScriptFunction(final Object self, final Object obj) {
+        return obj instanceof ScriptFunction;
+    }
+
+    /**
      * <p>
      * Given a name of a Java type, returns an object representing that type in Nashorn. The Java class of the objects
      * used to represent Java types in Nashorn is not {@link java.lang.Class} but rather {@link StaticClass}. They are
@@ -414,7 +483,7 @@
         final Context ctx = Global.getThisContext();
         try {
             return ctx.findClass(typeName);
-        } catch(ClassNotFoundException e) {
+        } catch(final ClassNotFoundException e) {
             // The logic below compensates for a frequent user error - when people use dot notation to separate inner
             // class names, i.e. "java.lang.Character.UnicodeBlock" vs."java.lang.Character$UnicodeBlock". The logic
             // below will try alternative class names, replacing dots at the end of the name with dollar signs.
@@ -429,7 +498,7 @@
                 nextName.setCharAt(lastDot, '$');
                 try {
                     return ctx.findClass(nextName.toString());
-                } catch(ClassNotFoundException cnfe) {
+                } catch(final ClassNotFoundException cnfe) {
                     // Intentionally ignored, so the loop retries with the next name
                 }
             }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
index 40ecbff..1443c94 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJavaImporter.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.GuardedInvocation;
@@ -37,6 +39,7 @@
 import jdk.nashorn.internal.runtime.NativeJavaPackage;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
 /**
  * This is "JavaImporter" constructor. This constructor allows you to use Java types omitting explicit package names.
@@ -131,8 +134,12 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String name) {
-        return createProperty(name);
+    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
+        final Object retval = createProperty(name);
+        if (isValid(programPoint)) {
+            throw new UnwarrantedOptimismException(retval, programPoint);
+        }
+        return retval;
     }
 
     private boolean createAndSetProperty(final CallSiteDescriptor desc) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java b/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java
index ec53965..83b336c 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeMath.java
@@ -489,6 +489,20 @@
     }
 
     /**
+     * ECMA 15.8.2.11 max(x) - specialized version for two Object args
+     *
+     * @param self  self reference
+     * @param x     first argument
+     * @param y     second argument
+     *
+     * @return largest value of x and y
+     */
+    @SpecializedFunction
+    public static double max(final Object self, final Object x, final Object y) {
+        return Math.max(JSType.toNumber(x), JSType.toNumber(y));
+    }
+
+    /**
      * ECMA 15.8.2.12 min(x)
      *
      * @param self  self reference
@@ -567,6 +581,20 @@
     }
 
     /**
+     * ECMA 15.8.2.12 min(x) - specialized version for two Object args
+     *
+     * @param self  self reference
+     * @param x     first argument
+     * @param y     second argument
+     *
+     * @return smallest value of x and y
+     */
+    @SpecializedFunction
+    public static double min(final Object self, final Object x, final Object y) {
+        return Math.min(JSType.toNumber(x), JSType.toNumber(y));
+    }
+
+    /**
      * ECMA 15.8.2.13 pow(x,y)
      *
      * @param self  self reference
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java
index a95587e..b4cff41 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeNumber.java
@@ -25,12 +25,10 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
-import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsLong;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -44,6 +42,7 @@
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
+import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
 import jdk.nashorn.internal.objects.annotations.Where;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
@@ -84,8 +83,6 @@
     public static final double POSITIVE_INFINITY = Double.POSITIVE_INFINITY;
 
     private final double  value;
-    private final boolean isInt;
-    private final boolean isLong;
 
     // initialized by nasgen
     private static PropertyMap $nasgenmap$;
@@ -93,8 +90,6 @@
     private NativeNumber(final double value, final ScriptObject proto, final PropertyMap map) {
         super(proto, map);
         this.value = value;
-        this.isInt  = isRepresentableAsInt(value);
-        this.isLong = isRepresentableAsLong(value);
     }
 
     NativeNumber(final double value, final Global global) {
@@ -132,30 +127,6 @@
         return value;
     }
 
-    /**
-     * Get the value of this Number as a {@code int}
-     * @return an {@code int} representing the Number value
-     * @throws ClassCastException If number is not representable as an {@code int}
-     */
-    public int intValue() throws ClassCastException {
-        if (isInt) {
-            return (int)value;
-        }
-        throw new ClassCastException();
-    }
-
-    /**
-     * Get the value of this Number as a {@code long}
-     * @return a {@code long} representing the Number value
-     * @throws ClassCastException If number is not representable as an {@code long}
-     */
-    public long longValue() throws ClassCastException {
-        if (isLong) {
-            return (long)value;
-        }
-        throw new ClassCastException();
-    }
-
     @Override
     public String getClassName() {
         return "Number";
@@ -186,8 +157,20 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static String toFixed(final Object self, final Object fractionDigits) {
-        final int f = JSType.toInteger(fractionDigits);
-        if (f < 0 || f > 20) {
+        return toFixed(self, JSType.toInteger(fractionDigits));
+    }
+
+    /**
+     * ECMA 15.7.4.5 Number.prototype.toFixed (fractionDigits) specialized for int fractionDigits
+     *
+     * @param self           self reference
+     * @param fractionDigits how many digits should be after the decimal point, 0 if undefined
+     *
+     * @return number in decimal fixed point notation
+     */
+    @SpecializedFunction
+    public static String toFixed(final Object self, final int fractionDigits) {
+        if (fractionDigits < 0 || fractionDigits > 20) {
             throw rangeError("invalid.fraction.digits", "toFixed");
         }
 
@@ -201,8 +184,8 @@
         }
 
         final NumberFormat format = NumberFormat.getNumberInstance(Locale.US);
-        format.setMinimumFractionDigits(f);
-        format.setMaximumFractionDigits(f);
+        format.setMinimumFractionDigits(fractionDigits);
+        format.setMaximumFractionDigits(fractionDigits);
         format.setGroupingUsed(false);
 
         return format.format(x);
@@ -240,7 +223,7 @@
      * ECMA 15.7.4.7 Number.prototype.toPrecision (precision)
      *
      * @param self      self reference
-     * @param precision use {@code precision - 1} digits after the significand's decimal point or call {@link NativeDate#toString} if undefined
+     * @param precision use {@code precision - 1} digits after the significand's decimal point or call {@link JSType#toString} if undefined
      *
      * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
      */
@@ -250,8 +233,23 @@
         if (precision == UNDEFINED) {
             return JSType.toString(x);
         }
+        return (toPrecision(x, JSType.toInteger(precision)));
+    }
 
-        final int p = JSType.toInteger(precision);
+    /**
+     * ECMA 15.7.4.7 Number.prototype.toPrecision (precision) specialized f
+     *
+     * @param self      self reference
+     * @param precision use {@code precision - 1} digits after the significand's decimal point.
+     *
+     * @return number in decimal exponentiation notation or decimal fixed notation depending on {@code precision}
+     */
+    @SpecializedFunction
+    public static String toPrecision(final Object self, final int precision) {
+        return toPrecision(getNumberValue(self), precision);
+    }
+
+    private static String toPrecision(final double x, final int p) {
         if (Double.isNaN(x)) {
             return "NaN";
         } else if (Double.isInfinite(x)) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
index 4fd8aeb..5667e6a 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeObject.java
@@ -75,7 +75,10 @@
  */
 @ScriptClass("Object")
 public final class NativeObject {
+    /** Methodhandle to proto getter */
     public static final MethodHandle GET__PROTO__ = findOwnMH("get__proto__", ScriptObject.class, Object.class);
+
+    /** Methodhandle to proto setter */
     public static final MethodHandle SET__PROTO__ = findOwnMH("set__proto__", Object.class, Object.class, Object.class);
 
     private static final Object TO_STRING = new Object();
@@ -94,9 +97,7 @@
     private static ScriptObject get__proto__(final Object self) {
         // See ES6 draft spec: B.2.2.1.1 get Object.prototype.__proto__
         // Step 1 Let O be the result of calling ToObject passing the this.
-        final Object obj = Global.toObject(self);
-        Global.checkObject(obj);
-        final ScriptObject sobj = (ScriptObject)obj;
+        final ScriptObject sobj = Global.checkObject(Global.toObject(self));
         return sobj.getProto();
     }
 
@@ -282,8 +283,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static ScriptObject defineProperty(final Object self, final Object obj, final Object prop, final Object attr) {
-        Global.checkObject(obj);
-        final ScriptObject sobj = (ScriptObject)obj;
+        final ScriptObject sobj = Global.checkObject(obj);
         sobj.defineOwnProperty(JSType.toString(prop), attr, true);
         return sobj;
     }
@@ -298,9 +298,7 @@
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static ScriptObject defineProperties(final Object self, final Object obj, final Object props) {
-        Global.checkObject(obj);
-
-        final ScriptObject sobj     = (ScriptObject)obj;
+        final ScriptObject sobj     = Global.checkObject(obj);
         final Object       propsObj = Global.toObject(props);
 
         if (propsObj instanceof ScriptObject) {
@@ -454,18 +452,17 @@
      */
     @Constructor
     public static Object construct(final boolean newObj, final Object self, final Object value) {
-        final JSType type = JSType.of(value);
+        final JSType type = JSType.ofNoFunction(value);
 
         // Object(null), Object(undefined), Object() are same as "new Object()"
 
-        if (newObj || (type == JSType.NULL || type == JSType.UNDEFINED)) {
+        if (newObj || type == JSType.NULL || type == JSType.UNDEFINED) {
             switch (type) {
             case BOOLEAN:
             case NUMBER:
             case STRING:
                 return Global.toObject(value);
             case OBJECT:
-            case FUNCTION:
                 return value;
             case NULL:
             case UNDEFINED:
@@ -546,7 +543,7 @@
         final Object key = JSType.toPrimitive(v, String.class);
         final Object obj = Global.toObject(self);
 
-        return (obj instanceof ScriptObject) && ((ScriptObject)obj).hasOwnProperty(key);
+        return obj instanceof ScriptObject && ((ScriptObject)obj).hasOwnProperty(key);
     }
 
     /**
@@ -660,25 +657,29 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
     public static Object bindProperties(final Object self, final Object target, final Object source) {
         // target object has to be a ScriptObject
-        Global.checkObject(target);
+        final ScriptObject targetObj = Global.checkObject(target);
         // check null or undefined source object
         Global.checkObjectCoercible(source);
 
-        final ScriptObject targetObj = (ScriptObject)target;
-
         if (source instanceof ScriptObject) {
-            final ScriptObject sourceObj = (ScriptObject)source;
-            final Property[] properties = sourceObj.getMap().getProperties();
+            final ScriptObject sourceObj  = (ScriptObject)source;
+
+            final PropertyMap  sourceMap  = sourceObj.getMap();
+            final Property[]   properties = sourceMap.getProperties();
+            //replace the map and blow up everything to objects to work with dual fields :-(
 
             // filter non-enumerable properties
             final ArrayList<Property> propList = new ArrayList<>();
-            for (Property prop : properties) {
+            for (final Property prop : properties) {
                 if (prop.isEnumerable()) {
+                    final Object value = sourceObj.get(prop.getKey());
+                    prop.setCurrentType(Object.class);
+                    prop.setValue(sourceObj, sourceObj, value, false);
                     propList.add(prop);
                 }
             }
 
-            if (! propList.isEmpty()) {
+            if (!propList.isEmpty()) {
                 targetObj.addBoundProperties(sourceObj, propList.toArray(new Property[propList.size()]));
             }
         } else if (source instanceof ScriptObjectMirror) {
@@ -696,7 +697,7 @@
                 final String name = keys[idx];
                 final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
                 final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
-                props[idx] = (AccessorProperty.create(name, 0, getter, setter));
+                props[idx] = AccessorProperty.create(name, 0, getter, setter);
             }
 
             targetObj.addBoundProperties(source, props);
@@ -715,6 +716,32 @@
         return target;
     }
 
+    /**
+     * Binds the source mirror object's properties to the target object. Binding
+     * properties allows two-way read/write for the properties of the source object.
+     * All inherited, enumerable properties are also bound. This method is used to
+     * to make 'with' statement work with ScriptObjectMirror as scope object.
+     *
+     * @param target the target object to which the source object's properties are bound
+     * @param source the source object whose properties are bound to the target
+     * @return the target object after property binding
+     */
+    public static Object bindAllProperties(final ScriptObject target, final ScriptObjectMirror source) {
+        final Set<String> keys = source.keySet();
+        // make accessor properties using dynamic invoker getters and setters
+        final AccessorProperty[] props = new AccessorProperty[keys.size()];
+        int idx = 0;
+        for (final String name : keys) {
+            final MethodHandle getter = Bootstrap.createDynamicInvoker("dyn:getMethod|getProp|getElem:" + name, MIRROR_GETTER_TYPE);
+            final MethodHandle setter = Bootstrap.createDynamicInvoker("dyn:setProp|setElem:" + name, MIRROR_SETTER_TYPE);
+            props[idx] = AccessorProperty.create(name, 0, getter, setter);
+            idx++;
+        }
+
+        target.addBoundProperties(source, props);
+        return target;
+    }
+
     private static void bindBeanProperties(final ScriptObject targetObj, final Object source,
             final Collection<String> readablePropertyNames, final Collection<String> writablePropertyNames,
             final Collection<String> methodNames) {
@@ -772,7 +799,7 @@
         targetObj.addBoundProperties(source, properties.toArray(new AccessorProperty[properties.size()]));
     }
 
-    private static MethodHandle getBoundBeanMethodGetter(Object source, MethodHandle methodGetter) {
+    private static MethodHandle getBoundBeanMethodGetter(final Object source, final MethodHandle methodGetter) {
         try {
             // NOTE: we're relying on the fact that "dyn:getMethod:..." return value is constant for any given method
             // name and object linked with BeansLinker. (Actually, an even stronger assumption is true: return value is
@@ -781,7 +808,7 @@
                     Bootstrap.bindDynamicMethod(methodGetter.invoke(source), source)), 0, Object.class);
         } catch(RuntimeException|Error e) {
             throw e;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
@@ -794,10 +821,10 @@
             assert passesGuard(source, inv.getGuard());
         } catch(RuntimeException|Error e) {
             throw e;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
-        assert inv.getSwitchPoint() == null; // Linkers in Dynalink's beans package don't use switchpoints.
+        assert inv.getSwitchPoints() == null; // Linkers in Dynalink's beans package don't use switchpoints.
         // We discard the guard, as all method handles will be bound to a specific object.
         return inv.getInvocation();
     }
@@ -806,12 +833,12 @@
         return guard == null || (boolean)guard.invoke(obj);
     }
 
-    private static LinkRequest createLinkRequest(String operation, MethodType methodType, Object source) {
+    private static LinkRequest createLinkRequest(final String operation, final MethodType methodType, final Object source) {
         return new LinkRequestImpl(CallSiteDescriptorFactory.create(MethodHandles.publicLookup(), operation,
-                methodType), false, source);
+                methodType), null, 0, false, source);
     }
 
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-       return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
+        return MH.findStatic(MethodHandles.lookup(), NativeObject.class, name, MH.type(rtype, types));
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
index 34657d2..01806d4 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java
@@ -28,10 +28,11 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
+import java.lang.invoke.MethodHandle;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
-
+import java.util.concurrent.Callable;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -44,13 +45,14 @@
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.regexp.RegExp;
-import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
-import jdk.nashorn.internal.runtime.regexp.RegExpResult;
-import jdk.nashorn.internal.runtime.regexp.RegExpMatcher;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.regexp.RegExp;
+import jdk.nashorn.internal.runtime.regexp.RegExpFactory;
+import jdk.nashorn.internal.runtime.regexp.RegExpMatcher;
+import jdk.nashorn.internal.runtime.regexp.RegExpResult;
 
 /**
  * ECMA 15.10 RegExp Objects.
@@ -211,7 +213,7 @@
      * @param string pattern string
      * @return flat regexp
      */
-    static NativeRegExp flatRegExp(String string) {
+    static NativeRegExp flatRegExp(final String string) {
         // escape special characters
         StringBuilder sb = null;
         final int length = string.length();
@@ -379,7 +381,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "input")
-    public static Object getLastInput(Object self) {
+    public static Object getLastInput(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getInput();
     }
@@ -390,7 +392,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "multiline")
-    public static Object getLastMultiline(Object self) {
+    public static Object getLastMultiline(final Object self) {
         return false; // doesn't ever seem to become true and isn't documented anyhwere
     }
 
@@ -400,7 +402,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "lastMatch")
-    public static Object getLastMatch(Object self) {
+    public static Object getLastMatch(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(0);
     }
@@ -411,7 +413,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "lastParen")
-    public static Object getLastParen(Object self) {
+    public static Object getLastParen(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getLastParen();
     }
@@ -422,7 +424,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "leftContext")
-    public static Object getLeftContext(Object self) {
+    public static Object getLeftContext(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getInput().substring(0, match.getIndex());
     }
@@ -433,7 +435,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "rightContext")
-    public static Object getRightContext(Object self) {
+    public static Object getRightContext(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getInput().substring(match.getIndex() + match.length());
     }
@@ -444,7 +446,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$1")
-    public static Object getGroup1(Object self) {
+    public static Object getGroup1(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(1);
     }
@@ -455,7 +457,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$2")
-    public static Object getGroup2(Object self) {
+    public static Object getGroup2(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(2);
     }
@@ -466,7 +468,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$3")
-    public static Object getGroup3(Object self) {
+    public static Object getGroup3(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(3);
     }
@@ -477,7 +479,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$4")
-    public static Object getGroup4(Object self) {
+    public static Object getGroup4(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(4);
     }
@@ -488,7 +490,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$5")
-    public static Object getGroup5(Object self) {
+    public static Object getGroup5(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(5);
     }
@@ -499,7 +501,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$6")
-    public static Object getGroup6(Object self) {
+    public static Object getGroup6(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(6);
     }
@@ -510,7 +512,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$7")
-    public static Object getGroup7(Object self) {
+    public static Object getGroup7(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(7);
     }
@@ -521,7 +523,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$8")
-    public static Object getGroup8(Object self) {
+    public static Object getGroup8(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(8);
     }
@@ -532,7 +534,7 @@
      * @return last regexp input
      */
     @Getter(where = Where.CONSTRUCTOR, attributes = Attribute.CONSTANT, name = "$9")
-    public static Object getGroup9(Object self) {
+    public static Object getGroup9(final Object self) {
         final RegExpResult match = Global.instance().getLastRegExpResult();
         return match == null ? "" : match.getGroup(9);
     }
@@ -569,7 +571,7 @@
     }
 
     // String.prototype.split method ignores the global flag and should not update lastIndex property.
-    private RegExpResult execSplit(final String string, int start) {
+    private RegExpResult execSplit(final String string, final int start) {
         if (start < 0 || start > string.length()) {
             return null;
         }
@@ -596,7 +598,7 @@
         for (int i = 0, lastGroupStart = matcher.start(); i <= groupCount; i++) {
             final int groupStart = matcher.start(i);
             if (lastGroupStart > groupStart
-                    || (groupsInNegativeLookahead != null && groupsInNegativeLookahead.isSet(i))) {
+                    || groupsInNegativeLookahead != null && groupsInNegativeLookahead.isSet(i)) {
                 // (1) ECMA 15.10.2.5 NOTE 3: need to clear Atom's captures each time Atom is repeated.
                 // (2) ECMA 15.10.2.8 NOTE 3: Backreferences to captures in (?!Disjunction) from elsewhere
                 // in the pattern always return undefined because the negative lookahead must fail.
@@ -649,7 +651,7 @@
      * @param replacement Replacement string.
      * @return String with substitutions.
      */
-    String replace(final String string, final String replacement, final ScriptFunction function) {
+    String replace(final String string, final String replacement, final ScriptFunction function) throws Throwable {
         final RegExpMatcher matcher = regexp.match(string);
 
         if (matcher == null) {
@@ -665,7 +667,8 @@
             sb.append(string, 0, matcher.start());
 
             if (function != null) {
-                sb.append(callReplaceValue(function, matcher, string));
+                final Object self = function.isStrict() ? UNDEFINED : Global.instance();
+                sb.append(callReplaceValue(getReplaceValueInvoker(), function, self, matcher, string));
             } else {
                 appendReplacement(matcher, string, replacement, sb);
             }
@@ -683,10 +686,13 @@
         int previousLastIndex = 0;
         final StringBuilder sb = new StringBuilder();
 
+        final MethodHandle invoker = function == null ? null : getReplaceValueInvoker();
+        final Object self = function == null || function.isStrict() ? UNDEFINED : Global.instance();
+
         do {
             sb.append(string, thisIndex, matcher.start());
             if (function != null) {
-                sb.append(callReplaceValue(function, matcher, string));
+                sb.append(callReplaceValue(invoker, function, self, matcher, string));
             } else {
                 appendReplacement(matcher, string, replacement, sb);
             }
@@ -746,8 +752,8 @@
                     cursor++;
                     if (cursor < replacement.length() && firstDigit < matcher.groupCount()) {
                         final int secondDigit = replacement.charAt(cursor) - '0';
-                        if ((secondDigit >= 0) && (secondDigit <= 9)) {
-                            final int newRefNum = (firstDigit * 10) + secondDigit;
+                        if (secondDigit >= 0 && secondDigit <= 9) {
+                            final int newRefNum = firstDigit * 10 + secondDigit;
                             if (newRefNum <= matcher.groupCount() && newRefNum > 0) {
                                 // $nn ($01-$99)
                                 refNum = newRefNum;
@@ -790,16 +796,26 @@
         }
     }
 
-    private String callReplaceValue(final ScriptFunction function, final RegExpMatcher matcher, final String string) {
+    private static final Object REPLACE_VALUE = new Object();
+
+    private static final MethodHandle getReplaceValueInvoker() {
+        return Global.instance().getDynamicInvoker(REPLACE_VALUE,
+                new Callable<MethodHandle>() {
+                    @Override
+                    public MethodHandle call() {
+                        return Bootstrap.createDynamicInvoker("dyn:call", String.class, ScriptFunction.class, Object.class, Object[].class);
+                    }
+                });
+    }
+
+    private String callReplaceValue(final MethodHandle invoker, final ScriptFunction function, final Object self, final RegExpMatcher matcher, final String string) throws Throwable {
         final Object[] groups = groups(matcher);
         final Object[] args   = Arrays.copyOf(groups, groups.length + 2);
 
         args[groups.length]     = matcher.start();
         args[groups.length + 1] = string;
 
-        final Object self = function.isStrict() ? UNDEFINED : Global.instance();
-
-        return JSType.toString(ScriptRuntime.apply(function, self, args));
+        return (String)invoker.invokeExact(function, self, args);
     }
 
     /**
@@ -908,7 +924,6 @@
     }
 
     private static NativeRegExp checkRegExp(final Object self) {
-        Global.checkObjectCoercible(self);
         if (self instanceof NativeRegExp) {
             return (NativeRegExp)self;
         } else if (self != null && self == Global.instance().getRegExpPrototype()) {
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
index f12cea1..ffd6055 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExpExecResult.java
@@ -32,9 +32,9 @@
 import jdk.nashorn.internal.objects.annotations.Setter;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
-import jdk.nashorn.internal.runtime.regexp.RegExpResult;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.regexp.RegExpResult;
 
 /**
  * Objects of this class are used to represent return values from
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java b/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
index dd2c281..7f32c10 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeStrictArguments.java
@@ -25,8 +25,8 @@
 
 package jdk.nashorn.internal.objects;
 
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -79,8 +79,9 @@
         final ScriptFunction func = Global.instance().getTypeErrorThrower();
         // We have to fill user accessor functions late as these are stored
         // in this object rather than in the PropertyMap of this object.
-        setUserAccessors("caller", func, func);
-        setUserAccessors("callee", func, func);
+        final int flags = Property.NOT_ENUMERABLE | Property.NOT_CONFIGURABLE;
+        initUserAccessors("caller", flags, func, func);
+        initUserAccessors("callee", flags, func, func);
 
         setArray(ArrayData.allocate(values));
         this.length = values.length;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java
index 51edf75..0ae7fdc 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeString.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeString.java
@@ -39,6 +39,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
+import java.util.Set;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -155,10 +156,9 @@
 
         if (returnType == Object.class && (self instanceof String || self instanceof ConsString)) {
             try {
-                MethodHandle mh = MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType());
-                return new GuardedInvocation(mh, NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
+                return new GuardedInvocation(MH.findStatic(MethodHandles.lookup(), NativeString.class, "get", desc.getMethodType()), NashornGuards.getInstanceOf2Guard(String.class, ConsString.class));
             } catch (final LookupException e) {
-                // Shouldn't happen. Fall back to super
+                //empty. Shouldn't happen. Fall back to super
             }
         }
         return super.findGetIndexMethod(desc, request);
@@ -236,111 +236,111 @@
     }
 
     @Override
-    public int getInt(final Object key) {
-        return JSType.toInt32(get(key));
+    public int getInt(final Object key, final int programPoint) {
+        return JSType.toInt32MaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public int getInt(final double key) {
-        return JSType.toInt32(get(key));
+    public int getInt(final double key, final int programPoint) {
+        return JSType.toInt32MaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public int getInt(final long key) {
-        return JSType.toInt32(get(key));
+    public int getInt(final long key, final int programPoint) {
+        return JSType.toInt32MaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public int getInt(final int key) {
-        return JSType.toInt32(get(key));
+    public int getInt(final int key, final int programPoint) {
+        return JSType.toInt32MaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public long getLong(final Object key) {
-        return JSType.toUint32(get(key));
+    public long getLong(final Object key, final int programPoint) {
+        return JSType.toLongMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public long getLong(final double key) {
-        return JSType.toUint32(get(key));
+    public long getLong(final double key, final int programPoint) {
+        return JSType.toLongMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public long getLong(final long key) {
-        return JSType.toUint32(get(key));
+    public long getLong(final long key, final int programPoint) {
+        return JSType.toLongMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public long getLong(final int key) {
-        return JSType.toUint32(get(key));
+    public long getLong(final int key, final int programPoint) {
+        return JSType.toLongMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public double getDouble(final Object key) {
-        return JSType.toNumber(get(key));
+    public double getDouble(final Object key, final int programPoint) {
+        return JSType.toNumberMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public double getDouble(final double key) {
-        return JSType.toNumber(get(key));
+    public double getDouble(final double key, final int programPoint) {
+        return JSType.toNumberMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public double getDouble(final long key) {
-        return JSType.toNumber(get(key));
+    public double getDouble(final long key, final int programPoint) {
+        return JSType.toNumberMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
-    public double getDouble(final int key) {
-        return JSType.toNumber(get(key));
+    public double getDouble(final int key, final int programPoint) {
+        return JSType.toNumberMaybeOptimistic(get(key), programPoint);
     }
 
     @Override
     public boolean has(final Object key) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
         final int index = ArrayIndex.getArrayIndex(primitiveKey);
-        return isValid(index) || super.has(primitiveKey);
+        return isValidStringIndex(index) || super.has(primitiveKey);
     }
 
     @Override
     public boolean has(final int key) {
-        return isValid(key) || super.has(key);
+        return isValidStringIndex(key) || super.has(key);
     }
 
     @Override
     public boolean has(final long key) {
         final int index = ArrayIndex.getArrayIndex(key);
-        return isValid(index) || super.has(key);
+        return isValidStringIndex(index) || super.has(key);
     }
 
     @Override
     public boolean has(final double key) {
         final int index = ArrayIndex.getArrayIndex(key);
-        return isValid(index) || super.has(key);
+        return isValidStringIndex(index) || super.has(key);
     }
 
     @Override
     public boolean hasOwnProperty(final Object key) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
         final int index = ArrayIndex.getArrayIndex(primitiveKey);
-        return isValid(index) || super.hasOwnProperty(primitiveKey);
+        return isValidStringIndex(index) || super.hasOwnProperty(primitiveKey);
     }
 
     @Override
     public boolean hasOwnProperty(final int key) {
-        return isValid(key) || super.hasOwnProperty(key);
+        return isValidStringIndex(key) || super.hasOwnProperty(key);
     }
 
     @Override
     public boolean hasOwnProperty(final long key) {
         final int index = ArrayIndex.getArrayIndex(key);
-        return isValid(index) || super.hasOwnProperty(key);
+        return isValidStringIndex(index) || super.hasOwnProperty(key);
     }
 
     @Override
     public boolean hasOwnProperty(final double key) {
         final int index = ArrayIndex.getArrayIndex(key);
-        return isValid(index) || super.hasOwnProperty(key);
+        return isValidStringIndex(index) || super.hasOwnProperty(key);
     }
 
     @Override
@@ -368,7 +368,7 @@
     }
 
     private boolean checkDeleteIndex(final int index, final boolean strict) {
-        if (isValid(index)) {
+        if (isValidStringIndex(index)) {
             if (strict) {
                 throw typeError("cant.delete.property", Integer.toString(index), ScriptRuntime.safeToString(this));
             }
@@ -392,10 +392,12 @@
     /**
      * return a List of own keys associated with the object.
      * @param all True if to include non-enumerable keys.
+     * @param nonEnumerable set of non-enumerable properties seen already.Used
+     * to filter out shadowed, but enumerable properties from proto children.
      * @return Array of keys.
      */
     @Override
-    public String[] getOwnKeys(final boolean all) {
+    protected String[] getOwnKeys(final boolean all, final Set<String> nonEnumerable) {
         final List<Object> keys = new ArrayList<>();
 
         // add string index keys
@@ -404,7 +406,7 @@
         }
 
         // add super class properties
-        keys.addAll(Arrays.asList(super.getOwnKeys(all)));
+        keys.addAll(Arrays.asList(super.getOwnKeys(all, nonEnumerable)));
         return keys.toArray(new String[keys.size()]);
     }
 
@@ -441,12 +443,11 @@
      * @return string with one charcode
      */
     @SpecializedFunction
-    public static String fromCharCode(final Object self, final Object value) {
-        try {
-            return "" + (char)JSType.toUint16(((Number)value).doubleValue());
-        } catch (final ClassCastException e) {
-            return fromCharCode(self, new Object[] { value });
+    public static Object fromCharCode(final Object self, final Object value) {
+        if (value instanceof Integer) {
+            return fromCharCode(self, (int)value);
         }
+        return Character.toString((char)JSType.toUint16(value));
     }
 
     /**
@@ -457,18 +458,46 @@
      */
     @SpecializedFunction
     public static String fromCharCode(final Object self, final int value) {
-        return "" + (char)(value & 0xffff);
+        return Character.toString((char)(value & 0xffff));
     }
 
     /**
-     * ECMA 15.5.3.2 - specialization for one char of long type
+     * ECMA 15.5.3.2 - specialization for two chars of int type
      * @param self  self reference
-     * @param value one argument to be interpreted as char
+     * @param ch1 first char
+     * @param ch2 second char
      * @return string with one charcode
      */
     @SpecializedFunction
-    public static String fromCharCode(final Object self, final long value) {
-        return "" + (char)((int)value & 0xffff);
+    public static Object fromCharCode(final Object self, final int ch1, final int ch2) {
+        return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff));
+    }
+
+    /**
+     * ECMA 15.5.3.2 - specialization for three chars of int type
+     * @param self  self reference
+     * @param ch1 first char
+     * @param ch2 second char
+     * @param ch3 third char
+     * @return string with one charcode
+     */
+    @SpecializedFunction
+    public static Object fromCharCode(final Object self, final int ch1, final int ch2, final int ch3) {
+        return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff));
+    }
+
+    /**
+     * ECMA 15.5.3.2 - specialization for four chars of int type
+     * @param self  self reference
+     * @param ch1 first char
+     * @param ch2 second char
+     * @param ch3 third char
+     * @param ch4 fourth char
+     * @return string with one charcode
+     */
+    @SpecializedFunction
+    public static String fromCharCode(final Object self, final int ch1, final int ch2, final int ch3, final int ch4) {
+        return Character.toString((char)(ch1 & 0xffff)) + Character.toString((char)(ch2 & 0xffff)) + Character.toString((char)(ch3 & 0xffff)) + Character.toString((char)(ch4 & 0xffff));
     }
 
     /**
@@ -479,7 +508,7 @@
      */
     @SpecializedFunction
     public static String fromCharCode(final Object self, final double value) {
-        return "" + (char)JSType.toUint16(value);
+        return Character.toString((char)JSType.toUint16(value));
     }
 
     /**
@@ -536,7 +565,7 @@
     }
 
     private static String charAtImpl(final String str, final int pos) {
-        return (pos < 0 || pos >= str.length()) ? "" : String.valueOf(str.charAt(pos));
+        return pos < 0 || pos >= str.length() ? "" : String.valueOf(str.charAt(pos));
     }
 
     /**
@@ -573,7 +602,7 @@
     }
 
     private static double charCodeAtImpl(final String str, final int pos) {
-        return (pos < 0 || pos >= str.length()) ? Double.NaN :  str.charAt(pos);
+        return pos < 0 || pos >= str.length() ? Double.NaN : str.charAt(pos);
     }
 
     /**
@@ -688,7 +717,7 @@
         collator.setStrength(Collator.IDENTICAL);
         collator.setDecomposition(Collator.CANONICAL_DECOMPOSITION);
 
-        return (double)collator.compare(str, JSType.toString(that));
+        return collator.compare(str, JSType.toString(that));
     }
 
     /**
@@ -743,9 +772,10 @@
      * @param string      item to replace
      * @param replacement item to replace it with
      * @return string after replacement
+     * @throws Throwable if replacement fails
      */
     @Function(attributes = Attribute.NOT_ENUMERABLE)
-    public static String replace(final Object self, final Object string, final Object replacement) {
+    public static String replace(final Object self, final Object string, final Object replacement) throws Throwable {
 
         final String str = checkObjectToString(self);
 
@@ -807,7 +837,7 @@
     @SpecializedFunction
     public static String slice(final Object self, final int start) {
         final String str = checkObjectToString(self);
-        final int from = (start < 0) ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
+        final int from = start < 0 ? Math.max(str.length() + start, 0) : Math.min(start, str.length());
 
         return str.substring(from);
     }
@@ -838,8 +868,8 @@
         final String str = checkObjectToString(self);
         final int len    = str.length();
 
-        final int from = (start < 0) ? Math.max(len + start, 0) : Math.min(start, len);
-        final int to   = (end < 0)   ? Math.max(len + end, 0)   : Math.min(end, len);
+        final int from = start < 0 ? Math.max(len + start, 0) : Math.min(start, len);
+        final int to   = end < 0   ? Math.max(len + end, 0)   : Math.min(end, len);
 
         return str.substring(Math.min(from, to), to);
     }
@@ -868,7 +898,7 @@
     @Function(attributes = Attribute.NOT_ENUMERABLE)
     public static ScriptObject split(final Object self, final Object separator, final Object limit) {
         final String str = checkObjectToString(self);
-        final long lim = (limit == UNDEFINED) ? JSType.MAX_UINT : JSType.toUint32(limit);
+        final long lim = limit == UNDEFINED ? JSType.MAX_UINT : JSType.toUint32(limit);
 
         if (separator == UNDEFINED) {
             return lim == 0 ? new NativeArray() : new NativeArray(new Object[]{str});
@@ -882,7 +912,7 @@
         return splitString(str, JSType.toString(separator), lim);
     }
 
-    private static ScriptObject splitString(String str, String separator, long limit) {
+    private static ScriptObject splitString(final String str, final String separator, final long limit) {
         if (separator.isEmpty()) {
             final int length = (int) Math.min(str.length(), limit);
             final Object[] array = new Object[length];
@@ -899,7 +929,7 @@
         int n = 0;
 
         while (pos < strLength && n < limit) {
-            int found = str.indexOf(separator, pos);
+            final int found = str.indexOf(separator, pos);
             if (found == -1) {
                 break;
             }
@@ -932,7 +962,7 @@
             intStart = Math.max(intStart + strLength, 0);
         }
 
-        final int intLen = Math.min(Math.max((length == UNDEFINED) ? Integer.MAX_VALUE : JSType.toInteger(length), 0), strLength - intStart);
+        final int intLen = Math.min(Math.max(length == UNDEFINED ? Integer.MAX_VALUE : JSType.toInteger(length), 0), strLength - intStart);
 
         return intLen <= 0 ? "" : str.substring(intStart, intStart + intLen);
     }
@@ -998,8 +1028,8 @@
     public static String substring(final Object self, final int start, final int end) {
         final String str = checkObjectToString(self);
         final int len = str.length();
-        final int validStart = start < 0 ? 0 : (start > len ? len : start);
-        final int validEnd   = end < 0 ? 0 : (end > len ? len : end);
+        final int validStart = start < 0 ? 0 : start > len ? len : start;
+        final int validEnd   = end < 0 ? 0 : end > len ? len : end;
 
         if (validStart < validEnd) {
             return str.substring(validStart, validEnd);
@@ -1092,7 +1122,7 @@
 
         final String str = checkObjectToString(self);
         int start = 0;
-        int end   = str.length() - 1;
+        final int end   = str.length() - 1;
 
         while (start <= end && ScriptRuntime.isJSWhitespace(str.charAt(start))) {
             start++;
@@ -1110,7 +1140,7 @@
     public static String trimRight(final Object self) {
 
         final String str = checkObjectToString(self);
-        int start = 0;
+        final int start = 0;
         int end   = str.length() - 1;
 
         while (end >= start && ScriptRuntime.isJSWhitespace(str.charAt(end))) {
@@ -1120,7 +1150,7 @@
         return str.substring(start, end + 1);
     }
 
-    private static ScriptObject newObj(final Object self, final CharSequence str) {
+    private static ScriptObject newObj(final CharSequence str) {
         return new NativeString(str);
     }
 
@@ -1137,8 +1167,8 @@
      */
     @Constructor(arity = 1)
     public static Object constructor(final boolean newObj, final Object self, final Object... args) {
-        final CharSequence str = (args.length > 0) ? JSType.toCharSequence(args[0]) : "";
-        return newObj ? newObj(self, str) : str.toString();
+        final CharSequence str = args.length > 0 ? JSType.toCharSequence(args[0]) : "";
+        return newObj ? newObj(str) : str.toString();
     }
 
     /**
@@ -1153,7 +1183,7 @@
      */
     @SpecializedConstructor
     public static Object constructor(final boolean newObj, final Object self) {
-        return newObj ? newObj(self, "") : "";
+        return newObj ? newObj("") : "";
     }
 
     /**
@@ -1170,7 +1200,7 @@
     @SpecializedConstructor
     public static Object constructor(final boolean newObj, final Object self, final Object arg) {
         final CharSequence str = JSType.toCharSequence(arg);
-        return newObj ? newObj(self, str) : str.toString();
+        return newObj ? newObj(str) : str.toString();
     }
 
     /**
@@ -1187,7 +1217,24 @@
     @SpecializedConstructor
     public static Object constructor(final boolean newObj, final Object self, final int arg) {
         final String str = JSType.toString(arg);
-        return newObj ? newObj(self, str) : str;
+        return newObj ? newObj(str) : str;
+    }
+
+    /**
+     * ECMA 15.5.2.1 new String ( [ value ] ) - special version with exactly one {@code boolean} arg
+     *
+     * Constructor
+     *
+     * @param newObj is this constructor invoked with the new operator
+     * @param self   self reference
+     * @param arg    the arg
+     *
+     * @return new NativeString containing the string representation of the arg
+     */
+    @SpecializedConstructor
+    public static Object constructor(final boolean newObj, final Object self, final boolean arg) {
+        final String str = JSType.toString(arg);
+        return newObj ? newObj(str) : str;
     }
 
     /**
@@ -1255,11 +1302,12 @@
         }
     }
 
-    private boolean isValid(final int key) {
+    private boolean isValidStringIndex(final int key) {
         return key >= 0 && key < value.length();
     }
 
     private static MethodHandle findOwnMH(final String name, final MethodType type) {
         return MH.findStatic(MethodHandles.lookup(), NativeString.class, name, type);
     }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
index 8aa3d62..68bd410 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint16Array.java
@@ -25,15 +25,23 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.CharBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Uint16 array for TypedArray extension
@@ -55,37 +63,100 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeUint16Array(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Uint16ArrayData(buffer, byteOffset, length);
+        public Uint16ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Uint16ArrayData(nb.asCharBuffer(), start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Uint16Array";
         }
     };
 
-    private static final class Uint16ArrayData extends ArrayDataImpl {
-        private Uint16ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Uint16ArrayData extends TypedArrayData<CharBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint16ArrayData.class, "getElem", int.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint16ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+        private Uint16ArrayData(final CharBuffer nb, final int start, final int end) {
+            super(((CharBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            return byteArray[byteIndex  ]       & 0x0000_00ff |
-                   byteArray[byteIndex+1] <<  8 & 0x0000_ff00 ;
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private int getElem(final int index) {
+            try {
+                return nb.get(index);
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                nb.put(index, (char)elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected void setImpl(final int index, final int value) {
-            final int byteIndex = byteIndex(index);
-            @SuppressWarnings("MismatchedReadAndWriteOfArray")
-            final byte[] byteArray = buffer.getByteArray();
-            byteArray[byteIndex  ] = (byte)(value       & 0xff);
-            byteArray[byteIndex+1] = (byte)(value >>> 8 & 0xff);
+        public boolean isUnsigned() {
+            return true;
+        }
+
+        @Override
+        public int getInt(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public long getLong(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toInt32(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, (int)value, strict);
         }
     }
 
@@ -100,7 +171,7 @@
      */
     @Constructor(arity = 1)
     public static NativeUint16Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeUint16Array)constructorImpl(args, FACTORY);
+        return (NativeUint16Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeUint16Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -108,11 +179,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Uint16Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
index 7381224..47ee08d 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint32Array.java
@@ -25,6 +25,13 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.IntBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +42,7 @@
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Uint32 array for TypedArray extension
@@ -56,55 +64,108 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteBegin, final int length) {
             return new NativeUint32Array(buffer, byteBegin, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Uint32ArrayData(buffer, byteOffset, length);
+        public Uint32ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Uint32ArrayData(nb.order(ByteOrder.nativeOrder()).asIntBuffer(), start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Uint32Array";
         }
     };
 
-    private static final class Uint32ArrayData extends ArrayDataImpl {
-        private Uint32ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Uint32ArrayData extends TypedArrayData<IntBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "getElem", long.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint32ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+        private Uint32ArrayData(final IntBuffer nb, final int start, final int end) {
+            super(((IntBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            return byteArray[byteIndex  ]       & 0x0000_00ff |
-                   byteArray[byteIndex+1] <<  8 & 0x0000_ff00 |
-                   byteArray[byteIndex+2] << 16 & 0x00ff_0000 |
-                   byteArray[byteIndex+3] << 24 & 0xff00_0000 ;
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
         }
 
         @Override
-        protected long getLongImpl(final int key) {
-            return getIntImpl(key) & JSType.MAX_UINT;
+        public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+            if (returnType == int.class) {
+                return null;
+            }
+            return getContinuousElementGetter(getClass(), GET_ELEM, returnType, programPoint);
+        }
+
+        private long getElem(final int index) {
+            try {
+                return nb.get(index) & JSType.MAX_UINT;
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                nb.put(index, elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected double getDoubleImpl(final int key) {
-            return getIntImpl(key) & JSType.MAX_UINT;
+        public boolean isUnsigned() {
+            return true;
         }
 
         @Override
-        protected Object getObjectImpl(final int key) {
-            return getIntImpl(key) & JSType.MAX_UINT;
+        public int getInt(final int index) {
+            return (int)getLong(index);
         }
 
         @Override
-        protected void setImpl(final int index, final int value) {
-            final int byteIndex = byteIndex(index);
-            final byte[] byteArray = buffer.getByteArray();
-            byteArray[byteIndex  ] = (byte)(value        & 0xff);
-            byteArray[byteIndex+1] = (byte)(value >>>  8 & 0xff);
-            byteArray[byteIndex+2] = (byte)(value >>> 16 & 0xff);
-            byteArray[byteIndex+3] = (byte)(value >>> 24 & 0xff);
+        public long getLong(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getLong(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getLong(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toInt32(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, (int)value, strict);
         }
     }
 
@@ -119,7 +180,7 @@
      */
     @Constructor(arity = 1)
     public static NativeUint32Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeUint32Array)constructorImpl(args, FACTORY);
+        return (NativeUint32Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeUint32Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -127,11 +188,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Uint32Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
index 1f30456..15e0124 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8Array.java
@@ -25,21 +25,29 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
 import jdk.nashorn.internal.objects.annotations.Property;
 import jdk.nashorn.internal.objects.annotations.ScriptClass;
 import jdk.nashorn.internal.objects.annotations.Where;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Uint8 array for TypedArray extension
  */
 @ScriptClass("Uint8Array")
 public final class NativeUint8Array extends ArrayBufferView {
+
     /**
      * The size in bytes of each element in the array.
      */
@@ -55,31 +63,102 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeUint8Array(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Uint8ArrayData(buffer, byteOffset, length);
+        public Uint8ArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Uint8ArrayData(nb, start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Uint8Array";
         }
     };
 
-    private static final class Uint8ArrayData extends ArrayDataImpl {
-        private Uint8ArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Uint8ArrayData extends TypedArrayData<ByteBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ArrayData.class, "getElem", int.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+        private Uint8ArrayData(final ByteBuffer nb, final int start, final int end) {
+            super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            return buffer.getByteArray()[byteIndex(index)] & 0xff;
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
+        }
+
+        private int getElem(final int index) {
+            try {
+                return nb.get(index) & 0xff;
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
+            }
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                nb.put(index, (byte)elem);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected void setImpl(final int index, final int value) {
-            buffer.getByteArray()[byteIndex(index)] = (byte)value;
+        public boolean isUnsigned() {
+            return true;
         }
+
+        @Override
+        public int getInt(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public long getLong(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toInt32(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
     }
 
     /**
@@ -93,7 +172,7 @@
      */
     @Constructor(arity = 1)
     public static NativeUint8Array constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeUint8Array)constructorImpl(args, FACTORY);
+        return (NativeUint8Array)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeUint8Array(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -101,11 +180,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Uint8Array";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
index d69adc1..db19ab3 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/NativeUint8ClampedArray.java
@@ -25,6 +25,13 @@
 
 package jdk.nashorn.internal.objects;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.nio.ByteBuffer;
 import jdk.nashorn.internal.objects.annotations.Attribute;
 import jdk.nashorn.internal.objects.annotations.Constructor;
 import jdk.nashorn.internal.objects.annotations.Function;
@@ -35,6 +42,7 @@
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
+import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
 
 /**
  * Uint8 clamped array for TypedArray extension
@@ -56,55 +64,148 @@
         public ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
             return new NativeUint8ClampedArray(buffer, byteOffset, length);
         }
+
         @Override
-        public ArrayData createArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
-            return new Uint8ClampedArrayData(buffer, byteOffset, length);
+        public Uint8ClampedArrayData createArrayData(final ByteBuffer nb, final int start, final int end) {
+            return new Uint8ClampedArrayData(nb, start, end);
+        }
+
+        @Override
+        public String getClassName() {
+            return "Uint8ClampedArray";
         }
     };
 
-    private static final class Uint8ClampedArrayData extends ArrayDataImpl {
-        private Uint8ClampedArrayData(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
-            super(buffer, byteOffset, elementLength);
+    private static final class Uint8ClampedArrayData extends TypedArrayData<ByteBuffer> {
+
+        private static final MethodHandle GET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "getElem", int.class, int.class).methodHandle();
+        private static final MethodHandle SET_ELEM = specialCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+        private static final MethodHandle RINT_D   = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", double.class, double.class).methodHandle();
+        private static final MethodHandle RINT_O   = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "rint", Object.class, Object.class).methodHandle();
+        private static final MethodHandle CLAMP_LONG = staticCall(MethodHandles.lookup(), Uint8ClampedArrayData.class, "clampLong", long.class, long.class).methodHandle();
+
+        private Uint8ClampedArrayData(final ByteBuffer nb, final int start, final int end) {
+            super(((ByteBuffer)nb.position(start).limit(end)).slice(), end - start);
         }
 
         @Override
-        protected int byteIndex(final int index) {
-            return index * BYTES_PER_ELEMENT + byteOffset;
+        protected MethodHandle getGetElem() {
+            return GET_ELEM;
         }
 
         @Override
-        protected int getIntImpl(final int index) {
-            return buffer.getByteArray()[byteIndex(index)] & 0xff;
+        protected MethodHandle getSetElem() {
+            return SET_ELEM;
         }
 
-        @Override
-        protected void setImpl(final int index, final int value) {
-            final byte clamped;
-            if ((value & 0xffff_ff00) == 0) {
-                clamped = (byte) value;
-            } else {
-                clamped = value < 0 ? 0 : (byte)0xff;
-            }
-            buffer.getByteArray()[byteIndex(index)] = clamped;
-        }
-
-        @Override
-        protected void setImpl(final int index, final long value) {
-            if (JSType.isRepresentableAsInt(value)) {
-                setImpl(index, (int)value);
-            } else {
-                buffer.getByteArray()[byteIndex(index)] = value > 0 ? (byte)0xff : 0;
+        private int getElem(final int index) {
+            try {
+                return nb.get(index) & 0xff;
+            } catch (final IndexOutOfBoundsException e) {
+                throw new ClassCastException(); //force relink - this works for unoptimistic too
             }
         }
 
         @Override
-        protected void setImpl(final int key, final double value) {
-            setImpl(key, (int)Math.rint(value));
+        public MethodHandle getElementSetter(final Class<?> elementType) {
+            final MethodHandle setter = super.getElementSetter(elementType); //getContinuousElementSetter(getClass(), setElem(), elementType);
+            if (setter != null) {
+                if (elementType == Object.class) {
+                    return MH.filterArguments(setter, 2, RINT_O);
+                } else if (elementType == double.class) {
+                    return MH.filterArguments(setter, 2, RINT_D);
+                } else if (elementType == long.class) {
+                    return MH.filterArguments(setter, 2, CLAMP_LONG);
+                }
+            }
+            return setter;
+        }
+
+        private void setElem(final int index, final int elem) {
+            try {
+                final byte clamped;
+                if ((elem & 0xffff_ff00) == 0) {
+                    clamped = (byte)elem;
+                } else {
+                    clamped = elem < 0 ? 0 : (byte)0xff;
+                }
+                nb.put(index, clamped);
+            } catch (final IndexOutOfBoundsException e) {
+                //swallow valid array indexes. it's ok.
+                if (index < 0) {
+                    throw new ClassCastException();
+                }
+            }
         }
 
         @Override
-        protected void setImpl(final int key, final Object value) {
-            setImpl(key, JSType.toNumber(value));
+        public boolean isClamped() {
+            return true;
+        }
+
+        @Override
+        public boolean isUnsigned() {
+            return true;
+        }
+
+        @Override
+        public int getInt(final int index) {
+            return getElem(index);
+        }
+
+        @Override
+        public long getLong(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public double getDouble(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public Object getObject(final int index) {
+            return getInt(index);
+        }
+
+        @Override
+        public ArrayData set(final int index, final Object value, final boolean strict) {
+            return set(index, JSType.toNumber(value), strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final int value, final boolean strict) {
+            setElem(index, value);
+            return this;
+        }
+
+        @Override
+        public ArrayData set(final int index, final long value, final boolean strict) {
+            return set(index, (int)value, strict);
+        }
+
+        @Override
+        public ArrayData set(final int index, final double value, final boolean strict) {
+            return set(index, rint(value), strict);
+        }
+
+        private static double rint(final double rint) {
+            return (int)Math.rint(rint);
+        }
+
+        @SuppressWarnings("unused")
+        private static Object rint(final Object rint) {
+            return rint(JSType.toNumber(rint));
+        }
+
+        @SuppressWarnings("unused")
+        private static long clampLong(final long l) {
+            if(l < 0L) {
+                return 0L;
+            } else if(l > 0xffL) {
+                return 0xffL;
+            }
+            return l;
         }
     }
 
@@ -119,7 +220,7 @@
      */
     @Constructor(arity = 1)
     public static NativeUint8ClampedArray constructor(final boolean newObj, final Object self, final Object... args) {
-        return (NativeUint8ClampedArray)constructorImpl(args, FACTORY);
+        return (NativeUint8ClampedArray)constructorImpl(newObj, args, FACTORY);
     }
 
     NativeUint8ClampedArray(final NativeArrayBuffer buffer, final int byteOffset, final int length) {
@@ -127,11 +228,6 @@
     }
 
     @Override
-    public String getClassName() {
-        return "Uint8ClampedArray";
-    }
-
-    @Override
     protected Factory factory() {
         return FACTORY;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java b/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java
index 483f617..b119dad 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/PrototypeObject.java
@@ -25,8 +25,8 @@
 
 package jdk.nashorn.internal.objects;
 
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
diff --git a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
index dcbc7da..a52051c 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/ScriptFunctionImpl.java
@@ -30,6 +30,7 @@
 
 import java.lang.invoke.MethodHandle;
 import java.util.ArrayList;
+import jdk.nashorn.internal.runtime.AccessorProperty;
 import jdk.nashorn.internal.runtime.GlobalFunctions;
 import jdk.nashorn.internal.runtime.Property;
 import jdk.nashorn.internal.runtime.PropertyMap;
@@ -37,7 +38,6 @@
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptObject;
-import jdk.nashorn.internal.runtime.AccessorProperty;
 
 /**
  * Concrete implementation of ScriptFunction. This sets correct map for the
@@ -175,13 +175,22 @@
     private static class AnonymousFunction extends ScriptFunctionImpl {
         private static final PropertyMap anonmap$ = PropertyMap.newMap();
 
-        AnonymousFunction(final Global global) {
+        AnonymousFunction() {
             super("", GlobalFunctions.ANONYMOUS, anonmap$, null);
         }
     }
 
-    static ScriptFunctionImpl newAnonymousFunction(final Global global) {
-        return new AnonymousFunction(global);
+    static ScriptFunctionImpl newAnonymousFunction() {
+        return new AnonymousFunction();
+    }
+
+    private static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs, final int flags) {
+        final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, flags);
+        func.setPrototype(UNDEFINED);
+        // Non-constructor built-in functions do not have "prototype" property
+        func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+
+        return func;
     }
 
     /**
@@ -193,12 +202,18 @@
      * @return new ScriptFunction
      */
     static ScriptFunction makeFunction(final String name, final MethodHandle methodHandle, final MethodHandle[] specs) {
-        final ScriptFunctionImpl func = new ScriptFunctionImpl(name, methodHandle, null, specs, ScriptFunctionData.IS_BUILTIN);
-        func.setPrototype(UNDEFINED);
-        // Non-constructor built-in functions do not have "prototype" property
-        func.deleteOwnProperty(func.getMap().findProperty("prototype"));
+        return makeFunction(name, methodHandle, specs, ScriptFunctionData.IS_BUILTIN);
+    }
 
-        return func;
+    /**
+     * Factory method for non-constructor built-in, strict functions
+     *
+     * @param name   function name
+     * @param methodHandle handle for invocation
+     * @return new ScriptFunction
+     */
+    static ScriptFunction makeStrictFunction(final String name, final MethodHandle methodHandle) {
+        return makeFunction(name, methodHandle, null, ScriptFunctionData.IS_BUILTIN | ScriptFunctionData.IS_STRICT );
     }
 
     /**
@@ -226,7 +241,7 @@
      * @return a function with the specified self and parameters bound.
      */
     @Override
-    protected ScriptFunction makeBoundFunction(Object self, Object[] args) {
+    protected ScriptFunction makeBoundFunction(final Object self, final Object[] args) {
         return super.makeBoundFunction(self, args);
     }
 
@@ -272,14 +287,13 @@
 
         // We have to fill user accessor functions late as these are stored
         // in this object rather than in the PropertyMap of this object.
-
-        final ScriptFunction errorThrower = global.getTypeErrorThrower();
+        assert objectSpill == null;
+        final ScriptFunction typeErrorThrower = global.getTypeErrorThrower();
         if (findProperty("arguments", true) != null) {
-            setUserAccessors("arguments", errorThrower, errorThrower);
-        }
-
+            initUserAccessors("arguments", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+       }
         if (findProperty("caller", true) != null) {
-            setUserAccessors("caller", errorThrower, errorThrower);
-        }
+            initUserAccessors("caller", Property.NOT_CONFIGURABLE | Property.NOT_ENUMERABLE, typeErrorThrower, typeErrorThrower);
+       }
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/objects/annotations/Optimistic.java b/nashorn/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
new file mode 100644
index 0000000..09e3b2a
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/objects/annotations/Optimistic.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.objects.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The Optimistic annotation is used for builtins that can throw UnwarrantedOptimism
+ * exception if they are wrong, whose callsite is optimistic and contains a program
+ * point. Every optimistic builtin callsite needs to bind its programPoint to an
+ * argument of the implementation at compile time
+ *
+ * Typical use case would be something like: if you want to do an optimistic "push" function
+ * in NativeArray that takes an int, write
+ *
+ *  <pre>
+ *  {@literal @}SpecializedFunction {@literal @}Optimistic
+ *  public static int push(final Object self, final int x, final int programPoint) {
+ *    try {
+ *    //push code assuming that this is an int array
+ *    //return new length of array, assuming it's an int
+ *    } catch (ArrayWasWrong e) {
+ *       //undo any array modifications
+ *       throw new UnwarrantedOptimismExceptionArrayType(x, programPoint);
+ *    } catch (LengthOverFlowed e) {
+ *       //undo any array modifications
+ *       throw new UnwarratnedOptimismExceptionArrayLength(uint32lenThatOverFlowed, programPoint)
+ *    }
+ *  }
+ *  </pre>
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Optimistic {
+    //empty
+}
diff --git a/nashorn/src/jdk/nashorn/internal/objects/annotations/Property.java b/nashorn/src/jdk/nashorn/internal/objects/annotations/Property.java
index 6aec205..7da82fe 100644
--- a/nashorn/src/jdk/nashorn/internal/objects/annotations/Property.java
+++ b/nashorn/src/jdk/nashorn/internal/objects/annotations/Property.java
@@ -40,21 +40,25 @@
 public @interface Property {
     /**
      * Name of the script property. If empty, the name is inferred.
+     * @return name
      */
     public String name() default "";
 
     /**
      * Attribute flags for this function.
+     * @return attribute
      */
     public int attributes() default DEFAULT_ATTRIBUTES;
 
     /**
      * Initialize this property with the object of given class.
+     * @return class
      */
     public String clazz() default "";
 
     /**
      * Where this property lives?
+     * @return location of property
      */
     public Where where() default Where.INSTANCE;
 }
diff --git a/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java b/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
index d4a42ba..5c61396 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/AbstractParser.java
@@ -31,6 +31,8 @@
 import static jdk.nashorn.internal.parser.TokenType.EOL;
 import static jdk.nashorn.internal.parser.TokenType.IDENT;
 
+import java.util.HashMap;
+import java.util.Map;
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.LiteralNode;
 import jdk.nashorn.internal.parser.Lexer.LexerToken;
@@ -58,6 +60,9 @@
     /** Index of current token. */
     protected int k;
 
+    /** Previous token - accessible to sub classes */
+    protected long previousToken;
+
     /** Descriptor of current token. */
     protected long token;
 
@@ -85,17 +90,20 @@
     /** Is this parser running under strict mode? */
     protected boolean isStrictMode;
 
-    /** //@ sourceURL or //# sourceURL */
-    protected String sourceURL;
+    /** What should line numbers be counted from? */
+    protected final int lineOffset;
+
+    private final Map<String, String> canonicalNames = new HashMap<>();
 
     /**
      * Construct a parser.
      *
-     * @param source  Source to parse.
-     * @param errors  Error reporting manager.
-     * @param strict  True if we are in strict mode
+     * @param source     Source to parse.
+     * @param errors     Error reporting manager.
+     * @param strict     True if we are in strict mode
+     * @param lineOffset Offset from which lines should be counted
      */
-    protected AbstractParser(final Source source, final ErrorManager errors, final boolean strict) {
+    protected AbstractParser(final Source source, final ErrorManager errors, final boolean strict, final int lineOffset) {
         this.source       = source;
         this.errors       = errors;
         this.k            = -1;
@@ -103,6 +111,7 @@
         this.type         = EOL;
         this.last         = EOL;
         this.isStrictMode = strict;
+        this.lineOffset   = lineOffset;
     }
 
     /**
@@ -174,7 +183,7 @@
     // currently only @sourceURL=foo supported
     private void checkDirectiveComment() {
         // if already set, ignore this one
-        if (sourceURL != null) {
+        if (source.getExplicitURL() != null) {
             return;
         }
 
@@ -182,7 +191,7 @@
         final int len = comment.length();
         // 4 characters for directive comment marker //@\s or //#\s
         if (len > 4 && comment.substring(4).startsWith(SOURCE_URL_PREFIX)) {
-            sourceURL = comment.substring(4 + SOURCE_URL_PREFIX.length());
+            source.setExplicitURL(comment.substring(4 + SOURCE_URL_PREFIX.length()));
         }
     }
 
@@ -199,6 +208,7 @@
             // Set up next token.
             k++;
             final long lastToken = token;
+            previousToken = token;
             token = getToken(k);
             type = Token.descType(token);
 
@@ -208,7 +218,7 @@
             }
 
             if (type == EOL) {
-                line = Token.descLength(token);
+                line         = Token.descLength(token);
                 linePosition = Token.descPosition(token);
             } else {
                 start = Token.descPosition(token);
@@ -403,7 +413,7 @@
             next();
 
             // Create IDENT node.
-            return new IdentNode(identToken, finish, ident).setIsFutureStrictName();
+            return createIdentNode(identToken, finish, ident).setIsFutureStrictName();
         }
 
         // Get IDENT.
@@ -412,7 +422,22 @@
             return null;
         }
         // Create IDENT node.
-        return new IdentNode(identToken, finish, ident);
+        return createIdentNode(identToken, finish, ident);
+    }
+
+    /**
+     * Creates a new {@link IdentNode} as if invoked with a {@link IdentNode#IdentNode(long, int, String)
+     * constructor} but making sure that the {@code name} is deduplicated within this parse job.
+     * @param identToken the token for the new {@code IdentNode}
+     * @param identFinish the finish for the new {@code IdentNode}
+     * @param name the name for the new {@code IdentNode}. It will be de-duplicated.
+     * @return a newly constructed {@code IdentNode} with the specified token, finish, and name; the name will
+     * be deduplicated.
+     */
+    protected IdentNode createIdentNode(final long identToken, final int identFinish, final String name) {
+        final String existingName = canonicalNames.putIfAbsent(name, name);
+        final String canonicalName = existingName != null ? existingName : name;
+        return new IdentNode(identToken, identFinish, canonicalName);
     }
 
     /**
@@ -447,7 +472,7 @@
             final String ident = (String)getValue(identToken);
             next();
             // Create IDENT node.
-            return new IdentNode(identToken, finish, ident);
+            return createIdentNode(identToken, finish, ident);
         } else {
             expect(IDENT);
             return null;
diff --git a/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java b/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java
index 51988f6..a5cae0e 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java
@@ -57,7 +57,7 @@
      * @param errors  the error manager
      */
     public JSONParser(final Source source, final ErrorManager errors) {
-        super(source, errors, false);
+        super(source, errors, false, 0);
     }
 
     /**
@@ -160,7 +160,7 @@
                 }
 
                 // First digit of number.
-                int digit = convertDigit(ch0, 10);
+                final int digit = convertDigit(ch0, 10);
 
                 // skip first digit
                 skip(1);
diff --git a/nashorn/src/jdk/nashorn/internal/parser/Lexer.java b/nashorn/src/jdk/nashorn/internal/parser/Lexer.java
index 653f04c..1dad69e 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/Lexer.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/Lexer.java
@@ -27,8 +27,8 @@
 
 import static jdk.nashorn.internal.parser.TokenType.ADD;
 import static jdk.nashorn.internal.parser.TokenType.COMMENT;
-import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
 import static jdk.nashorn.internal.parser.TokenType.DECIMAL;
+import static jdk.nashorn.internal.parser.TokenType.DIRECTIVE_COMMENT;
 import static jdk.nashorn.internal.parser.TokenType.EOF;
 import static jdk.nashorn.internal.parser.TokenType.EOL;
 import static jdk.nashorn.internal.parser.TokenType.ERROR;
@@ -48,6 +48,7 @@
 import jdk.nashorn.internal.runtime.ECMAErrors;
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.JSErrorType;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.options.Options;
@@ -76,7 +77,7 @@
     private final boolean nested;
 
     /** Pending new line number and position. */
-    private int pendingLine;
+    int pendingLine;
 
     /** Position of last EOL + 1. */
     private int linePosition;
@@ -181,8 +182,21 @@
      * @param scripting are we in scripting mode
      */
     public Lexer(final Source source, final TokenStream stream, final boolean scripting) {
-        super(source.getContent(), 1, 0, source.getLength());
+        this(source, 0, source.getLength(), stream, scripting);
+    }
 
+    /**
+     * Contructor
+     *
+     * @param source    the source
+     * @param start     start position in source from which to start lexing
+     * @param len       length of source segment to lex
+     * @param stream    token stream to lex
+     * @param scripting are we in scripting mode
+     */
+
+    public Lexer(final Source source, final int start, final int len, final TokenStream stream, final boolean scripting) {
+        super(source.getContent(), 1, start, len);
         this.source      = source;
         this.stream      = stream;
         this.scripting   = scripting;
@@ -1609,7 +1623,7 @@
      */
     Object getValueOf(final long token, final boolean strict) {
         final int start = Token.descPosition(token);
-        final int len = Token.descLength(token);
+        final int len   = Token.descLength(token);
 
         switch (Token.descType(token)) {
         case DECIMAL:
@@ -1619,7 +1633,23 @@
         case HEXADECIMAL:
             return Lexer.valueOf(source.getString(start + 2, len - 2), 16); // number
         case FLOATING:
-            return Double.valueOf(source.getString(start, len)); // number
+            final String str   = source.getString(start, len);
+            final double value = Double.valueOf(str);
+            if (str.indexOf('.') != -1) {
+                return value; //number
+            }
+            //anything without an explicit decimal point is still subject to a
+            //"representable as int or long" check. Then the programmer does not
+            //explicitly code something as a double. For example new Color(int, int, int)
+            //and new Color(float, float, float) will get ambiguous for cases like
+            //new Color(1.0, 1.5, 1.5) if we don't respect the decimal point.
+            //yet we don't want e.g. 1e6 to be a double unnecessarily
+            if (JSType.isRepresentableAsInt(value) && !JSType.isNegativeZero(value)) {
+                return (int)value;
+            } else if (JSType.isRepresentableAsLong(value) && !JSType.isNegativeZero(value)) {
+                return (long)value;
+            }
+            return value;
         case STRING:
             return source.getString(start, len); // String
         case ESCSTRING:
diff --git a/nashorn/src/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk/nashorn/internal/parser/Parser.java
index 6ad60b5..74ab1e5 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.parser;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
 import static jdk.nashorn.internal.codegen.CompilerConstants.ANON_FUNCTION_PREFIX;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
+import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL;
+import static jdk.nashorn.internal.codegen.CompilerConstants.PROGRAM;
 import static jdk.nashorn.internal.parser.TokenType.ASSIGN;
 import static jdk.nashorn.internal.parser.TokenType.CASE;
 import static jdk.nashorn.internal.parser.TokenType.CATCH;
@@ -53,8 +53,10 @@
 import static jdk.nashorn.internal.parser.TokenType.TERNARY;
 import static jdk.nashorn.internal.parser.TokenType.WHILE;
 
+import java.util.ArrayDeque;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Deque;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -84,6 +86,7 @@
 import jdk.nashorn.internal.ir.IdentNode;
 import jdk.nashorn.internal.ir.IfNode;
 import jdk.nashorn.internal.ir.IndexNode;
+import jdk.nashorn.internal.ir.JoinPredecessorExpression;
 import jdk.nashorn.internal.ir.LabelNode;
 import jdk.nashorn.internal.ir.LexicalContext;
 import jdk.nashorn.internal.ir.LiteralNode;
@@ -103,22 +106,29 @@
 import jdk.nashorn.internal.ir.VarNode;
 import jdk.nashorn.internal.ir.WhileNode;
 import jdk.nashorn.internal.ir.WithNode;
-import jdk.nashorn.internal.runtime.DebugLogger;
+import jdk.nashorn.internal.ir.debug.ASTWriter;
+import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ErrorManager;
 import jdk.nashorn.internal.runtime.JSErrorType;
 import jdk.nashorn.internal.runtime.ParserException;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
 import jdk.nashorn.internal.runtime.ScriptEnvironment;
 import jdk.nashorn.internal.runtime.ScriptingFunctions;
 import jdk.nashorn.internal.runtime.Source;
 import jdk.nashorn.internal.runtime.Timing;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * Builds the IR.
  */
-public class Parser extends AbstractParser {
+@Logger(name="parser")
+public class Parser extends AbstractParser implements Loggable {
     private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName();
 
-    /** Current script environment. */
+    /** Current env. */
     private final ScriptEnvironment env;
 
     /** Is scripting mode. */
@@ -127,15 +137,18 @@
     private List<Statement> functionDeclarations;
 
     private final BlockLexicalContext lc = new BlockLexicalContext();
+    private final Deque<Object> defaultNames = new ArrayDeque<>();
 
     /** Namespace for function names where not explicitly given */
     private final Namespace namespace;
 
-    private static final DebugLogger LOG = new DebugLogger("parser");
+    private final DebugLogger log;
 
     /** to receive line information from Lexer when scanning multine literals. */
     protected final Lexer.LineInfoReceiver lineInfoReceiver;
 
+    private int nextFunctionId;
+
     /**
      * Constructor
      *
@@ -144,7 +157,20 @@
      * @param errors  error manager
      */
     public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors) {
-        this(env, source, errors, env._strict);
+        this(env, source, errors, env._strict, null);
+    }
+
+    /**
+     * Constructor
+     *
+     * @param env     script environment
+     * @param source  source to parse
+     * @param errors  error manager
+     * @param strict  strict
+     * @param log debug logger if one is needed
+     */
+    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final DebugLogger log) {
+        this(env, source, errors, strict, FunctionNode.FIRST_FUNCTION_ID, 0, log);
     }
 
     /**
@@ -154,11 +180,15 @@
      * @param source  source to parse
      * @param errors  error manager
      * @param strict  parser created with strict mode enabled.
+     * @param nextFunctionId  starting value for assigning new unique ids to function nodes
+     * @param lineOffset line offset to start counting lines from
+     * @param log debug logger if one is needed
      */
-    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict) {
-        super(source, errors, strict);
-        this.env       = env;
+    public Parser(final ScriptEnvironment env, final Source source, final ErrorManager errors, final boolean strict, final int nextFunctionId, final int lineOffset, final DebugLogger log) {
+        super(source, errors, strict, lineOffset);
+        this.env = env;
         this.namespace = new Namespace(env.getNamespace());
+        this.nextFunctionId    = nextFunctionId;
         this.scripting = env._scripting;
         if (this.scripting) {
             this.lineInfoReceiver = new Lexer.LineInfoReceiver() {
@@ -173,6 +203,27 @@
             // non-scripting mode script can't have multi-line literals
             this.lineInfoReceiver = null;
         }
+
+        this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    /**
+     * Sets the name for the first function. This is only used when reparsing anonymous functions to ensure they can
+     * preserve their already assigned name, as that name doesn't appear in their source text.
+     * @param name the name for the first parsed function.
+     */
+    public void setFunctionName(final String name) {
+        defaultNames.push(createIdentNode(0, 0, name));
     }
 
     /**
@@ -181,12 +232,12 @@
      * if parsing should fail
      *
      * This is the default parse call, which will name the function node
-     * "runScript" {@link CompilerConstants#RUN_SCRIPT}
+     * {code :program} {@link CompilerConstants#PROGRAM}
      *
      * @return function node resulting from successful parse
      */
     public FunctionNode parse() {
-        return parse(RUN_SCRIPT.symbolName());
+        return parse(PROGRAM.symbolName(), 0, source.getLength(), false);
     }
 
     /**
@@ -194,35 +245,44 @@
      * Errors will be thrown and the error manager will contain information
      * if parsing should fail
      *
+     * This should be used to create one and only one function node
+     *
      * @param scriptName name for the script, given to the parsed FunctionNode
+     * @param startPos start position in source
+     * @param len length of parse
+     * @param allowPropertyFunction if true, "get" and "set" are allowed as first tokens of the program, followed by
+     * a property getter or setter function. This is used when reparsing a function that can potentially be defined as a
+     * property getter or setter in an object literal.
      *
      * @return function node resulting from successful parse
      */
-    public FunctionNode parse(final String scriptName) {
-        final long t0 = Timing.isEnabled() ? System.currentTimeMillis() : 0L;
-        LOG.info(this, " begin for '", scriptName, "'");
+    public FunctionNode parse(final String scriptName, final int startPos, final int len, final boolean allowPropertyFunction) {
+        final boolean isTimingEnabled = env.isTimingEnabled();
+        final long t0 = isTimingEnabled ? System.nanoTime() : 0L;
+        log.info(this, " begin for '", scriptName, "'");
 
         try {
             stream = new TokenStream();
-            lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+            lexer  = new Lexer(source, startPos, len, stream, scripting && !env._no_syntax_extensions);
+            lexer.line = lexer.pendingLine = lineOffset + 1;
+            line = lineOffset;
 
             // Set up first token (skips opening EOL.)
             k = -1;
             next();
-
             // Begin parse.
-            return program(scriptName);
+            return program(scriptName, allowPropertyFunction);
         } catch (final Exception e) {
             handleParseException(e);
 
             return null;
         } finally {
             final String end = this + " end '" + scriptName + "'";
-            if (Timing.isEnabled()) {
-                Timing.accumulateTime(toString(), System.currentTimeMillis() - t0);
-                LOG.info(end, "' in ", (System.currentTimeMillis() - t0), " ms");
+            if (isTimingEnabled) {
+                env._timing.accumulateTime(toString(), System.nanoTime() - t0);
+                log.info(end, "' in ", Timing.toMillisPrint(System.nanoTime() - t0), " ms");
             } else {
-                LOG.info(end);
+                log.info(end);
             }
         }
     }
@@ -264,6 +324,7 @@
         try {
             stream = new TokenStream();
             lexer  = new Lexer(source, stream, scripting && !env._no_syntax_extensions);
+            final int functionLine = line;
 
             // Set up first token (skips opening EOL.)
             k = -1;
@@ -275,21 +336,23 @@
 
             FunctionNode function = newFunctionNode(
                 functionToken,
-                new IdentNode(functionToken, Token.descPosition(functionToken), RUN_SCRIPT.symbolName()),
+                new IdentNode(functionToken, Token.descPosition(functionToken), PROGRAM.symbolName()),
                 new ArrayList<IdentNode>(),
-                FunctionNode.Kind.NORMAL);
+                FunctionNode.Kind.NORMAL,
+                functionLine);
 
             functionDeclarations = new ArrayList<>();
-            sourceElements();
+            sourceElements(false);
             addFunctionDeclarations(function);
             functionDeclarations = null;
 
             expect(EOF);
 
             function.setFinish(source.getLength() - 1);
-
             function = restoreFunctionNode(function, token); //commit code
             function = function.setBody(lc, function.getBody().setNeedsScope(lc));
+
+            printAST(function);
             return function;
         } catch (final Exception e) {
             handleParseException(e);
@@ -381,7 +444,7 @@
      * @param ident Name of function.
      * @return New block.
      */
-    private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
+    private FunctionNode newFunctionNode(final long startToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine) {
         // Build function name.
         final StringBuilder sb = new StringBuilder();
 
@@ -394,26 +457,22 @@
         sb.append(ident.getName());
 
         final String name = namespace.uniqueName(sb.toString());
-        assert parentFunction != null || name.equals(RUN_SCRIPT.symbolName())  : "name = " + name;// must not rename runScript().
+        assert parentFunction != null || name.equals(PROGRAM.symbolName()) || name.startsWith(RecompilableScriptFunctionData.RECOMPILATION_PREFIX) : "name = " + name;
 
         int flags = 0;
-        if (parentFunction == null) {
-            flags |= FunctionNode.IS_PROGRAM;
-        }
         if (isStrictMode) {
             flags |= FunctionNode.IS_STRICT;
         }
-        if (env._specialize_calls != null) {
-            if (env._specialize_calls.contains(name)) {
-                flags |= FunctionNode.CAN_SPECIALIZE;
-            }
+        if (parentFunction == null) {
+            flags |= FunctionNode.IS_PROGRAM;
         }
 
         // Start new block.
-        FunctionNode functionNode =
+        final FunctionNode functionNode =
             new FunctionNode(
                 source,
-                line, //TODO?
+                nextFunctionId++,
+                functionLine,
                 token,
                 Token.descPosition(token),
                 startToken,
@@ -422,8 +481,7 @@
                 name,
                 parameters,
                 kind,
-                flags,
-                sourceURL);
+                flags);
 
         lc.push(functionNode);
         // Create new block, and just put it on the context stack, restoreFunctionNode() will associate it with the
@@ -447,9 +505,8 @@
         return lc.pop(functionNode).
             setBody(lc, newBody).
             setLastToken(lc, lastToken).
-            setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED).
-            snapshot(lc);
-        }
+            setState(lc, errors.hasErrors() ? CompilationState.PARSE_ERROR : CompilationState.PARSED);
+    }
 
     /**
      * Get the statements in a block.
@@ -582,9 +639,13 @@
         }
 
         // Build up node.
+        if(BinaryNode.isLogical(opType)) {
+            return new BinaryNode(op, new JoinPredecessorExpression(lhs), new JoinPredecessorExpression(rhs));
+        }
         return new BinaryNode(op, lhs, rhs);
     }
 
+
     /**
      * Reduce increment/decrement to simpler operations.
      * @param firstToken First token.
@@ -620,19 +681,21 @@
      *
      * Parse the top level script.
      */
-    private FunctionNode program(final String scriptName) {
-        // Make a fake token for the script.
-        final long functionToken = Token.toDesc(FUNCTION, 0, source.getLength());
+    private FunctionNode program(final String scriptName, final boolean allowPropertyFunction) {
+        // Make a pseudo-token for the script holding its start and length.
+        final long functionToken = Token.toDesc(FUNCTION, Token.descPosition(Token.withDelimiter(token)), source.getLength());
+        final int  functionLine  = line;
         // Set up the script to append elements.
 
         FunctionNode script = newFunctionNode(
             functionToken,
             new IdentNode(functionToken, Token.descPosition(functionToken), scriptName),
             new ArrayList<IdentNode>(),
-            FunctionNode.Kind.SCRIPT);
+            FunctionNode.Kind.SCRIPT,
+            functionLine);
 
         functionDeclarations = new ArrayList<>();
-        sourceElements();
+        sourceElements(allowPropertyFunction);
         addFunctionDeclarations(script);
         functionDeclarations = null;
 
@@ -642,10 +705,6 @@
 
         script = restoreFunctionNode(script, token); //commit code
         script = script.setBody(lc, script.getBody().setNeedsScope(lc));
-        // user may have directive comment to set sourceURL
-        if (sourceURL != null) {
-            script = script.setSourceURL(lc, sourceURL);
-        }
 
         return script;
     }
@@ -683,10 +742,12 @@
      *
      * Parse the elements of the script or function.
      */
-    private void sourceElements() {
-        List<Node>    directiveStmts = null;
-        boolean       checkDirective = true;
-        final boolean oldStrictMode = isStrictMode;
+    private void sourceElements(final boolean shouldAllowPropertyFunction) {
+        List<Node>    directiveStmts        = null;
+        boolean       checkDirective        = true;
+        boolean       allowPropertyFunction = shouldAllowPropertyFunction;
+        final boolean oldStrictMode         = isStrictMode;
+
 
         try {
             // If is a script, then process until the end of the script.
@@ -698,7 +759,8 @@
 
                 try {
                     // Get the next element.
-                    statement(true);
+                    statement(true, allowPropertyFunction);
+                    allowPropertyFunction = false;
 
                     // check for directive prologues
                     if (checkDirective) {
@@ -742,6 +804,12 @@
                                         verifyStrictIdent(param, "function parameter");
                                     }
                                 }
+                            } else if (Context.DEBUG) {
+                                final int flag = FunctionNode.getDirectiveFlag(directive);
+                                if (flag != 0) {
+                                    final FunctionNode function = lc.getCurrentFunction();
+                                    lc.setFlag(function, flag);
+                                }
                             }
                         }
                     }
@@ -781,13 +849,13 @@
      * Parse any of the basic statement types.
      */
     private void statement() {
-        statement(false);
+        statement(false, false);
     }
 
     /**
      * @param topLevel does this statement occur at the "top level" of a script or a function?
      */
-    private void statement(final boolean topLevel) {
+    private void statement(final boolean topLevel, final boolean allowPropertyFunction) {
         if (type == FUNCTION) {
             // As per spec (ECMA section 12), function declarations as arbitrary statement
             // is not "portable". Implementation can issue a warning or disallow the same.
@@ -860,6 +928,20 @@
                     labelStatement();
                     return;
                 }
+                if(allowPropertyFunction) {
+                    final String ident = (String)getValue();
+                    final long propertyToken = token;
+                    final int propertyLine = line;
+                    if("get".equals(ident)) {
+                        next();
+                        addPropertyFunctionStatement(propertyGetterFunction(propertyToken, propertyLine));
+                        return;
+                    } else if("set".equals(ident)) {
+                        next();
+                        addPropertyFunctionStatement(propertySetterFunction(propertyToken, propertyLine));
+                        return;
+                    }
+                }
             }
 
             expressionStatement();
@@ -867,6 +949,11 @@
         }
     }
 
+    private void addPropertyFunctionStatement(final PropertyFunction propertyFunction) {
+        final FunctionNode fn = propertyFunction.functionNode;
+        functionDeclarations.add(new ExpressionStatement(fn.getLineNumber(), fn.getToken(), finish, fn));
+    }
+
     /**
      * block :
      *      { StatementList? }
@@ -970,7 +1057,12 @@
                 next();
 
                 // Get initializer expression. Suppress IN if not statement.
-                init = assignmentExpression(!isStatement);
+                defaultNames.push(name);
+                try {
+                    init = assignmentExpression(!isStatement);
+                } finally {
+                    defaultNames.pop();
+                }
             }
 
             // Allocate var node.
@@ -986,7 +1078,7 @@
 
         // If is a statement then handle end of line.
         if (isStatement) {
-            boolean semicolon = type == SEMICOLON;
+            final boolean semicolon = type == SEMICOLON;
             endOfLine();
             if (semicolon) {
                 lc.getCurrentBlock().setFinish(finish);
@@ -1089,7 +1181,7 @@
      */
     private void forStatement() {
         // Create FOR node, capturing FOR token.
-        ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, null, null, null, ForNode.IS_FOR);
+        ForNode forNode = new ForNode(line, token, Token.descPosition(token), null, ForNode.IS_FOR);
 
         lc.push(forNode);
 
@@ -1138,16 +1230,16 @@
 
                 expect(SEMICOLON);
                 if (type != SEMICOLON) {
-                    forNode = forNode.setTest(lc, expression());
+                    forNode = forNode.setTest(lc, joinPredecessorExpression());
                 }
                 expect(SEMICOLON);
                 if (type != RPAREN) {
-                    forNode = forNode.setModify(lc, expression());
+                    forNode = forNode.setModify(lc, joinPredecessorExpression());
                 }
                 break;
 
             case IN:
-                forNode = forNode.setIsForIn(lc);
+                forNode = forNode.setIsForIn(lc).setTest(lc, new JoinPredecessorExpression());
                 if (vars != null) {
                     // for (var i in obj)
                     if (vars.size() == 1) {
@@ -1180,7 +1272,7 @@
                 next();
 
                 // Get the collection expression.
-                forNode = forNode.setModify(lc, expression());
+                forNode = forNode.setModify(lc, joinPredecessorExpression());
                 break;
 
             default:
@@ -1240,7 +1332,7 @@
         try {
             expect(LPAREN);
             final int whileLine = line;
-            final Expression test = expression();
+            final JoinPredecessorExpression test = joinPredecessorExpression();
             expect(RPAREN);
             final Block body = getStatement();
             appendStatement(whileNode =
@@ -1278,7 +1370,7 @@
             expect(WHILE);
             expect(LPAREN);
             final int doLine = line;
-            final Expression test = expression();
+            final JoinPredecessorExpression test = joinPredecessorExpression();
             expect(RPAREN);
 
             if (type == SEMICOLON) {
@@ -1332,8 +1424,8 @@
             break;
         }
 
-        final IdentNode label = labelNode == null ? null : labelNode.getLabel();
-        final LoopNode targetNode = lc.getContinueTo(label);
+        final String labelName = labelNode == null ? null : labelNode.getLabelName();
+        final LoopNode targetNode = lc.getContinueTo(labelName);
 
         if (targetNode == null) {
             throw error(AbstractParser.message("illegal.continue.stmt"), continueToken);
@@ -1342,7 +1434,7 @@
         endOfLine();
 
         // Construct and add CONTINUE node.
-        appendStatement(new ContinueNode(continueLine, continueToken, finish, label == null ? null : new IdentNode(label)));
+        appendStatement(new ContinueNode(continueLine, continueToken, finish, labelName));
     }
 
     /**
@@ -1382,8 +1474,8 @@
 
         //either an explicit label - then get its node or just a "break" - get first breakable
         //targetNode is what we are breaking out from.
-        final IdentNode label = labelNode == null ? null : labelNode.getLabel();
-        final BreakableNode targetNode = lc.getBreakable(label);
+        final String labelName = labelNode == null ? null : labelNode.getLabelName();
+        final BreakableNode targetNode = lc.getBreakable(labelName);
         if (targetNode == null) {
             throw error(AbstractParser.message("illegal.break.stmt"), breakToken);
         }
@@ -1391,7 +1483,7 @@
         endOfLine();
 
         // Construct and add BREAK node.
-        appendStatement(new BreakNode(breakLine, breakToken, finish, label == null ? null : new IdentNode(label)));
+        appendStatement(new BreakNode(breakLine, breakToken, finish, labelName));
     }
 
     /**
@@ -1618,7 +1710,7 @@
             throw error(AbstractParser.message("duplicate.label", ident.getName()), labelToken);
         }
 
-        LabelNode labelNode = new LabelNode(line, labelToken, finish, ident, null);
+        LabelNode labelNode = new LabelNode(line, labelToken, finish, ident.getName(), null);
         try {
             lc.push(labelNode);
             labelNode = labelNode.setBody(lc, getStatement());
@@ -1665,7 +1757,7 @@
 
         endOfLine();
 
-        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, 0));
+        appendStatement(new ThrowNode(throwLine, throwToken, finish, expression, false));
     }
 
     /**
@@ -1730,7 +1822,7 @@
                 try {
                     // Get CATCH body.
                     final Block catchBody = getBlock(true);
-                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, 0);
+                    final CatchNode catchNode = new CatchNode(catchLine, catchToken, finish, exception, ifExpression, catchBody, false);
                     appendStatement(catchNode);
                 } finally {
                     catchBlock = restoreBlock(catchBlock);
@@ -1892,7 +1984,7 @@
         // Skip ending of edit string expression.
         expect(RBRACE);
 
-        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments);
+        return new CallNode(primaryLine, primaryToken, finish, execIdent, arguments, false);
     }
 
     /**
@@ -2128,8 +2220,8 @@
     private PropertyNode propertyAssignment() {
         // Capture firstToken.
         final long propertyToken = token;
+        final int  functionLine  = line;
 
-        FunctionNode functionNode;
         PropertyKey propertyName;
 
         if (type == IDENT) {
@@ -2141,49 +2233,75 @@
 
                 switch (ident) {
                 case "get":
-                    final PropertyKey getIdent = propertyName();
-                    final String getterName = getIdent.getPropertyName();
-                    final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
-                    expect(LPAREN);
-                    expect(RPAREN);
-                    functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER);
-                    return new PropertyNode(propertyToken, finish, getIdent, null, functionNode, null);
+                    final PropertyFunction getter = propertyGetterFunction(getSetToken, functionLine);
+                    return new PropertyNode(propertyToken, finish, getter.ident, null, getter.functionNode, null);
 
                 case "set":
-                    final PropertyKey setIdent = propertyName();
-                    final String setterName = setIdent.getPropertyName();
-                    final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
-                    expect(LPAREN);
-                    // be sloppy and allow missing setter parameter even though
-                    // spec does not permit it!
-                    final IdentNode argIdent;
-                    if (type == IDENT || isNonStrictModeIdent()) {
-                        argIdent = getIdent();
-                        verifyStrictIdent(argIdent, "setter argument");
-                    } else {
-                        argIdent = null;
-                    }
-                    expect(RPAREN);
-                    List<IdentNode> parameters = new ArrayList<>();
-                    if (argIdent != null) {
-                        parameters.add(argIdent);
-                    }
-                    functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER);
-                    return new PropertyNode(propertyToken, finish, setIdent, null, null, functionNode);
-
+                    final PropertyFunction setter = propertySetterFunction(getSetToken, functionLine);
+                    return new PropertyNode(propertyToken, finish, setter.ident, null, null, setter.functionNode);
                 default:
                     break;
                 }
             }
 
-            propertyName =  new IdentNode(propertyToken, finish, ident).setIsPropertyName();
+            propertyName =  createIdentNode(propertyToken, finish, ident).setIsPropertyName();
         } else {
             propertyName = propertyName();
         }
 
         expect(COLON);
 
-        return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
+        defaultNames.push(propertyName);
+        try {
+            return new PropertyNode(propertyToken, finish, propertyName, assignmentExpression(false), null, null);
+        } finally {
+            defaultNames.pop();
+        }
+    }
+
+    private PropertyFunction propertyGetterFunction(final long getSetToken, final int functionLine) {
+        final PropertyKey getIdent = propertyName();
+        final String getterName = getIdent.getPropertyName();
+        final IdentNode getNameNode = createIdentNode(((Node)getIdent).getToken(), finish, NameCodec.encode("get " + getterName));
+        expect(LPAREN);
+        expect(RPAREN);
+        final FunctionNode functionNode = functionBody(getSetToken, getNameNode, new ArrayList<IdentNode>(), FunctionNode.Kind.GETTER, functionLine);
+
+        return new PropertyFunction(getIdent, functionNode);
+    }
+
+    private PropertyFunction propertySetterFunction(final long getSetToken, final int functionLine) {
+        final PropertyKey setIdent = propertyName();
+        final String setterName = setIdent.getPropertyName();
+        final IdentNode setNameNode = createIdentNode(((Node)setIdent).getToken(), finish, NameCodec.encode("set " + setterName));
+        expect(LPAREN);
+        // be sloppy and allow missing setter parameter even though
+        // spec does not permit it!
+        final IdentNode argIdent;
+        if (type == IDENT || isNonStrictModeIdent()) {
+            argIdent = getIdent();
+            verifyStrictIdent(argIdent, "setter argument");
+        } else {
+            argIdent = null;
+        }
+        expect(RPAREN);
+        final List<IdentNode> parameters = new ArrayList<>();
+        if (argIdent != null) {
+            parameters.add(argIdent);
+        }
+        final FunctionNode functionNode = functionBody(getSetToken, setNameNode, parameters, FunctionNode.Kind.SETTER, functionLine);
+
+        return new PropertyFunction(setIdent, functionNode);
+    }
+
+    private static class PropertyFunction {
+        final PropertyKey ident;
+        final FunctionNode functionNode;
+
+        PropertyFunction(final PropertyKey ident, final FunctionNode function) {
+            this.ident = ident;
+            this.functionNode = function;
+        }
     }
 
     /**
@@ -2216,7 +2334,7 @@
                 detectSpecialFunction((IdentNode)lhs);
             }
 
-            lhs = new CallNode(callLine, callToken, finish, lhs, arguments);
+            lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
         }
 
 loop:
@@ -2231,7 +2349,7 @@
                 final List<Expression> arguments = optimizeList(argumentList());
 
                 // Create call node.
-                lhs = new CallNode(callLine, callToken, finish, lhs, arguments);
+                lhs = new CallNode(callLine, callToken, finish, lhs, arguments, false);
 
                 break;
 
@@ -2254,7 +2372,7 @@
                 final IdentNode property = getIdentifierName();
 
                 // Create property access node.
-                lhs = new AccessNode(callToken, finish, lhs, property);
+                lhs = new AccessNode(callToken, finish, lhs, property.getName());
 
                 break;
 
@@ -2310,7 +2428,7 @@
             arguments.add(objectLiteral());
         }
 
-        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments));
+        final CallNode callNode = new CallNode(callLine, constructor.getToken(), finish, constructor, optimizeList(arguments), true);
 
         return new UnaryNode(newToken, callNode);
     }
@@ -2334,7 +2452,7 @@
 
         switch (type) {
         case NEW:
-            // Get new exppression.
+            // Get new expression.
             lhs = newExpression();
             break;
 
@@ -2378,7 +2496,7 @@
                 final IdentNode property = getIdentifierName();
 
                 // Create property access node.
-                lhs = new AccessNode(callToken, finish, lhs, property);
+                lhs = new AccessNode(callToken, finish, lhs, property.getName());
 
                 break;
 
@@ -2429,7 +2547,7 @@
         return nodeList;
     }
 
-    private static <T> List<T> optimizeList(ArrayList<T> list) {
+    private static <T> List<T> optimizeList(final ArrayList<T> list) {
         switch(list.size()) {
             case 0: {
                 return Collections.emptyList();
@@ -2479,7 +2597,7 @@
         // name is null, generate anonymous name
         boolean isAnonymous = false;
         if (name == null) {
-            final String tmpName = ANON_FUNCTION_PREFIX.symbolName() + functionLine;
+            final String tmpName = getDefaultValidFunctionName(functionLine);
             name = new IdentNode(functionToken, Token.descPosition(functionToken), tmpName);
             isAnonymous = true;
         }
@@ -2488,7 +2606,7 @@
         final List<IdentNode> parameters = formalParameterList();
         expect(RPAREN);
 
-        FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL);
+        FunctionNode functionNode = functionBody(functionToken, name, parameters, FunctionNode.Kind.NORMAL, functionLine);
 
         if (isStatement) {
             if (topLevel) {
@@ -2554,6 +2672,47 @@
         return functionNode;
     }
 
+    private String getDefaultValidFunctionName(final int functionLine) {
+        final String defaultFunctionName = getDefaultFunctionName();
+        return isValidIdentifier(defaultFunctionName) ? defaultFunctionName : ANON_FUNCTION_PREFIX.symbolName() + functionLine;
+    }
+
+    private static boolean isValidIdentifier(final String name) {
+        if(name == null || name.isEmpty()) {
+            return false;
+        }
+        if(!Character.isJavaIdentifierStart(name.charAt(0))) {
+            return false;
+        }
+        for(int i = 1; i < name.length(); ++i) {
+            if(!Character.isJavaIdentifierPart(name.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private String getDefaultFunctionName() {
+        if(!defaultNames.isEmpty()) {
+            final Object nameExpr = defaultNames.peek();
+            if(nameExpr instanceof PropertyKey) {
+                markDefaultNameUsed();
+                return ((PropertyKey)nameExpr).getPropertyName();
+            } else if(nameExpr instanceof AccessNode) {
+                markDefaultNameUsed();
+                return ((AccessNode)nameExpr).getProperty();
+            }
+        }
+        return null;
+    }
+
+    private void markDefaultNameUsed() {
+        defaultNames.pop();
+        // Can be any value as long as getDefaultFunctionName doesn't recognize it as something it can extract a value
+        // from. Can't be null
+        defaultNames.push("");
+    }
+
     /**
      * FormalParameterList :
      *      Identifier
@@ -2583,7 +2742,7 @@
      */
     private List<IdentNode> formalParameterList(final TokenType endType) {
         // Prepare to gather parameters.
-        final List<IdentNode> parameters = new ArrayList<>();
+        final ArrayList<IdentNode> parameters = new ArrayList<>();
         // Track commas.
         boolean first = true;
 
@@ -2604,6 +2763,7 @@
             parameters.add(ident);
         }
 
+        parameters.trimToSize();
         return parameters;
     }
 
@@ -2616,13 +2776,13 @@
      * Parse function body.
      * @return function node (body.)
      */
-    private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind) {
+    private FunctionNode functionBody(final long firstToken, final IdentNode ident, final List<IdentNode> parameters, final FunctionNode.Kind kind, final int functionLine) {
         FunctionNode functionNode = null;
         long lastToken = 0L;
 
         try {
             // Create a new function block.
-            functionNode = newFunctionNode(firstToken, ident, parameters, kind);
+            functionNode = newFunctionNode(firstToken, ident, parameters, kind, functionLine);
 
             // Nashorn extension: expression closures
             if (!env._no_syntax_extensions && type != LBRACE) {
@@ -2635,11 +2795,13 @@
 
                 // just expression as function body
                 final Expression expr = assignmentExpression(true);
+                lastToken = previousToken;
                 assert lc.getCurrentBlock() == lc.getFunctionBody(functionNode);
-                final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), finish, expr);
+                // EOL uses length field to store the line number
+                final int lastFinish = Token.descPosition(lastToken) + (Token.descType(lastToken) == EOL ? 0 : Token.descLength(lastToken));
+                final ReturnNode returnNode = new ReturnNode(functionNode.getLineNumber(), expr.getToken(), lastFinish, expr);
                 appendStatement(returnNode);
-                lastToken = token;
-                functionNode.setFinish(Token.descPosition(token) + Token.descLength(token));
+                functionNode.setFinish(lastFinish);
 
             } else {
                 expect(LBRACE);
@@ -2648,7 +2810,7 @@
                 final List<Statement> prevFunctionDecls = functionDeclarations;
                 functionDeclarations = new ArrayList<>();
                 try {
-                    sourceElements();
+                    sourceElements(false);
                     addFunctionDeclarations(functionNode);
                 } finally {
                     functionDeclarations = prevFunctionDecls;
@@ -2657,14 +2819,24 @@
                 lastToken = token;
                 expect(RBRACE);
                 functionNode.setFinish(finish);
-
             }
         } finally {
             functionNode = restoreFunctionNode(functionNode, lastToken);
         }
+        printAST(functionNode);
         return functionNode;
     }
 
+    private void printAST(final FunctionNode functionNode) {
+        if (functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
+            env.getErr().println(new ASTWriter(functionNode));
+        }
+
+        if (functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+            env.getErr().println(new PrintVisitor(functionNode, true, false));
+        }
+    }
+
     private void addFunctionDeclarations(final FunctionNode functionNode) {
         assert lc.peek() == lc.getFunctionBody(functionNode);
         VarNode lastDecl = null;
@@ -2919,6 +3091,10 @@
         return expression(unaryExpression(), COMMARIGHT.getPrecedence(), false);
     }
 
+    private JoinPredecessorExpression joinPredecessorExpression() {
+        return new JoinPredecessorExpression(expression());
+    }
+
     private Expression expression(final Expression exprLhs, final int minPrecedence, final boolean noIn) {
         // Get the precedence of the next operator.
         int precedence = type.getPrecedence();
@@ -2935,33 +3111,42 @@
 
                 // Pass expression. Middle expression of a conditional expression can be a "in"
                 // expression - even in the contexts where "in" is not permitted.
-                final Expression rhs = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
+                final Expression trueExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), false);
 
                 expect(COLON);
 
                 // Fail expression.
-                final Expression third = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
+                final Expression falseExpr = expression(unaryExpression(), ASSIGN.getPrecedence(), noIn);
 
                 // Build up node.
-                lhs = new TernaryNode(op, lhs, rhs, third);
+                lhs = new TernaryNode(op, lhs, new JoinPredecessorExpression(trueExpr), new JoinPredecessorExpression(falseExpr));
             } else {
                 // Skip operator.
                 next();
 
                  // Get the next primary expression.
-                Expression rhs = unaryExpression();
-
-                // Get precedence of next operator.
-                int nextPrecedence = type.getPrecedence();
-
-                // Subtask greater precedence.
-                while (type.isOperator(noIn) &&
-                       (nextPrecedence > precedence ||
-                       nextPrecedence == precedence && !type.isLeftAssociative())) {
-                    rhs = expression(rhs, nextPrecedence, noIn);
-                    nextPrecedence = type.getPrecedence();
+                Expression rhs;
+                final boolean isAssign = Token.descType(op) == ASSIGN;
+                if(isAssign) {
+                    defaultNames.push(lhs);
                 }
+                try {
+                    rhs = unaryExpression();
+                    // Get precedence of next operator.
+                    int nextPrecedence = type.getPrecedence();
 
+                    // Subtask greater precedence.
+                    while (type.isOperator(noIn) &&
+                           (nextPrecedence > precedence ||
+                           nextPrecedence == precedence && !type.isLeftAssociative())) {
+                        rhs = expression(rhs, nextPrecedence, noIn);
+                        nextPrecedence = type.getPrecedence();
+                    }
+                } finally {
+                    if(isAssign) {
+                        defaultNames.pop();
+                    }
+                }
                 lhs = verifyAssignment(op, lhs, rhs);
             }
 
@@ -3001,7 +3186,7 @@
 
     @Override
     public String toString() {
-        return "[JavaScript Parsing]";
+        return "'JavaScript Parsing'";
     }
 
     private static void markEval(final LexicalContext lc) {
diff --git a/nashorn/src/jdk/nashorn/internal/parser/Token.java b/nashorn/src/jdk/nashorn/internal/parser/Token.java
index 0012daa..43df83b 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/Token.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/Token.java
@@ -61,6 +61,28 @@
     }
 
     /**
+     * Normally returns the token itself, except in case of string tokens
+     * which report their position past their opening delimiter and thus
+     * need to have position and length adjusted.
+     *
+     * @param token Token descriptor.
+     * @return same or adjusted token.
+     */
+    public static long withDelimiter(final long token) {
+        final TokenType tokenType = Token.descType(token);
+        switch(tokenType) {
+            case STRING: case ESCSTRING: case EXECSTRING: {
+                final int start = Token.descPosition(token) - 1;
+                final int len = Token.descLength(token) + 2;
+                return toDesc(tokenType, start, len);
+            }
+            default: {
+                return token;
+            }
+        }
+    }
+
+    /**
      * Extract token length from a token descriptor.
      * @param token Token descriptor.
      * @return Length of the token.
diff --git a/nashorn/src/jdk/nashorn/internal/parser/TokenType.java b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
index 5900507..36d1ecd 100644
--- a/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
+++ b/nashorn/src/jdk/nashorn/internal/parser/TokenType.java
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.parser;
 
-import java.util.Locale;
 import static jdk.nashorn.internal.parser.TokenKind.BINARY;
 import static jdk.nashorn.internal.parser.TokenKind.BRACKET;
 import static jdk.nashorn.internal.parser.TokenKind.FUTURE;
@@ -36,6 +35,8 @@
 import static jdk.nashorn.internal.parser.TokenKind.SPECIAL;
 import static jdk.nashorn.internal.parser.TokenKind.UNARY;
 
+import java.util.Locale;
+
 /**
  * Description of all the JavaScript tokens.
  */
@@ -182,7 +183,6 @@
     ARRAY          (LITERAL,  null),
 
     COMMALEFT      (IR,       null),
-    DISCARD        (IR,       null),
     DECPOSTFIX     (IR,       null),
     INCPOSTFIX     (IR,       null);
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
index e8ff153..892c942 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/AccessorProperty.java
@@ -25,38 +25,41 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.ACCESSOR_TYPES;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.DEBUG_FIELDS;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.LOG;
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_TYPE;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.PRIMITIVE_FIELD_TYPE;
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGetter;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createGuardBoxedPrimitiveSetter;
 import static jdk.nashorn.internal.codegen.ObjectClassGenerator.createSetter;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorType;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getAccessorTypeIndex;
-import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getNumberOfAccessorTypes;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldCount;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.getFieldName;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.lookup.MethodHandleFactory.stripName;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.JSType.getNumberOfAccessorTypes;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import java.io.IOException;
 import java.io.ObjectInputStream;
-import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import java.util.function.Supplier;
+import java.util.logging.Level;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.objects.Global;
 
 /**
  * An AccessorProperty is the most generic property type. An AccessorProperty is
  * represented as fields in a ScriptObject class.
  */
-public final class AccessorProperty extends Property implements Serializable {
-    private static final MethodHandles.Lookup lookup = MethodHandles.lookup();
-    private static final MethodHandle REPLACE_MAP = findOwnMH("replaceMap", Object.class, Object.class, PropertyMap.class, String.class, Class.class, Class.class);
+public class AccessorProperty extends Property {
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    private static final MethodHandle REPLACE_MAP   = findOwnMH_S("replaceMap", Object.class, Object.class, PropertyMap.class);
+    private static final MethodHandle INVALIDATE_SP = findOwnMH_S("invalidateSwitchPoint", Object.class, Object.class, SwitchPoint.class);
+
+    private static final SwitchPoint NO_CHANGE_CALLBACK = new SwitchPoint();
 
     private static final int NOOF_TYPES = getNumberOfAccessorTypes();
     private static final long serialVersionUID = 3371720170182154920L;
@@ -67,51 +70,58 @@
      * these are the most frequently retrieved ones, and lookup of method handle natives only registers in the profiler
      * for them.
      */
-    private static ClassValue<GettersSetters> GETTERS_SETTERS = new ClassValue<GettersSetters>() {
+    private static ClassValue<Accessors> GETTERS_SETTERS = new ClassValue<Accessors>() {
         @Override
-        protected GettersSetters computeValue(Class<?> structure) {
-            return new GettersSetters(structure);
+        protected Accessors computeValue(final Class<?> structure) {
+            return new Accessors(structure);
         }
     };
 
-    /** Property getter cache */
-    private transient MethodHandle[] getters = new MethodHandle[NOOF_TYPES];
+    private static class Accessors {
+        final MethodHandle[] objectGetters;
+        final MethodHandle[] objectSetters;
+        final MethodHandle[] primitiveGetters;
+        final MethodHandle[] primitiveSetters;
 
-    private static final MethodType[] ACCESSOR_GETTER_TYPES = new MethodType[NOOF_TYPES];
-    private static final MethodType[] ACCESSOR_SETTER_TYPES = new MethodType[NOOF_TYPES];
-    private static final MethodType ACCESSOR_GETTER_PRIMITIVE_TYPE;
-    private static final MethodType ACCESSOR_SETTER_PRIMITIVE_TYPE;
-    private static final MethodHandle SPILL_ELEMENT_GETTER;
-    private static final MethodHandle SPILL_ELEMENT_SETTER;
+        /**
+         * Normal
+         * @param structure
+         */
+        Accessors(final Class<?> structure) {
+            final int fieldCount = getFieldCount(structure);
+            objectGetters    = new MethodHandle[fieldCount];
+            objectSetters    = new MethodHandle[fieldCount];
+            primitiveGetters = new MethodHandle[fieldCount];
+            primitiveSetters = new MethodHandle[fieldCount];
 
-    private static final int SPILL_CACHE_SIZE = 8;
-    private static final MethodHandle[] SPILL_ACCESSORS = new MethodHandle[SPILL_CACHE_SIZE * 2];
+            for (int i = 0; i < fieldCount; i++) {
+                final String fieldName = getFieldName(i, Type.OBJECT);
+                final Class<?> typeClass = Type.OBJECT.getTypeClass();
+                objectGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldName, typeClass), Lookup.GET_OBJECT_TYPE);
+                objectSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldName, typeClass), Lookup.SET_OBJECT_TYPE);
+            }
 
-    static {
-        MethodType getterPrimitiveType = null;
-        MethodType setterPrimitiveType = null;
-
-        for (int i = 0; i < NOOF_TYPES; i++) {
-            final Type type = ACCESSOR_TYPES.get(i);
-            ACCESSOR_GETTER_TYPES[i] = MH.type(type.getTypeClass(), Object.class);
-            ACCESSOR_SETTER_TYPES[i] = MH.type(void.class, Object.class, type.getTypeClass());
-
-            if (type == PRIMITIVE_TYPE) {
-                getterPrimitiveType = ACCESSOR_GETTER_TYPES[i];
-                setterPrimitiveType = ACCESSOR_SETTER_TYPES[i];
+            if (!OBJECT_FIELDS_ONLY) {
+                for (int i = 0; i < fieldCount; i++) {
+                    final String fieldNamePrimitive = getFieldName(i, PRIMITIVE_FIELD_TYPE);
+                    final Class<?> typeClass = PRIMITIVE_FIELD_TYPE.getTypeClass();
+                    primitiveGetters[i] = MH.asType(MH.getter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.GET_PRIMITIVE_TYPE);
+                    primitiveSetters[i] = MH.asType(MH.setter(LOOKUP, structure, fieldNamePrimitive, typeClass), Lookup.SET_PRIMITIVE_TYPE);
+                }
             }
         }
-
-        ACCESSOR_GETTER_PRIMITIVE_TYPE = getterPrimitiveType;
-        ACCESSOR_SETTER_PRIMITIVE_TYPE = setterPrimitiveType;
-
-        final MethodType spillGetterType = MethodType.methodType(Object[].class, Object.class);
-        final MethodHandle spillGetter = MH.asType(MH.getter(MethodHandles.lookup(), ScriptObject.class, "spill", Object[].class), spillGetterType);
-        SPILL_ELEMENT_GETTER = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, spillGetter);
-        SPILL_ELEMENT_SETTER = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, spillGetter);
     }
 
     /**
+     * Property getter cache
+     *   Note that we can't do the same simple caching for optimistic getters,
+     *   due to the fact that they are bound to a program point, which will
+     *   produce different boun method handles wrapping the same access mechanism
+     *   depending on callsite
+     */
+    private MethodHandle[] GETTER_CACHE = new MethodHandle[NOOF_TYPES];
+
+    /**
      * Create a new accessor property. Factory method used by nasgen generated code.
      *
      * @param key           {@link Property} key.
@@ -126,16 +136,16 @@
     }
 
     /** Seed getter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
-    private transient MethodHandle primitiveGetter;
+    transient MethodHandle primitiveGetter;
 
     /** Seed setter for the primitive version of this field (in -Dnashorn.fields.dual=true mode) */
-    private transient MethodHandle primitiveSetter;
+    transient MethodHandle primitiveSetter;
 
     /** Seed getter for the Object version of this field */
-    private transient MethodHandle objectGetter;
+    transient MethodHandle objectGetter;
 
     /** Seed setter for the Object version of this field */
-    private transient MethodHandle objectSetter;
+    transient MethodHandle objectSetter;
 
     /**
      * Current type of this object, in object only mode, this is an Object.class. In dual-fields mode
@@ -156,33 +166,50 @@
      * @param delegate  delegate object to rebind receiver to
      */
     AccessorProperty(final AccessorProperty property, final Object delegate) {
-        super(property);
+        super(property, property.getFlags() | IS_BOUND);
 
         this.primitiveGetter = bindTo(property.primitiveGetter, delegate);
         this.primitiveSetter = bindTo(property.primitiveSetter, delegate);
-        this.objectGetter    = bindTo(property.ensureObjectGetter(), delegate);
-        this.objectSetter    = bindTo(property.ensureObjectSetter(), delegate);
-
+        this.objectGetter    = bindTo(property.objectGetter, delegate);
+        this.objectSetter    = bindTo(property.objectSetter, delegate);
+        property.GETTER_CACHE = new MethodHandle[NOOF_TYPES];
         // Properties created this way are bound to a delegate
-        this.flags |= IS_BOUND;
         setCurrentType(property.getCurrentType());
     }
 
     /**
+     * SPILL PROPERTY or USER ACCESSOR PROPERTY abstract constructor
+     *
      * Constructor for spill properties. Array getters and setters will be created on demand.
      *
      * @param key    the property key
      * @param flags  the property flags
      * @param slot   spill slot
+     * @param primitiveGetter primitive getter
+     * @param primitiveSetter primitive setter
+     * @param objectGetter    object getter
+     * @param objectSetter    object setter
      */
-    public AccessorProperty(final String key, final int flags, final int slot) {
+    protected AccessorProperty(
+            final String key,
+            final int flags,
+            final int slot,
+            final MethodHandle primitiveGetter,
+            final MethodHandle primitiveSetter,
+            final MethodHandle objectGetter,
+            final MethodHandle objectSetter) {
         super(key, flags, slot);
-        assert (flags & IS_SPILL) == IS_SPILL;
-
-        setCurrentType(Object.class);
+        assert getClass() != AccessorProperty.class;
+        this.primitiveGetter = primitiveGetter;
+        this.primitiveSetter = primitiveSetter;
+        this.objectGetter    = objectGetter;
+        this.objectSetter    = objectSetter;
+        initializeType();
     }
 
     /**
+     * NASGEN constructor
+     *
      * Constructor. Similar to the constructor with both primitive getters and setters, the difference
      * here being that only one getter and setter (setter is optional for non writable fields) is given
      * to the constructor, and the rest are created from those. Used e.g. by Nasgen classes
@@ -193,8 +220,9 @@
      * @param getter the property getter
      * @param setter the property setter or null if non writable, non configurable
      */
-    AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
-        super(key, flags, slot);
+    private AccessorProperty(final String key, final int flags, final int slot, final MethodHandle getter, final MethodHandle setter) {
+        super(key, flags | (getter.type().returnType().isPrimitive() ? IS_NASGEN_PRIMITIVE : 0), slot);
+        assert !isSpill();
 
         // we don't need to prep the setters these will never be invalidated as this is a nasgen
         // or known type getter/setter. No invalidations will take place
@@ -203,40 +231,31 @@
         final Class<?> setterType = setter == null ? null : setter.type().parameterType(1);
 
         assert setterType == null || setterType == getterType;
-
-        if (getterType.isPrimitive()) {
-            for (int i = 0; i < NOOF_TYPES; i++) {
-                getters[i] = MH.asType(
-                    Lookup.filterReturnType(
-                        getter,
-                        getAccessorType(i).getTypeClass()),
-                    ACCESSOR_GETTER_TYPES[i]);
-            }
+        if (OBJECT_FIELDS_ONLY) {
+            primitiveGetter = primitiveSetter = null;
         } else {
-            objectGetter = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
-            objectSetter = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;
-        }
-
-        setCurrentType(getterType);
-    }
-
-    private static class GettersSetters {
-        final MethodHandle[] getters;
-        final MethodHandle[] setters;
-
-        public GettersSetters(Class<?> structure) {
-            final int fieldCount = ObjectClassGenerator.getFieldCount(structure);
-            getters = new MethodHandle[fieldCount];
-            setters = new MethodHandle[fieldCount];
-            for(int i = 0; i < fieldCount; ++i) {
-                final String fieldName = ObjectClassGenerator.getFieldName(i, Type.OBJECT);
-                getters[i] = MH.asType(MH.getter(lookup, structure, fieldName, Type.OBJECT.getTypeClass()), Lookup.GET_OBJECT_TYPE);
-                setters[i] = MH.asType(MH.setter(lookup, structure, fieldName, Type.OBJECT.getTypeClass()), Lookup.SET_OBJECT_TYPE);
+            if (getterType == int.class || getterType == long.class) {
+                primitiveGetter = MH.asType(getter, Lookup.GET_PRIMITIVE_TYPE);
+                primitiveSetter = setter == null ? null : MH.asType(setter, Lookup.SET_PRIMITIVE_TYPE);
+            } else if (getterType == double.class) {
+                primitiveGetter = MH.asType(MH.filterReturnValue(getter, ObjectClassGenerator.PACK_DOUBLE), Lookup.GET_PRIMITIVE_TYPE);
+                primitiveSetter = setter == null ? null : MH.asType(MH.filterArguments(setter, 1, ObjectClassGenerator.UNPACK_DOUBLE), Lookup.SET_PRIMITIVE_TYPE);
+            } else {
+                primitiveGetter = primitiveSetter = null;
             }
         }
+
+        assert primitiveGetter == null || primitiveGetter.type() == Lookup.GET_PRIMITIVE_TYPE : primitiveGetter + "!=" + Lookup.GET_PRIMITIVE_TYPE;
+        assert primitiveSetter == null || primitiveSetter.type() == Lookup.SET_PRIMITIVE_TYPE : primitiveSetter;
+
+        objectGetter  = getter.type() != Lookup.GET_OBJECT_TYPE ? MH.asType(getter, Lookup.GET_OBJECT_TYPE) : getter;
+        objectSetter  = setter != null && setter.type() != Lookup.SET_OBJECT_TYPE ? MH.asType(setter, Lookup.SET_OBJECT_TYPE) : setter;
+
+        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : getterType);
     }
 
     /**
+     * Normal ACCESS PROPERTY constructor given a structure class.
      * Constructor for dual field AccessorPropertys.
      *
      * @param key              property key
@@ -248,77 +267,119 @@
         super(key, flags, slot);
 
         initGetterSetter(structure);
+        initializeType();
     }
 
     private void initGetterSetter(final Class<?> structure) {
         final int slot = getSlot();
-        final String key = getKey();
         /*
          * primitiveGetter and primitiveSetter are only used in dual fields mode. Setting them to null also
          * works in dual field mode, it only means that the property never has a primitive
          * representation.
          */
-        primitiveGetter = null;
-        primitiveSetter = null;
 
         if (isParameter() && hasArguments()) {
-            final MethodHandle arguments   = MH.getter(lookup, structure, "arguments", ScriptObject.class);
-
+            //parameters are always stored in an object array, which may or may not be a good idea
+            final MethodHandle arguments = MH.getter(LOOKUP, structure, "arguments", ScriptObject.class);
             objectGetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.GET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.GET_OBJECT_TYPE);
             objectSetter = MH.asType(MH.insertArguments(MH.filterArguments(ScriptObject.SET_ARGUMENT.methodHandle(), 0, arguments), 1, slot), Lookup.SET_OBJECT_TYPE);
+            primitiveGetter = null;
+            primitiveSetter = null;
         } else {
-            final GettersSetters gs = GETTERS_SETTERS.get(structure);
-            objectGetter = gs.getters[slot];
-            objectSetter = gs.setters[slot];
-
-            if (!OBJECT_FIELDS_ONLY) {
-                final String fieldNamePrimitive = ObjectClassGenerator.getFieldName(slot, PRIMITIVE_TYPE);
-                final Class<?> typeClass = PRIMITIVE_TYPE.getTypeClass();
-                primitiveGetter = MH.asType(MH.getter(lookup, structure, fieldNamePrimitive, typeClass), ACCESSOR_GETTER_PRIMITIVE_TYPE);
-                primitiveSetter = MH.asType(MH.setter(lookup, structure, fieldNamePrimitive, typeClass), ACCESSOR_SETTER_PRIMITIVE_TYPE);
-            }
+            final Accessors gs = GETTERS_SETTERS.get(structure);
+            objectGetter    = gs.objectGetters[slot];
+            primitiveGetter = gs.primitiveGetters[slot];
+            objectSetter    = gs.objectSetters[slot];
+            primitiveSetter = gs.primitiveSetters[slot];
         }
-
-        Class<?> initialType = null;
-
-        if (OBJECT_FIELDS_ONLY || isAlwaysObject()) {
-            initialType = Object.class;
-        } else if (!canBePrimitive()) {
-            info(key + " cannot be primitive");
-            initialType = Object.class;
-        } else {
-            info(key + " CAN be primitive");
-            if (!canBeUndefined()) {
-                info(key + " is always defined");
-                initialType = int.class; //double works too for less type invalidation, but this requires experimentation, e.g. var x = 17; x += 2 will turn it into double now because of lack of range analysis
-            }
-        }
-
-        // is always object means "is never initialized to undefined, and always of object type
-        setCurrentType(initialType);
     }
 
     /**
-     * Copy constructor
+     * Constructor
      *
-     * @param property  source property
+     * @param key          key
+     * @param flags        flags
+     * @param slot         field slot index
+     * @param owner        owner of property
+     * @param initialValue initial value to which the property can be set
      */
-    protected AccessorProperty(final AccessorProperty property) {
-        super(property);
+    protected AccessorProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
+        this(key, flags, owner.getClass(), slot);
+        setInitialValue(owner, initialValue);
+    }
 
-        this.getters         = property.getters;
+    /**
+     * Normal access property constructor that overrides the type
+     * Override the initial type. Used for Object Literals
+     *
+     * @param key          key
+     * @param flags        flags
+     * @param structure    structure to JO subclass
+     * @param slot         field slot index
+     * @param initialType  initial type of the property
+     */
+    public AccessorProperty(final String key, final int flags, final Class<?> structure, final int slot, final Class<?> initialType) {
+        this(key, flags, structure, slot);
+        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
+    }
+
+    /**
+     * Copy constructor that may change type and in that case clear the cache. Important to do that before
+     * type change or getters will be created already stale.
+     *
+     * @param property property
+     * @param newType  new type
+     */
+    protected AccessorProperty(final AccessorProperty property, final Class<?> newType) {
+        super(property, property.getFlags());
+
+        this.GETTER_CACHE    = newType != property.getCurrentType() ? new MethodHandle[NOOF_TYPES] : property.GETTER_CACHE;
         this.primitiveGetter = property.primitiveGetter;
         this.primitiveSetter = property.primitiveSetter;
         this.objectGetter    = property.objectGetter;
         this.objectSetter    = property.objectSetter;
 
-        setCurrentType(property.getCurrentType());
+        setCurrentType(newType);
+    }
+
+    /**
+     * COPY constructor
+     *
+     * @param property  source property
+     */
+    protected AccessorProperty(final AccessorProperty property) {
+        this(property, property.getCurrentType());
+    }
+
+    /**
+     * Set initial value of a script object's property
+     * @param owner        owner
+     * @param initialValue initial value
+     */
+    protected final void setInitialValue(final ScriptObject owner, final Object initialValue) {
+        setCurrentType(JSType.unboxedFieldType(initialValue));
+        if (initialValue instanceof Integer) {
+            invokeSetter(owner, ((Integer)initialValue).intValue());
+        } else if (initialValue instanceof Long) {
+            invokeSetter(owner, ((Long)initialValue).longValue());
+        } else if (initialValue instanceof Double) {
+            invokeSetter(owner, ((Double)initialValue).doubleValue());
+        } else {
+            invokeSetter(owner, initialValue);
+        }
+    }
+
+    /**
+     * Initialize the type of a property
+     */
+    protected final void initializeType() {
+        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : null);
     }
 
     private void readObject(final ObjectInputStream s) throws IOException, ClassNotFoundException {
         s.defaultReadObject();
         // Restore getters array
-        getters = new MethodHandle[NOOF_TYPES];
+        GETTER_CACHE = new MethodHandle[NOOF_TYPES];
     }
 
     private static MethodHandle bindTo(final MethodHandle mh, final Object receiver) {
@@ -330,83 +391,214 @@
     }
 
     @Override
-    protected Property copy() {
+    public Property copy() {
         return new AccessorProperty(this);
     }
 
     @Override
-    public void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict)  {
-        if (isSpill()) {
-            self.spill[getSlot()] = value;
-        } else {
-            try {
-                getSetter(Object.class, self.getMap()).invokeExact((Object)self, value);
-            } catch (final Error|RuntimeException e) {
-                throw e;
-            } catch (final Throwable e) {
-                throw new RuntimeException(e);
-            }
-        }
+    public Property copy(final Class<?> newType) {
+        return new AccessorProperty(this, newType);
     }
 
     @Override
-    public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
-        if (isSpill()) {
-            return self.spill[getSlot()];
-        }
-
+    public int getIntValue(final ScriptObject self, final ScriptObject owner) {
         try {
-            return getGetter(Object.class).invokeExact((Object)self);
-        } catch (final Error|RuntimeException e) {
+            return (int)getGetter(int.class).invokeExact((Object)self);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+     }
+
+    @Override
+    public long getLongValue(final ScriptObject self, final ScriptObject owner) {
+        try {
+            return (long)getGetter(long.class).invokeExact((Object)self);
+        } catch (final Error | RuntimeException e) {
             throw e;
         } catch (final Throwable e) {
             throw new RuntimeException(e);
         }
     }
 
-    // Spill getters and setters are lazily initialized, see JDK-8011630
-    private MethodHandle ensureObjectGetter() {
-        if (isSpill() && objectGetter == null) {
-            objectGetter = getSpillGetter();
+     @Override
+     public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
+        try {
+            return (double)getGetter(double.class).invokeExact((Object)self);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
         }
-        return objectGetter;
     }
 
-    private MethodHandle ensureObjectSetter() {
-        if (isSpill() && objectSetter == null) {
-            objectSetter = getSpillSetter();
+     @Override
+     public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
+        try {
+            return getGetter(Object.class).invokeExact((Object)self);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
         }
-        return objectSetter;
+    }
+
+     /**
+      * Invoke setter for this property with a value
+      * @param self  owner
+      * @param value value
+      */
+    protected final void invokeSetter(final ScriptObject self, final int value) {
+        try {
+            getSetter(int.class, self.getMap()).invokeExact((Object)self, value);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Invoke setter for this property with a value
+     * @param self  owner
+     * @param value value
+     */
+    protected final void invokeSetter(final ScriptObject self, final long value) {
+        try {
+            getSetter(long.class, self.getMap()).invokeExact((Object)self, value);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Invoke setter for this property with a value
+     * @param self  owner
+     * @param value value
+     */
+    protected final void invokeSetter(final ScriptObject self, final double value) {
+        try {
+            getSetter(double.class, self.getMap()).invokeExact((Object)self, value);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Invoke setter for this property with a value
+     * @param self  owner
+     * @param value value
+     */
+    protected final void invokeSetter(final ScriptObject self, final Object value) {
+        try {
+            getSetter(Object.class, self.getMap()).invokeExact((Object)self, value);
+        } catch (final Error | RuntimeException e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict)  {
+        assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
+        invokeSetter(self, value);
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict)  {
+        assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
+        invokeSetter(self, value);
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict)  {
+        assert isConfigurable() || isWritable() : getKey() + " is not writable or configurable";
+        invokeSetter(self, value);
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict)  {
+        //this is sometimes used for bootstrapping, hence no assert. ugly.
+        invokeSetter(self, value);
     }
 
     @Override
     void initMethodHandles(final Class<?> structure) {
+        // sanity check for structure class
         if (!ScriptObject.class.isAssignableFrom(structure) || !StructureLoader.isStructureClass(structure.getName())) {
             throw new IllegalArgumentException();
         }
-        if (!isSpill()) {
-            initGetterSetter(structure);
-        }
+        // this method is overridden in SpillProperty
+        assert !isSpill();
+        initGetterSetter(structure);
     }
 
     @Override
     public MethodHandle getGetter(final Class<?> type) {
         final int i = getAccessorTypeIndex(type);
-        ensureObjectGetter();
 
-        if (getters[i] == null) {
-            getters[i] = debug(
-                createGetter(currentType, type, primitiveGetter, objectGetter),
-                currentType, type, "get");
+        assert type == int.class ||
+                type == long.class ||
+                type == double.class ||
+                type == Object.class :
+                "invalid getter type " + type + " for " + getKey();
+
+        //all this does is add a return value filter for object fields only
+        final MethodHandle[] getterCache = GETTER_CACHE;
+        final MethodHandle cachedGetter = getterCache[i];
+        final MethodHandle getter;
+        if (cachedGetter != null) {
+            getter = cachedGetter;
+        } else {
+            getter = debug(
+                createGetter(
+                    getCurrentType(),
+                    type,
+                    primitiveGetter,
+                    objectGetter,
+                    INVALID_PROGRAM_POINT),
+                getCurrentType(),
+                type,
+                "get");
+            getterCache[i] = getter;
+       }
+       assert getter.type().returnType() == type && getter.type().parameterType(0) == Object.class;
+       return getter;
+    }
+
+    @Override
+    public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
+        // nasgen generated primitive fields like Math.PI have only one known unchangeable primitive type
+        if (objectGetter == null) {
+            return getOptimisticPrimitiveGetter(type, programPoint);
         }
 
-        return getters[i];
+        return debug(
+            createGetter(
+                getCurrentType(),
+                type,
+                primitiveGetter,
+                objectGetter,
+                programPoint),
+            getCurrentType(),
+            type,
+            "get");
+    }
+
+    private MethodHandle getOptimisticPrimitiveGetter(final Class<?> type, final int programPoint) {
+        final MethodHandle g = getGetter(getCurrentType());
+        return MH.asType(OptimisticReturnFilters.filterOptimisticReturnValue(g, type, programPoint), g.type().changeReturnType(type));
     }
 
     private Property getWiderProperty(final Class<?> type) {
-        final AccessorProperty newProperty = new AccessorProperty(this);
-        newProperty.invalidate(type);
-        return newProperty;
+        return copy(type); //invalidate cache of new property
+
     }
 
     private PropertyMap getWiderMap(final PropertyMap oldMap, final Property newProperty) {
@@ -418,115 +610,99 @@
 
     // the final three arguments are for debug printout purposes only
     @SuppressWarnings("unused")
-    private static Object replaceMap(final Object sobj, final PropertyMap newMap, final String key, final Class<?> oldType, final Class<?> newType) {
-        if (DEBUG_FIELDS) {
-            final PropertyMap oldMap = ((ScriptObject)sobj).getMap();
-            info("Type change for '" + key + "' " + oldType + "=>" + newType);
-            finest("setting map " + sobj + " from " + Debug.id(oldMap) + " to " + Debug.id(newMap) + " " + oldMap + " => " + newMap);
-        }
+    private static Object replaceMap(final Object sobj, final PropertyMap newMap) {
         ((ScriptObject)sobj).setMap(newMap);
         return sobj;
     }
 
+    @SuppressWarnings("unused")
+    private static Object invalidateSwitchPoint(final Object obj, final SwitchPoint sp) {
+        SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+        return obj;
+    }
+
     private MethodHandle generateSetter(final Class<?> forType, final Class<?> type) {
-        ensureObjectSetter();
-        MethodHandle mh = createSetter(forType, type, primitiveSetter, objectSetter);
-        mh = debug(mh, currentType, type, "set");
-        return mh;
+        return debug(createSetter(forType, type, primitiveSetter, objectSetter), getCurrentType(), type, "set");
+    }
+
+    /**
+     * Is this property of the undefined type?
+     * @return true if undefined
+     */
+    protected final boolean isUndefined() {
+        return getCurrentType() == null;
     }
 
     @Override
     public MethodHandle getSetter(final Class<?> type, final PropertyMap currentMap) {
-        final int i            = getAccessorTypeIndex(type);
-        final int ci           = currentType == null ? -1 : getAccessorTypeIndex(currentType);
-        final Class<?> forType = currentType == null ? type : currentType;
+        final int      i       = getAccessorTypeIndex(type);
+        final int      ci      = isUndefined() ? -1 : getAccessorTypeIndex(getCurrentType());
+        final Class<?> forType = isUndefined() ? type : getCurrentType();
 
         //if we are asking for an object setter, but are still a primitive type, we might try to box it
         MethodHandle mh;
-
         if (needsInvalidator(i, ci)) {
             final Property     newProperty = getWiderProperty(type);
             final PropertyMap  newMap      = getWiderMap(currentMap, newProperty);
+
             final MethodHandle widerSetter = newProperty.getSetter(type, newMap);
-            final MethodHandle explodeTypeSetter = MH.filterArguments(widerSetter, 0, MH.insertArguments(REPLACE_MAP, 1, newMap, getKey(), currentType, type));
-            if (currentType != null && currentType.isPrimitive() && type == Object.class) {
-                //might try a box check on this to avoid widening field to object storage
-                mh = createGuardBoxedPrimitiveSetter(currentType, generateSetter(currentType, currentType), explodeTypeSetter);
-            } else {
-                mh = explodeTypeSetter;
+            final Class<?>     ct = getCurrentType();
+            mh = MH.filterArguments(widerSetter, 0, MH.insertArguments(debugReplace(ct, type, currentMap, newMap) , 1, newMap));
+            if (ct != null && ct.isPrimitive() && !type.isPrimitive()) {
+                 mh = ObjectClassGenerator.createGuardBoxedPrimitiveSetter(ct, generateSetter(ct, ct), mh);
             }
         } else {
-            mh = generateSetter(forType, type);
+            mh = generateSetter(!forType.isPrimitive() ? Object.class : forType, type);
         }
 
+        /**
+         * Check if this is a special global name that requires switchpoint invalidation
+         */
+        final SwitchPoint ccb = getChangeCallback();
+        if (ccb != null && ccb != NO_CHANGE_CALLBACK) {
+            mh = MH.filterArguments(mh, 0, MH.insertArguments(debugInvalidate(getKey(), ccb), 1, changeCallback));
+        }
+
+        assert mh.type().returnType() == void.class : mh.type();
+
         return mh;
     }
 
+    /**
+     * Get the change callback for this property
+     * @return switchpoint that is invalidated when property changes
+     */
+    protected SwitchPoint getChangeCallback() {
+        if (changeCallback == null) {
+            try {
+                changeCallback = Global.instance().getChangeCallback(getKey());
+            } catch (final NullPointerException e) {
+                assert !"apply".equals(getKey()) && !"call".equals(getKey());
+                //empty
+            }
+            if (changeCallback == null) {
+                changeCallback = NO_CHANGE_CALLBACK;
+            }
+        }
+        return changeCallback;
+    }
+
     @Override
-    public boolean canChangeType() {
+    public final boolean canChangeType() {
         if (OBJECT_FIELDS_ONLY) {
             return false;
         }
-        return currentType != Object.class && (isConfigurable() || isWritable());
+        return getCurrentType() != Object.class && (isConfigurable() || isWritable());
     }
 
     private boolean needsInvalidator(final int ti, final int fti) {
         return canChangeType() && ti > fti;
     }
 
-    private void invalidate(final Class<?> newType) {
-        getters = new MethodHandle[NOOF_TYPES];
-        setCurrentType(newType);
-    }
-
-    private MethodHandle getSpillGetter() {
-        final int slot = getSlot();
-        MethodHandle getter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2] : null;
-        if (getter == null) {
-            getter = MH.insertArguments(SPILL_ELEMENT_GETTER, 1, slot);
-            if (slot < SPILL_CACHE_SIZE) {
-                SPILL_ACCESSORS[slot * 2 + 0] = getter;
-            }
-        }
-        return getter;
-    }
-
-    private MethodHandle getSpillSetter() {
-        final int slot = getSlot();
-        MethodHandle setter = slot < SPILL_CACHE_SIZE ? SPILL_ACCESSORS[slot * 2 + 1] : null;
-        if (setter == null) {
-            setter = MH.insertArguments(SPILL_ELEMENT_SETTER, 1, slot);
-            if (slot < SPILL_CACHE_SIZE) {
-                SPILL_ACCESSORS[slot * 2 + 1] = setter;
-            }
-        }
-        return setter;
-    }
-
-    private static void finest(final String str) {
-        if (DEBUG_FIELDS) {
-            LOG.finest(str);
-        }
-    }
-
-    private static void info(final String str) {
-        if (DEBUG_FIELDS) {
-            LOG.info(str);
-        }
-    }
-
-    private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
-        if (DEBUG_FIELDS) {
-           return MethodHandleFactory.addDebugPrintout(
-               LOG,
-               mh,
-               tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", forType=" + stripName(forType) + ", type=" + stripName(type) + ')');
-        }
-        return mh;
-    }
-
-    private void setCurrentType(final Class<?> currentType) {
-        this.currentType = currentType;
+    @Override
+    public final void setCurrentType(final Class<?> currentType) {
+        assert currentType != boolean.class : "no boolean storage support yet - fix this";
+        this.currentType = currentType == null ? null : currentType.isPrimitive() ? currentType : Object.class;
     }
 
     @Override
@@ -534,8 +710,82 @@
         return currentType;
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        return MH.findStatic(lookup, AccessorProperty.class, name, MH.type(rtype, types));
+
+    private MethodHandle debug(final MethodHandle mh, final Class<?> forType, final Class<?> type, final String tag) {
+        if (!Context.DEBUG || !Global.hasInstance()) {
+            return mh;
+        }
+
+        final Context context = Context.getContextTrusted();
+        assert context != null;
+
+        return context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                Level.INFO,
+                mh,
+                0,
+                true,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return tag + " '" + getKey() + "' (property="+ Debug.id(this) + ", slot=" + getSlot() + " " + getClass().getSimpleName() + " forType=" + stripName(forType) + ", type=" + stripName(type) + ')';
+                    }
+                });
     }
 
+    private MethodHandle debugReplace(final Class<?> oldType, final Class<?> newType, final PropertyMap oldMap, final PropertyMap newMap) {
+        if (!Context.DEBUG || !Global.hasInstance()) {
+            return REPLACE_MAP;
+        }
+
+        final Context context = Context.getContextTrusted();
+        assert context != null;
+
+        MethodHandle mh = context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                REPLACE_MAP,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return "Type change for '" + getKey() + "' " + oldType + "=>" + newType;
+                    }
+                });
+
+        mh = context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                Level.FINEST,
+                mh,
+                Integer.MAX_VALUE,
+                false,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return "Setting map " + Debug.id(oldMap) + " => " + Debug.id(newMap) + " " + oldMap + " => " + newMap;
+                    }
+                });
+        return mh;
+    }
+
+    private static MethodHandle debugInvalidate(final String key, final SwitchPoint sp) {
+        if (!Context.DEBUG || !Global.hasInstance()) {
+            return INVALIDATE_SP;
+        }
+
+        final Context context = Context.getContextTrusted();
+        assert context != null;
+
+        return context.addLoggingToHandle(
+                ObjectClassGenerator.class,
+                INVALIDATE_SP,
+                new Supplier<String>() {
+                    @Override
+                    public String get() {
+                        return "Field change callback for " + key + " triggered: " + sp;
+                    }
+                });
+    }
+
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(LOOKUP, AccessorProperty.class, name, MH.type(rtype, types));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java b/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java
index 579b6f3..db42e28 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CodeInstaller.java
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime;
 
+import java.util.Collection;
 import java.util.Map;
 import jdk.nashorn.internal.codegen.ClassEmitter;
 
@@ -48,12 +49,20 @@
     public T getOwner();
 
     /**
-     * Install a class
+     * Install a class.
      * @param className name of the class with / separation
      * @param bytecode  bytecode
      * @return the installed class
      */
-    public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants);
+    public Class<?> install(final String className, final byte[] bytecode);
+
+    /**
+     * Initialize already installed classes.
+     * @param classes the class to initialize
+     * @param source the source object for the classes
+     * @param constants the runtime constants for the classes
+     */
+    public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants);
 
     /**
      * Verify generated bytecode before emission. This is called back from the
@@ -83,5 +92,14 @@
      * @param classBytes map of class names to class bytes
      * @param constants constants array
      */
-    public void storeCompiledScript(Source source, String mainClassName, Map<String, byte[]> classBytes, Object[] constants);
+    public void storeScript(String cacheKey, Source source, String mainClassName, Map<String, byte[]> classBytes,
+                            Map<Integer, FunctionInitializer> initializers, Object[] constants, int compilationId);
+
+    /**
+     * Load a previously compiled script
+     * @param source the script source
+     * @param functionKey the function id and signature
+     * @return compiled script data
+     */
+    public StoredScript loadScript(Source source, String functionKey);
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java b/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java
index 8f59599..8d79320 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CodeStore.java
@@ -37,30 +37,31 @@
 import java.security.AccessController;
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
-import java.util.Base64;
 import java.util.Map;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * A code cache for persistent caching of compiled scripts.
  */
-final class CodeStore {
+@Logger(name="codestore")
+final class CodeStore implements Loggable {
 
     private final File dir;
     private final int minSize;
-
-    // Message digest to file name encoder
-    private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding();
+    private final DebugLogger log;
 
     // Default minimum size for storing a compiled script class
     private final static int DEFAULT_MIN_SIZE = 1000;
 
     /**
      * Constructor
-     * @param path directory to store code in
      * @throws IOException
      */
-    public CodeStore(final String path) throws IOException {
-        this(path, DEFAULT_MIN_SIZE);
+    public CodeStore(final Context context, final String path) throws IOException {
+        this(context, path, DEFAULT_MIN_SIZE);
     }
 
     /**
@@ -69,9 +70,20 @@
      * @param minSize minimum file size for caching scripts
      * @throws IOException
      */
-    public CodeStore(final String path, final int minSize) throws IOException {
+    public CodeStore(final Context context, final String path, final int minSize) throws IOException {
         this.dir = checkDirectory(path);
         this.minSize = minSize;
+        this.log = initLogger(context);
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+         return context.getLogger(getClass());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
     }
 
     private static File checkDirectory(final String path) throws IOException {
@@ -81,85 +93,99 @@
                 public File run() throws IOException {
                     final File dir = new File(path).getAbsoluteFile();
                     if (!dir.exists() && !dir.mkdirs()) {
-                        throw new IOException("Could not create directory: " + dir);
+                        throw new IOException("Could not create directory: " + dir.getPath());
                     } else if (!dir.isDirectory()) {
-                        throw new IOException("Not a directory: " + dir);
+                        throw new IOException("Not a directory: " + dir.getPath());
                     } else if (!dir.canRead() || !dir.canWrite()) {
-                        throw new IOException("Directory not readable or writable: " + dir);
+                        throw new IOException("Directory not readable or writable: " + dir.getPath());
                     }
                     return dir;
                 }
             });
-        } catch (PrivilegedActionException e) {
+        } catch (final PrivilegedActionException e) {
             throw (IOException) e.getException();
         }
     }
 
+    private File getCacheFile(final Source source, final String functionKey) {
+        return new File(dir, source.getDigest() + '-' + functionKey);
+    }
+
+    /**
+     * Generate a string representing the function with {@code functionId} and {@code paramTypes}.
+     * @param functionId function id
+     * @param paramTypes parameter types
+     * @return a string representing the function
+     */
+    public static String getCacheKey(final int functionId, final Type[] paramTypes) {
+        final StringBuilder b = new StringBuilder().append(functionId);
+        if(paramTypes != null && paramTypes.length > 0) {
+            b.append('-');
+            for(final Type t: paramTypes) {
+                b.append(Type.getShortSignatureDescriptor(t));
+            }
+        }
+        return b.toString();
+    }
+
     /**
      * Return a compiled script from the cache, or null if it isn't found.
      *
      * @param source the source
-     * @return the compiled script or null
-     * @throws IOException
-     * @throws ClassNotFoundException
+     * @param functionKey the function key
+     * @return the stored script or null
      */
-    public CompiledScript getScript(final Source source) throws IOException, ClassNotFoundException {
+    public StoredScript loadScript(final Source source, final String functionKey) {
         if (source.getLength() < minSize) {
             return null;
         }
 
-        final String digest = BASE64.encodeToString(source.getDigest());
-        final File file = new File(dir, digest);
+        final File file = getCacheFile(source, functionKey);
 
         try {
-            return AccessController.doPrivileged(new PrivilegedExceptionAction<CompiledScript>() {
+            return AccessController.doPrivileged(new PrivilegedExceptionAction<StoredScript>() {
                 @Override
-                public CompiledScript run() throws IOException, ClassNotFoundException {
+                public StoredScript run() throws IOException, ClassNotFoundException {
                     if (!file.exists()) {
                         return null;
                     }
                     try (ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(new FileInputStream(file)))) {
-                        CompiledScript compiledScript = (CompiledScript) in.readObject();
-                        compiledScript.setSource(source);
-                        return compiledScript;
+                        final StoredScript storedScript = (StoredScript) in.readObject();
+                        getLogger().info("loaded ", source, "-", functionKey);
+                        return storedScript;
                     }
                 }
             });
-        } catch (PrivilegedActionException e) {
-            final Exception ex = e.getException();
-            if (ex instanceof IOException) {
-                throw  (IOException) ex;
-            } else if (ex instanceof ClassNotFoundException) {
-                throw (ClassNotFoundException) ex;
-            }
-            throw (new RuntimeException(ex));
+        } catch (final PrivilegedActionException e) {
+            getLogger().warning("failed to load ", source, "-", functionKey, ": ", e.getException());
+            return null;
         }
     }
 
     /**
      * Store a compiled script in the cache.
      *
+     * @param functionKey the function key
      * @param source the source
      * @param mainClassName the main class name
      * @param classBytes a map of class bytes
      * @param constants the constants array
-     * @throws IOException
      */
-    public void putScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants)
-            throws IOException {
+    public void storeScript(final String functionKey, final Source source, final String mainClassName, final Map<String, byte[]> classBytes,
+                          final Map<Integer, FunctionInitializer> initializers, final Object[] constants, final int compilationId) {
         if (source.getLength() < minSize) {
             return;
         }
         for (final Object constant : constants) {
             // Make sure all constant data is serializable
             if (! (constant instanceof Serializable)) {
+                getLogger().warning("cannot store ", source, " non serializable constant ", constant);
                 return;
             }
         }
 
-        final String digest = BASE64.encodeToString(source.getDigest());
-        final File file = new File(dir, digest);
-        final CompiledScript script = new CompiledScript(source, mainClassName, classBytes, constants);
+        final File file = getCacheFile(source, functionKey);
+        final StoredScript script = new StoredScript(compilationId, mainClassName, classBytes, initializers, constants);
 
         try {
             AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
@@ -168,11 +194,12 @@
                     try (ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(new FileOutputStream(file)))) {
                         out.writeObject(script);
                     }
+                    getLogger().info("stored ", source, "-", functionKey);
                     return null;
                 }
             });
-        } catch (PrivilegedActionException e) {
-             throw (IOException) e.getException();
+        } catch (final PrivilegedActionException e) {
+            getLogger().warning("failed to store ", script, "-", functionKey, ": ", e.getException());
         }
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
index 18b20a3..958b259 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunction.java
@@ -24,51 +24,218 @@
  */
 package jdk.nashorn.internal.runtime;
 
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 
+import java.lang.invoke.CallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.MutableCallSite;
+import java.lang.invoke.SwitchPoint;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
+import jdk.nashorn.internal.codegen.TypeMap;
+import jdk.nashorn.internal.codegen.types.ArrayType;
 import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.FunctionNode;
+import jdk.nashorn.internal.runtime.events.RecompilationEvent;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
 
 /**
  * An version of a JavaScript function, native or JavaScript.
  * Supports lazily generating a constructor version of the invocation.
  */
-final class CompiledFunction implements Comparable<CompiledFunction> {
+final class CompiledFunction {
 
-    /** The method type may be more specific than the invoker, if. e.g.
-     *  the invoker is guarded, and a guard with a generic object only
-     *  fallback, while the target is more specific, we still need the
-     *  more specific type for sorting */
-    private final MethodType   type;
-    private final MethodHandle invoker;
+    private static final MethodHandle NEWFILTER = findOwnMH("newFilter", Object.class, Object.class, Object.class);
+    private static final MethodHandle RELINK_COMPOSABLE_INVOKER = findOwnMH("relinkComposableInvoker", void.class, CallSite.class, CompiledFunction.class, boolean.class);
+    private static final MethodHandle HANDLE_REWRITE_EXCEPTION = findOwnMH("handleRewriteException", MethodHandle.class, CompiledFunction.class, OptimismInfo.class, RewriteException.class);
+    private static final MethodHandle RESTOF_INVOKER = MethodHandles.exactInvoker(MethodType.methodType(Object.class, RewriteException.class));
+
+    private final DebugLogger log;
+
+    /**
+     * The method type may be more specific than the invoker, if. e.g.
+     * the invoker is guarded, and a guard with a generic object only
+     * fallback, while the target is more specific, we still need the
+     * more specific type for sorting
+     */
+    private MethodHandle invoker;
     private MethodHandle constructor;
+    private OptimismInfo optimismInfo;
+    private final int flags; // from FunctionNode
+    private final MethodType callSiteType;
 
-    CompiledFunction(final MethodType type, final MethodHandle invoker) {
-        this(type, invoker, null);
+    CompiledFunction(final MethodHandle invoker) {
+        this(invoker, null);
     }
 
-    CompiledFunction(final MethodType type, final MethodHandle invoker, final MethodHandle constructor) {
-        assert type != null;
-        this.type        = type;
-        this.invoker     = invoker;
+    static CompiledFunction createBuiltInConstructor(final MethodHandle invoker) {
+        return new CompiledFunction(MH.insertArguments(invoker, 0, false), createConstructorFromInvoker(MH.insertArguments(invoker, 0, true)));
+    }
+
+    CompiledFunction(final MethodHandle invoker, final MethodHandle constructor) {
+        this(invoker, constructor, 0, null, DebugLogger.DISABLED_LOGGER);
+    }
+
+    CompiledFunction(final MethodHandle invoker, final MethodHandle constructor, final int flags, final MethodType callSiteType, final DebugLogger log) {
+        this.invoker = invoker;
         this.constructor = constructor;
+        this.flags = flags;
+        this.callSiteType = callSiteType;
+        this.log = log;
+    }
+
+    CompiledFunction(final MethodHandle invoker, final RecompilableScriptFunctionData functionData,
+            final Map<Integer, Type> invalidatedProgramPoints, final MethodType callSiteType, final int flags) {
+        this(invoker, null, flags, callSiteType, functionData.getLogger());
+        if ((flags & FunctionNode.IS_DEOPTIMIZABLE) != 0) {
+            optimismInfo = new OptimismInfo(functionData, invalidatedProgramPoints);
+        } else {
+            optimismInfo = null;
+        }
+    }
+
+    int getFlags() {
+        return flags;
+    }
+
+    boolean isApplyToCall() {
+        return (flags & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0;
+    }
+
+    boolean isVarArg() {
+        return isVarArgsType(invoker.type());
     }
 
     @Override
     public String toString() {
-        return "<callSiteType= " + type + " invoker=" + invoker + " ctor=" + constructor + ">";
+        return "[invokerType=" + invoker.type() + " ctor=" + constructor + " weight=" + weight() + " isApplyToCall=" + isApplyToCall() + "]";
     }
 
-    MethodHandle getInvoker() {
-        return invoker;
+    boolean needsCallee() {
+        return ScriptFunctionData.needsCallee(invoker);
     }
 
-    MethodHandle getConstructor() {
+    /**
+     * Returns an invoker method handle for this function. Note that the handle is safely composable in
+     * the sense that you can compose it with other handles using any combinators even if you can't affect call site
+     * invalidation. If this compiled function is non-optimistic, then it returns the same value as
+     * {@link #getInvokerOrConstructor(boolean)}. However, if the function is optimistic, then this handle will
+     * incur an overhead as it will add an intermediate internal call site that can relink itself when the function
+     * needs to regenerate its code to always point at the latest generated code version.
+     * @return a guaranteed composable invoker method handle for this function.
+     */
+    MethodHandle createComposableInvoker() {
+        return createComposableInvoker(false);
+    }
+
+    /**
+     * Returns an invoker method handle for this function when invoked as a constructor. Note that the handle should be
+     * considered non-composable in the sense that you can only compose it with other handles using any combinators if
+     * you can ensure that the composition is guarded by {@link #getOptimisticAssumptionsSwitchPoint()} if it's
+     * non-null, and that you can relink the call site it is set into as a target if the switch point is invalidated. In
+     * all other cases, use {@link #createComposableConstructor()}.
+     * @return a direct constructor method handle for this function.
+     */
+    private MethodHandle getConstructor() {
+        if (constructor == null) {
+            constructor = createConstructorFromInvoker(createInvokerForPessimisticCaller());
+        }
+
         return constructor;
     }
 
-    void setConstructor(final MethodHandle constructor) {
-        this.constructor = constructor;
+    /**
+     * Creates a version of the invoker intended for a pessimistic caller (return type is Object, no caller optimistic
+     * program point available).
+     * @return a version of the invoker intended for a pessimistic caller.
+     */
+    private MethodHandle createInvokerForPessimisticCaller() {
+        return createInvoker(Object.class, INVALID_PROGRAM_POINT);
+    }
+
+    /**
+     * Compose a constructor from an invoker.
+     *
+     * @param invoker         invoker
+     * @return the composed constructor
+     */
+    private static MethodHandle createConstructorFromInvoker(final MethodHandle invoker) {
+        final boolean needsCallee = ScriptFunctionData.needsCallee(invoker);
+        // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having
+        // "this" in the first argument position is what allows the elegant folded composition of
+        // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor
+        // always returns Object.
+        final MethodHandle swapped = needsCallee ? swapCalleeAndThis(invoker) : invoker;
+
+        final MethodHandle returnsObject = MH.asType(swapped, swapped.type().changeReturnType(Object.class));
+
+        final MethodType ctorType = returnsObject.type();
+
+        // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually
+        // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it.
+        // (this, [callee, ]args...) => ([callee, ]args...)
+        final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray();
+
+        // Fold constructor into newFilter that replaces the return value from the constructor with the originally
+        // allocated value when the originally allocated value is a JS primitive (String, Boolean, Number).
+        // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...)
+        final MethodHandle filtered = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), returnsObject);
+
+        // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject...
+        if (needsCallee) {
+            // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and
+            // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...),
+            // or...
+            return MH.foldArguments(filtered, ScriptFunction.ALLOCATE);
+        }
+
+        // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee
+        // (this, args...) filter (callee) => (callee, args...)
+        return MH.filterArguments(filtered, 0, ScriptFunction.ALLOCATE);
+    }
+
+    /**
+     * Permutes the parameters in the method handle from {@code (callee, this, ...)} to {@code (this, callee, ...)}.
+     * Used when creating a constructor handle.
+     * @param mh a method handle with order of arguments {@code (callee, this, ...)}
+     * @return a method handle with order of arguments {@code (this, callee, ...)}
+     */
+    private static MethodHandle swapCalleeAndThis(final MethodHandle mh) {
+        final MethodType type = mh.type();
+        assert type.parameterType(0) == ScriptFunction.class : type;
+        assert type.parameterType(1) == Object.class : type;
+        final MethodType newType = type.changeParameterType(0, Object.class).changeParameterType(1, ScriptFunction.class);
+        final int[] reorder = new int[type.parameterCount()];
+        reorder[0] = 1;
+        assert reorder[1] == 0;
+        for (int i = 2; i < reorder.length; ++i) {
+            reorder[i] = i;
+        }
+        return MethodHandles.permuteArguments(mh, newType, reorder);
+    }
+
+    /**
+     * Returns an invoker method handle for this function when invoked as a constructor. Note that the handle is safely
+     * composable in the sense that you can compose it with other handles using any combinators even if you can't affect
+     * call site invalidation. If this compiled function is non-optimistic, then it returns the same value as
+     * {@link #getConstructor()}. However, if the function is optimistic, then this handle will incur an overhead as it
+     * will add an intermediate internal call site that can relink itself when the function needs to regenerate its code
+     * to always point at the latest generated code version.
+     * @return a guaranteed composable constructor method handle for this function.
+     */
+    MethodHandle createComposableConstructor() {
+        return createComposableInvoker(true);
     }
 
     boolean hasConstructor() {
@@ -76,45 +243,10 @@
     }
 
     MethodType type() {
-        return type;
+        return invoker.type();
     }
 
-    @Override
-    public int compareTo(final CompiledFunction o) {
-        return compareMethodTypes(type(), o.type());
-    }
-
-    private static int compareMethodTypes(final MethodType ownType, final MethodType otherType) {
-        // Comparable interface demands that compareTo() should only return 0 if objects are equal.
-        // Failing to meet this requirement causes same weight functions to replace each other in TreeSet,
-        // so we go some lengths to come up with an ordering between same weight functions,
-        // first falling back to parameter count and then to hash code.
-        if (ownType.equals(otherType)) {
-            return 0;
-        }
-
-        final int diff = weight(ownType) - weight(otherType);
-        if (diff != 0) {
-            return diff;
-        }
-        if (ownType.parameterCount() != otherType.parameterCount()) {
-            return ownType.parameterCount() - otherType.parameterCount();
-        }
-        // We're just interested in not returning 0 here, not correct ordering
-        return ownType.hashCode() - otherType.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return obj instanceof CompiledFunction && type().equals(((CompiledFunction)obj).type());
-    }
-
-    @Override
-    public int hashCode() {
-        return type().hashCode();
-    }
-
-    private int weight() {
+    int weight() {
         return weight(type());
     }
 
@@ -124,76 +256,599 @@
         }
 
         int weight = Type.typeFor(type.returnType()).getWeight();
-        for (final Class<?> paramType : type.parameterArray()) {
+        for (int i = 0 ; i < type.parameterCount() ; i++) {
+            final Class<?> paramType = type.parameterType(i);
             final int pweight = Type.typeFor(paramType).getWeight() * 2; //params are more important than call types as return values are always specialized
             weight += pweight;
         }
+
+        weight += type.parameterCount(); //more params outweigh few parameters
+
         return weight;
     }
 
-    private static boolean isVarArgsType(final MethodType type) {
+    static boolean isVarArgsType(final MethodType type) {
         assert type.parameterCount() >= 1 : type;
         return type.parameterType(type.parameterCount() - 1) == Object[].class;
     }
 
-    boolean moreGenericThan(final CompiledFunction o) {
-        return weight() > o.weight();
+    static boolean moreGenericThan(final MethodType mt0, final MethodType mt1) {
+        return weight(mt0) > weight(mt1);
     }
 
-    boolean moreGenericThan(final MethodType mt) {
-        return weight() > weight(mt);
+    boolean betterThanFinal(final CompiledFunction other, final MethodType callSiteMethodType) {
+        // Prefer anything over nothing, as we can't compile new versions.
+        if (other == null) {
+            return true;
+        }
+        return betterThanFinal(type(), other.type(), callSiteMethodType);
     }
 
-    /**
-     * Check whether a given method descriptor is compatible with this invocation.
-     * It is compatible if the types are narrower than the invocation type so that
-     * a semantically equivalent linkage can be performed.
-     *
-     * @param mt type to check against
-     * @return true if types are compatible
-     */
-    boolean typeCompatible(final MethodType mt) {
-        final int wantedParamCount   = mt.parameterCount();
-        final int existingParamCount = type.parameterCount();
+    static boolean betterThanFinal(final MethodType thisMethodType, final MethodType otherMethodType, final MethodType callSiteMethodType) {
+        final int thisParamCount = getParamCount(thisMethodType);
+        final int otherParamCount = getParamCount(otherMethodType);
+        final int callSiteRawParamCount = getParamCount(callSiteMethodType);
+        final boolean csVarArg = callSiteRawParamCount == Integer.MAX_VALUE;
+        // Subtract 1 for callee for non-vararg call sites
+        final int callSiteParamCount = csVarArg ? callSiteRawParamCount : callSiteRawParamCount - 1;
 
-        //if we are not examining a varargs type, the number of parameters must be the same
-        if (wantedParamCount != existingParamCount && !isVarArgsType(mt)) {
+        // Prefer the function that discards less parameters
+        final int thisDiscardsParams = Math.max(callSiteParamCount - thisParamCount, 0);
+        final int otherDiscardsParams = Math.max(callSiteParamCount - otherParamCount, 0);
+        if(thisDiscardsParams < otherDiscardsParams) {
+            return true;
+        }
+        if(thisDiscardsParams > otherDiscardsParams) {
             return false;
         }
 
-        //we only go as far as the shortest array. the only chance to make this work if
-        //parameters lengths do not match is if our type ends with a varargs argument.
-        //then every trailing parameter in the given callsite can be folded into it, making
-        //us compatible (albeit slower than a direct specialization)
-        final int lastParamIndex = Math.min(wantedParamCount, existingParamCount);
-        for (int i = 0; i < lastParamIndex; i++) {
-            final Type w = Type.typeFor(mt.parameterType(i));
-            final Type e = Type.typeFor(type.parameterType(i));
+        final boolean thisVarArg = thisParamCount == Integer.MAX_VALUE;
+        final boolean otherVarArg = otherParamCount == Integer.MAX_VALUE;
+        if(!(thisVarArg && otherVarArg && csVarArg)) {
+            // At least one of them isn't vararg
+            final Type[] thisType = toTypeWithoutCallee(thisMethodType, 0); // Never has callee
+            final Type[] otherType = toTypeWithoutCallee(otherMethodType, 0); // Never has callee
+            final Type[] callSiteType = toTypeWithoutCallee(callSiteMethodType, 1); // Always has callee
 
-            //don't specialize on booleans, we have the "true" vs int 1 ambiguity in resolution
-            //we also currently don't support boolean as a javascript function callsite type.
-            //it will always box.
-            if (w.isBoolean()) {
+            int narrowWeightDelta = 0;
+            int widenWeightDelta = 0;
+            final int minParamsCount = Math.min(Math.min(thisParamCount, otherParamCount), callSiteParamCount);
+            for(int i = 0; i < minParamsCount; ++i) {
+                final int callSiteParamWeight = getParamType(i, callSiteType, csVarArg).getWeight();
+                // Delta is negative for narrowing, positive for widening
+                final int thisParamWeightDelta = getParamType(i, thisType, thisVarArg).getWeight() - callSiteParamWeight;
+                final int otherParamWeightDelta = getParamType(i, otherType, otherVarArg).getWeight() - callSiteParamWeight;
+                // Only count absolute values of narrowings
+                narrowWeightDelta += Math.max(-thisParamWeightDelta, 0) - Math.max(-otherParamWeightDelta, 0);
+                // Only count absolute values of widenings
+                widenWeightDelta += Math.max(thisParamWeightDelta, 0) - Math.max(otherParamWeightDelta, 0);
+            }
+
+            // If both functions accept more arguments than what is passed at the call site, account for ability
+            // to receive Undefined un-narrowed in the remaining arguments.
+            if(!thisVarArg) {
+                for(int i = callSiteParamCount; i < thisParamCount; ++i) {
+                    narrowWeightDelta += Math.max(Type.OBJECT.getWeight() - thisType[i].getWeight(), 0);
+                }
+            }
+            if(!otherVarArg) {
+                for(int i = callSiteParamCount; i < otherParamCount; ++i) {
+                    narrowWeightDelta -= Math.max(Type.OBJECT.getWeight() - otherType[i].getWeight(), 0);
+                }
+            }
+
+            // Prefer function that narrows less
+            if(narrowWeightDelta < 0) {
+                return true;
+            }
+            if(narrowWeightDelta > 0) {
                 return false;
             }
 
-            //This callsite type has a vararg here. it will swallow all remaining args.
-            //for consistency, check that it's the last argument
-            if (e.isArray()) {
+            // Prefer function that widens less
+            if(widenWeightDelta < 0) {
                 return true;
             }
-
-            //Our arguments must be at least as wide as the wanted one, if not wider
-            if (Type.widest(w, e) != e) {
-                //e.g. this invocation takes double and callsite says "object". reject. won't fit
-                //but if invocation takes a double and callsite says "int" or "long" or "double", that's fine
+            if(widenWeightDelta > 0) {
                 return false;
             }
         }
 
-        return true; // anything goes for return type, take the convenient one and it will be upcasted thru dynalink magic.
+        // Prefer the function that exactly matches the arity of the call site.
+        if(thisParamCount == callSiteParamCount && otherParamCount != callSiteParamCount) {
+            return true;
+        }
+        if(thisParamCount != callSiteParamCount && otherParamCount == callSiteParamCount) {
+            return false;
+        }
+
+        // Otherwise, neither function matches arity exactly. We also know that at this point, they both can receive
+        // more arguments than call site, otherwise we would've already chosen the one that discards less parameters.
+        // Note that variable arity methods are preferred, as they actually match the call site arity better, since they
+        // really have arbitrary arity.
+        if(thisVarArg) {
+            if(!otherVarArg) {
+                return true; //
+            }
+        } else if(otherVarArg) {
+            return false;
+        }
+
+        // Neither is variable arity; chose the one that has less extra parameters.
+        final int fnParamDelta = thisParamCount - otherParamCount;
+        if(fnParamDelta < 0) {
+            return true;
+        }
+        if(fnParamDelta > 0) {
+            return false;
+        }
+
+        final int callSiteRetWeight = Type.typeFor(callSiteMethodType.returnType()).getWeight();
+        // Delta is negative for narrower return type, positive for wider return type
+        final int thisRetWeightDelta = Type.typeFor(thisMethodType.returnType()).getWeight() - callSiteRetWeight;
+        final int otherRetWeightDelta = Type.typeFor(otherMethodType.returnType()).getWeight() - callSiteRetWeight;
+
+        // Prefer function that returns a less wide return type
+        final int widenRetDelta = Math.max(thisRetWeightDelta, 0) - Math.max(otherRetWeightDelta, 0);
+        if(widenRetDelta < 0) {
+            return true;
+        }
+        if(widenRetDelta > 0) {
+            return false;
+        }
+
+        // Prefer function that returns a less narrow return type
+        final int narrowRetDelta = Math.max(-thisRetWeightDelta, 0) - Math.max(-otherRetWeightDelta, 0);
+        if(narrowRetDelta < 0) {
+            return true;
+        }
+        if(narrowRetDelta > 0) {
+            return false;
+        }
+
+        throw new AssertionError(thisMethodType + " identically applicable to " + otherMethodType + " for " + callSiteMethodType); // Signatures are identical
     }
 
+    private static Type[] toTypeWithoutCallee(final MethodType type, final int thisIndex) {
+        final int paramCount = type.parameterCount();
+        final Type[] t = new Type[paramCount - thisIndex];
+        for(int i = thisIndex; i < paramCount; ++i) {
+            t[i - thisIndex] = Type.typeFor(type.parameterType(i));
+        }
+        return t;
+    }
 
+    private static Type getParamType(final int i, final Type[] paramTypes, final boolean isVarArg) {
+        final int fixParamCount = paramTypes.length - (isVarArg ? 1 : 0);
+        if(i < fixParamCount) {
+            return paramTypes[i];
+        }
+        assert isVarArg;
+        return ((ArrayType)paramTypes[paramTypes.length - 1]).getElementType();
+    }
 
+    boolean matchesCallSite(final MethodType callSiteType, final boolean pickVarArg) {
+        if (callSiteType.equals(this.callSiteType)) {
+            return true;
+        }
+        final MethodType type  = type();
+        final int fnParamCount = getParamCount(type);
+        final boolean isVarArg = fnParamCount == Integer.MAX_VALUE;
+        if (isVarArg) {
+            return pickVarArg;
+        }
+
+        final int csParamCount = getParamCount(callSiteType);
+        final boolean csIsVarArg = csParamCount == Integer.MAX_VALUE;
+        final int thisThisIndex = needsCallee() ? 1 : 0; // Index of "this" parameter in this function's type
+
+        final int fnParamCountNoCallee = fnParamCount - thisThisIndex;
+        final int minParams = Math.min(csParamCount - 1, fnParamCountNoCallee); // callSiteType always has callee, so subtract 1
+        // We must match all incoming parameters, except "this". Starting from 1 to skip "this".
+        for(int i = 1; i < minParams; ++i) {
+            final Type fnType = Type.typeFor(type.parameterType(i + thisThisIndex));
+            final Type csType = csIsVarArg ? Type.OBJECT : Type.typeFor(callSiteType.parameterType(i + 1));
+            if(!fnType.isEquivalentTo(csType)) {
+                return false;
+            }
+        }
+
+        // Must match any undefined parameters to Object type.
+        for(int i = minParams; i < fnParamCountNoCallee; ++i) {
+            if(!Type.typeFor(type.parameterType(i + thisThisIndex)).isEquivalentTo(Type.OBJECT)) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
+    private static int getParamCount(final MethodType type) {
+        final int paramCount = type.parameterCount();
+        return type.parameterType(paramCount - 1).isArray() ? Integer.MAX_VALUE : paramCount;
+    }
+
+    private boolean canBeDeoptimized() {
+        return optimismInfo != null;
+    }
+
+    private MethodHandle createComposableInvoker(final boolean isConstructor) {
+        final MethodHandle handle = getInvokerOrConstructor(isConstructor);
+
+        // If compiled function is not optimistic, it can't ever change its invoker/constructor, so just return them
+        // directly.
+        if(!canBeDeoptimized()) {
+            return handle;
+        }
+
+        // Otherwise, we need a new level of indirection; need to introduce a mutable call site that can relink itslef
+        // to the compiled function's changed target whenever the optimistic assumptions are invalidated.
+        final CallSite cs = new MutableCallSite(handle.type());
+        relinkComposableInvoker(cs, this, isConstructor);
+        return cs.dynamicInvoker();
+    }
+
+    private static class HandleAndAssumptions {
+        final MethodHandle handle;
+        final SwitchPoint assumptions;
+
+        HandleAndAssumptions(final MethodHandle handle, final SwitchPoint assumptions) {
+            this.handle = handle;
+            this.assumptions = assumptions;
+        }
+
+        GuardedInvocation createInvocation() {
+            return new GuardedInvocation(handle, assumptions);
+        }
+    }
+
+    /**
+     * Returns a pair of an invocation created with a passed-in supplier and a non-invalidated switch point for
+     * optimistic assumptions (or null for the switch point if the function can not be deoptimized). While the method
+     * makes a best effort to return a non-invalidated switch point (compensating for possible deoptimizing
+     * recompilation happening on another thread) it is still possible that by the time this method returns the
+     * switchpoint has been invalidated by a {@code RewriteException} triggered on another thread for this function.
+     * This is not a problem, though, as these switch points are always used to produce call sites that fall back to
+     * relinking when they are invalidated, and in this case the execution will end up here again. What this method
+     * basically does is minimize such busy-loop relinking while the function is being recompiled on a different thread.
+     * @param invocationSupplier the supplier that constructs the actual invocation method handle; should use the
+     * {@code CompiledFunction} method itself in some capacity.
+     * @return a tuple object containing the method handle as created by the supplier and an optimistic assumptions
+     * switch point that is guaranteed to not have been invalidated before the call to this method (or null if the
+     * function can't be further deoptimized).
+     */
+    private synchronized HandleAndAssumptions getValidOptimisticInvocation(final Supplier<MethodHandle> invocationSupplier) {
+        for(;;) {
+            final MethodHandle handle = invocationSupplier.get();
+            final SwitchPoint assumptions = canBeDeoptimized() ? optimismInfo.optimisticAssumptions : null;
+            if(assumptions != null && assumptions.hasBeenInvalidated()) {
+                // We can be in a situation where one thread is in the middle of a deoptimizing compilation when we hit
+                // this and thus, it has invalidated the old switch point, but hasn't created the new one yet. Note that
+                // the behavior of invalidating the old switch point before recompilation, and only creating the new one
+                // after recompilation is by design. If we didn't wait here for the recompilation to complete, we would
+                // be busy looping through the fallback path of the invalidated switch point, relinking the call site
+                // again with the same invalidated switch point, invoking the fallback, etc. stealing CPU cycles from
+                // the recompilation task we're dependent on. This can still happen if the switch point gets invalidated
+                // after we grabbed it here, in which case we'll indeed do one busy relink immediately.
+                try {
+                    wait();
+                } catch (final InterruptedException e) {
+                    // Intentionally ignored. There's nothing meaningful we can do if we're interrupted
+                }
+            } else {
+                return new HandleAndAssumptions(handle, assumptions);
+            }
+        }
+    }
+
+    private static void relinkComposableInvoker(final CallSite cs, final CompiledFunction inv, final boolean constructor) {
+        final HandleAndAssumptions handleAndAssumptions = inv.getValidOptimisticInvocation(new Supplier<MethodHandle>() {
+            @Override
+            public MethodHandle get() {
+                return inv.getInvokerOrConstructor(constructor);
+            }
+        });
+        final MethodHandle handle = handleAndAssumptions.handle;
+        final SwitchPoint assumptions = handleAndAssumptions.assumptions;
+        final MethodHandle target;
+        if(assumptions == null) {
+            target = handle;
+        } else {
+            final MethodHandle relink = MethodHandles.insertArguments(RELINK_COMPOSABLE_INVOKER, 0, cs, inv, constructor);
+            target = assumptions.guardWithTest(handle, MethodHandles.foldArguments(cs.dynamicInvoker(), relink));
+        }
+        cs.setTarget(target.asType(cs.type()));
+    }
+
+    private MethodHandle getInvokerOrConstructor(final boolean selectCtor) {
+        return selectCtor ? getConstructor() : createInvokerForPessimisticCaller();
+    }
+
+    /**
+     * Returns a guarded invocation for this function when not invoked as a constructor. The guarded invocation has no
+     * guard but it potentially has an optimistic assumptions switch point. As such, it will probably not be used as a
+     * final guarded invocation, but rather as a holder for an invocation handle and switch point to be decomposed and
+     * reassembled into a different final invocation by the user of this method. Any recompositions should take care to
+     * continue to use the switch point. If that is not possible, use {@link #createComposableInvoker()} instead.
+     * @return a guarded invocation for an ordinary (non-constructor) invocation of this function.
+     */
+    GuardedInvocation createFunctionInvocation(final Class<?> callSiteReturnType, final int callerProgramPoint) {
+        return getValidOptimisticInvocation(new Supplier<MethodHandle>() {
+            @Override
+            public MethodHandle get() {
+                return createInvoker(callSiteReturnType, callerProgramPoint);
+            }
+        }).createInvocation();
+    }
+
+    /**
+     * Returns a guarded invocation for this function when invoked as a constructor. The guarded invocation has no guard
+     * but it potentially has an optimistic assumptions switch point. As such, it will probably not be used as a final
+     * guarded invocation, but rather as a holder for an invocation handle and switch point to be decomposed and
+     * reassembled into a different final invocation by the user of this method. Any recompositions should take care to
+     * continue to use the switch point. If that is not possible, use {@link #createComposableConstructor()} instead.
+     * @return a guarded invocation for invocation of this function as a constructor.
+     */
+    GuardedInvocation createConstructorInvocation() {
+        return getValidOptimisticInvocation(new Supplier<MethodHandle>() {
+            @Override
+            public MethodHandle get() {
+                return getConstructor();
+            }
+        }).createInvocation();
+    }
+
+    private MethodHandle createInvoker(final Class<?> callSiteReturnType, final int callerProgramPoint) {
+        final boolean isOptimistic = canBeDeoptimized();
+        MethodHandle handleRewriteException = isOptimistic ? createRewriteExceptionHandler() : null;
+
+        MethodHandle inv = invoker;
+        if(isValid(callerProgramPoint)) {
+            inv = OptimisticReturnFilters.filterOptimisticReturnValue(inv, callSiteReturnType, callerProgramPoint);
+            inv = changeReturnType(inv, callSiteReturnType);
+            if(callSiteReturnType.isPrimitive() && handleRewriteException != null) {
+                // because handleRewriteException always returns Object
+                handleRewriteException = OptimisticReturnFilters.filterOptimisticReturnValue(handleRewriteException,
+                        callSiteReturnType, callerProgramPoint);
+            }
+        } else if(isOptimistic) {
+            // Required so that rewrite exception has the same return type. It'd be okay to do it even if we weren't
+            // optimistic, but it isn't necessary as the linker upstream will eventually convert the return type.
+            inv = changeReturnType(inv, callSiteReturnType);
+        }
+
+        if(isOptimistic) {
+            assert handleRewriteException != null;
+            final MethodHandle typedHandleRewriteException = changeReturnType(handleRewriteException, inv.type().returnType());
+            return MH.catchException(inv, RewriteException.class, typedHandleRewriteException);
+        }
+        return inv;
+    }
+
+    private MethodHandle createRewriteExceptionHandler() {
+        return MH.foldArguments(RESTOF_INVOKER, MH.insertArguments(HANDLE_REWRITE_EXCEPTION, 0, this, optimismInfo));
+    }
+
+    private static MethodHandle changeReturnType(final MethodHandle mh, final Class<?> newReturnType) {
+        return Bootstrap.getLinkerServices().asType(mh, mh.type().changeReturnType(newReturnType));
+    }
+
+    @SuppressWarnings("unused")
+    private static MethodHandle handleRewriteException(final CompiledFunction function, final OptimismInfo oldOptimismInfo, final RewriteException re) {
+        return function.handleRewriteException(oldOptimismInfo, re);
+    }
+
+    /**
+     * Debug function for printing out all invalidated program points and their
+     * invalidation mapping to next type
+     * @param ipp
+     * @return string describing the ipp map
+     */
+    private static String toStringInvalidations(final Map<Integer, Type> ipp) {
+        if (ipp == null) {
+            return "";
+        }
+
+        final StringBuilder sb = new StringBuilder();
+
+        for (final Iterator<Map.Entry<Integer, Type>> iter = ipp.entrySet().iterator(); iter.hasNext(); ) {
+            final Map.Entry<Integer, Type> entry = iter.next();
+            final char bct = entry.getValue().getBytecodeStackType();
+
+            sb.append('[').
+                    append(entry.getKey()).
+                    append("->").
+                    append(bct == 'A' ? 'O' : bct).
+                    append(']');
+
+            if (iter.hasNext()) {
+                sb.append(' ');
+            }
+        }
+
+        return sb.toString();
+    }
+
+    private void logRecompile(final String reason, final FunctionNode fn, final MethodType callSiteType, final Map<Integer, Type> ipp) {
+        if (log.isEnabled()) {
+            log.info(reason, DebugLogger.quote(fn.getName()), " signature: ", callSiteType, " ", toStringInvalidations(ipp));
+        }
+    }
+
+    /**
+     * Handles a {@link RewriteException} raised during the execution of this function by recompiling (if needed) the
+     * function with an optimistic assumption invalidated at the program point indicated by the exception, and then
+     * executing a rest-of method to complete the execution with the deoptimized version.
+     * @param oldOptInfo the optimism info of this function. We must store it explicitly as a bound argument in the
+     * method handle, otherwise it could be null for handling a rewrite exception in an outer invocation of a recursive
+     * function when recursive invocations of the function have completely deoptimized it.
+     * @param re the rewrite exception that was raised
+     * @return the method handle for the rest-of method, for folding composition.
+     */
+    private synchronized MethodHandle handleRewriteException(final OptimismInfo oldOptInfo, final RewriteException re) {
+        if (log.isEnabled()) {
+            log.info(new RecompilationEvent(Level.INFO, re, re.getReturnValueNonDestructive()), "RewriteException ", re.getMessageShort());
+        }
+
+        final MethodType type = type();
+
+        // Compiler needs a call site type as its input, which always has a callee parameter, so we must add it if
+        // this function doesn't have a callee parameter.
+        final MethodType callSiteType = type.parameterType(0) == ScriptFunction.class ?
+                type :
+                type.insertParameterTypes(0, ScriptFunction.class);
+        final OptimismInfo currentOptInfo = optimismInfo;
+        final boolean shouldRecompile = currentOptInfo != null && currentOptInfo.requestRecompile(re);
+
+        // Effective optimism info, for subsequent use. We'll normally try to use the current (latest) one, but if it
+        // isn't available, we'll use the old one bound into the call site.
+        final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo;
+        FunctionNode fn = effectiveOptInfo.reparse();
+        final Compiler compiler = effectiveOptInfo.getCompiler(fn, callSiteType, re); //set to non rest-of
+
+        if (!shouldRecompile) {
+            // It didn't necessarily recompile, e.g. for an outer invocation of a recursive function if we already
+            // recompiled a deoptimized version for an inner invocation.
+            // We still need to do the rest of from the beginning
+            logRecompile("Rest-of compilation [STANDALONE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
+            return restOfHandle(effectiveOptInfo, compiler.compile(fn, CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
+        }
+
+        logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
+        fn = compiler.compile(fn, CompilationPhases.COMPILE_UPTO_BYTECODE);
+        log.info("Reusable IR generated");
+
+        // compile the rest of the function, and install it
+        log.info("Generating and installing bytecode from reusable IR...");
+        logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
+        final FunctionNode normalFn = compiler.compile(fn, CompilationPhases.COMPILE_FROM_BYTECODE);
+
+        if (effectiveOptInfo.data.usePersistentCodeCache()) {
+            final RecompilableScriptFunctionData data = effectiveOptInfo.data;
+            final int functionNodeId = data.getFunctionNodeId();
+            final TypeMap typeMap = data.typeMap(callSiteType);
+            final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
+            final String cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
+            compiler.persistClassInfo(cacheKey, normalFn);
+        }
+
+        FunctionNode fn2 = effectiveOptInfo.reparse();
+        fn2 = compiler.compile(fn2, CompilationPhases.COMPILE_UPTO_BYTECODE);
+        log.info("Done.");
+
+        final boolean canBeDeoptimized = normalFn.canBeDeoptimized();
+
+        if (log.isEnabled()) {
+            log.info("Recompiled '", fn.getName(), "' (", Debug.id(this), ") ", canBeDeoptimized ? " can still be deoptimized." : " is completely deoptimized.");
+        }
+
+        log.info("Looking up invoker...");
+
+        final MethodHandle newInvoker = effectiveOptInfo.data.lookup(fn);
+        invoker     = newInvoker.asType(type.changeReturnType(newInvoker.type().returnType()));
+        constructor = null; // Will be regenerated when needed
+
+        log.info("Done: ", invoker);
+        final MethodHandle restOf = restOfHandle(effectiveOptInfo, compiler.compile(fn, CompilationPhases.COMPILE_FROM_BYTECODE_RESTOF), canBeDeoptimized);
+
+        // Note that we only adjust the switch point after we set the invoker/constructor. This is important.
+        if (canBeDeoptimized) {
+            effectiveOptInfo.newOptimisticAssumptions(); // Otherwise, set a new switch point.
+        } else {
+            optimismInfo = null; // If we got to a point where we no longer have optimistic assumptions, let the optimism info go.
+        }
+        notifyAll();
+
+        return restOf;
+    }
+
+    private MethodHandle restOfHandle(final OptimismInfo info, final FunctionNode restOfFunction, final boolean canBeDeoptimized) {
+        assert info != null;
+        assert restOfFunction.getCompileUnit().getUnitClassName().contains("restOf");
+        final MethodHandle restOf =
+                changeReturnType(
+                        info.data.lookupCodeMethod(
+                                restOfFunction.getCompileUnit().getCode(),
+                                MH.type(restOfFunction.getReturnType().getTypeClass(),
+                                        RewriteException.class)),
+                        Object.class);
+
+        if (!canBeDeoptimized) {
+            return restOf;
+        }
+
+        // If rest-of is itself optimistic, we must make sure that we can repeat a deoptimization if it, too hits an exception.
+        return MH.catchException(restOf, RewriteException.class, createRewriteExceptionHandler());
+
+    }
+
+    private static class OptimismInfo {
+        // TODO: this is pointing to its owning ScriptFunctionData. Re-evaluate if that's okay.
+        private final RecompilableScriptFunctionData data;
+        private final Map<Integer, Type> invalidatedProgramPoints;
+        private SwitchPoint optimisticAssumptions;
+        private final DebugLogger log;
+
+        OptimismInfo(final RecompilableScriptFunctionData data, final Map<Integer, Type> invalidatedProgramPoints) {
+            this.data = data;
+            this.log  = data.getLogger();
+            this.invalidatedProgramPoints = invalidatedProgramPoints == null ? new TreeMap<Integer, Type>() : invalidatedProgramPoints;
+            newOptimisticAssumptions();
+        }
+
+        private void newOptimisticAssumptions() {
+            optimisticAssumptions = new SwitchPoint();
+        }
+
+        boolean requestRecompile(final RewriteException e) {
+            final Type retType            = e.getReturnType();
+            final Type previousFailedType = invalidatedProgramPoints.put(e.getProgramPoint(), retType);
+
+            if (previousFailedType != null && !previousFailedType.narrowerThan(retType)) {
+                final StackTraceElement[] stack      = e.getStackTrace();
+                final String              functionId = stack.length == 0 ?
+                        data.getName() :
+                        stack[0].getClassName() + "." + stack[0].getMethodName();
+
+                log.info("RewriteException for an already invalidated program point ", e.getProgramPoint(), " in ", functionId, ". This is okay for a recursive function invocation, but a bug otherwise.");
+
+                return false;
+            }
+
+            SwitchPoint.invalidateAll(new SwitchPoint[] { optimisticAssumptions });
+
+            return true;
+        }
+
+        Compiler getCompiler(final FunctionNode fn, final MethodType actualCallSiteType, final RewriteException e) {
+            return data.getCompiler(fn, actualCallSiteType, e.getRuntimeScope(), invalidatedProgramPoints, getEntryPoints(e));
+        }
+
+        private static int[] getEntryPoints(final RewriteException e) {
+            final int[] prevEntryPoints = e.getPreviousContinuationEntryPoints();
+            final int[] entryPoints;
+            if (prevEntryPoints == null) {
+                entryPoints = new int[1];
+            } else {
+                final int l = prevEntryPoints.length;
+                entryPoints = new int[l + 1];
+                System.arraycopy(prevEntryPoints, 0, entryPoints, 1, l);
+            }
+            entryPoints[0] = e.getProgramPoint();
+            return entryPoints;
+        }
+
+        FunctionNode reparse() {
+            return data.reparse();
+        }
+    }
+
+    @SuppressWarnings("unused")
+    private static Object newFilter(final Object result, final Object allocation) {
+        return (result instanceof ScriptObject || !JSType.isPrimitive(result))? result : allocation;
+    }
+
+    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), CompiledFunction.class, name, MH.type(rtype, types));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunctions.java
deleted file mode 100644
index ba5ae66..0000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledFunctions.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.
- */
-package jdk.nashorn.internal.runtime;
-
-import java.lang.invoke.MethodHandle;
-import java.lang.invoke.MethodType;
-import java.util.Iterator;
-import java.util.TreeSet;
-
-/**
- * This is a list of code versions of a function.
- * The list is sorted in ascending order of generic descriptors
- */
-@SuppressWarnings("serial")
-final class CompiledFunctions extends TreeSet<CompiledFunction> {
-
-    private CompiledFunction generic;
-
-    CompiledFunction best(final MethodType type) {
-        final Iterator<CompiledFunction> iter = iterator();
-        while (iter.hasNext()) {
-            final CompiledFunction next = iter.next();
-            if (next.typeCompatible(type)) {
-                return next;
-            }
-        }
-        return generic();
-    }
-
-    boolean needsCallee() {
-        return ScriptFunctionData.needsCallee(mostGeneric().getInvoker());
-    }
-
-    CompiledFunction mostGeneric() {
-        return last();
-    }
-
-    CompiledFunction generic() {
-        CompiledFunction gen = this.generic;
-        if (gen == null) {
-            gen = this.generic = makeGeneric(mostGeneric());
-        }
-        return gen;
-    }
-
-    private static CompiledFunction makeGeneric(final CompiledFunction func) {
-        final MethodHandle invoker = composeGenericMethod(func.getInvoker());
-        final MethodHandle constructor = func.hasConstructor() ? composeGenericMethod(func.getConstructor()) : null;
-        return new CompiledFunction(invoker.type(), invoker, constructor);
-    }
-
-    /**
-     * Takes a method handle, and returns a potentially different method handle that can be used in
-     * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}.
-     * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into
-     * {@code Object} as well, except for the following ones:
-     * <ul>
-     *   <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li>
-     *   <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself
-     *   (callee) as an argument.</li>
-     * </ul>
-     *
-     * @param mh the original method handle
-     *
-     * @return the new handle, conforming to the rules above.
-     */
-    private static MethodHandle composeGenericMethod(final MethodHandle mh) {
-        final MethodType type = mh.type();
-        final boolean isVarArg = ScriptFunctionData.isVarArg(mh);
-        final int paramCount = isVarArg ? type.parameterCount() - 1 : type.parameterCount();
-
-        MethodType newType = MethodType.genericMethodType(paramCount, isVarArg);
-
-        if (ScriptFunctionData.needsCallee(mh)) {
-            newType = newType.changeParameterType(0, ScriptFunction.class);
-        }
-        return type.equals(newType) ? mh : mh.asType(newType);
-    }
-
-    /**
-     * Is the given type even more specific than this entire list? That means
-     * we have an opportunity for more specific versions of the method
-     * through lazy code generation
-     *
-     * @param type type to check against
-     * @return true if the given type is more specific than all invocations available
-     */
-    boolean isLessSpecificThan(final MethodType type) {
-        return best(type).moreGenericThan(type);
-    }
-
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ConsString.java b/nashorn/src/jdk/nashorn/internal/runtime/ConsString.java
index 8f764f4..a181b0c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ConsString.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ConsString.java
@@ -36,8 +36,12 @@
 public final class ConsString implements CharSequence {
 
     private CharSequence left, right;
-    final private int length;
-    private boolean flat = false;
+    private final int length;
+    private volatile int state = STATE_NEW;
+
+    private final static int STATE_NEW       =  0;
+    private final static int STATE_THRESHOLD =  2;
+    private final static int STATE_FLATTENED = -1;
 
     /**
      * Constructor
@@ -53,11 +57,14 @@
         this.left = left;
         this.right = right;
         length = left.length() + right.length();
+        if (length < 0) {
+            throw new IllegalArgumentException("too big concatenated String");
+        }
     }
 
     @Override
     public String toString() {
-        return (String) flattened();
+        return (String) flattened(true);
     }
 
     @Override
@@ -67,22 +74,31 @@
 
     @Override
     public char charAt(final int index) {
-        return flattened().charAt(index);
+        return flattened(true).charAt(index);
     }
 
     @Override
     public CharSequence subSequence(final int start, final int end) {
-        return flattened().subSequence(start, end);
+        return flattened(true).subSequence(start, end);
     }
 
-    private CharSequence flattened() {
-        if (!flat) {
-            flatten();
+    /**
+     * Returns the components of this ConsString as a {@code CharSequence} array with two elements.
+     * The elements will be either {@code Strings} or other {@code ConsStrings}.
+     * @return CharSequence array of length 2
+     */
+    public synchronized CharSequence[] getComponents() {
+        return new CharSequence[] { left, right };
+    }
+
+    private CharSequence flattened(final boolean flattenNested) {
+        if (state != STATE_FLATTENED) {
+            flatten(flattenNested);
         }
         return left;
     }
 
-    private void flatten() {
+    private synchronized void flatten(final boolean flattenNested) {
         // We use iterative traversal as recursion may exceed the stack size limit.
         final char[] chars = new char[length];
         int pos = length;
@@ -97,8 +113,14 @@
         do {
             if (cs instanceof ConsString) {
                 final ConsString cons = (ConsString) cs;
-                stack.addFirst(cons.left);
-                cs = cons.right;
+                // Count the times a cons-string is traversed as part of other cons-strings being flattened.
+                // If it crosses a threshold we flatten the nested cons-string internally.
+                if (cons.state == STATE_FLATTENED || (flattenNested && ++cons.state >= STATE_THRESHOLD)) {
+                    cs = cons.flattened(false);
+                } else {
+                    stack.addFirst(cons.left);
+                    cs = cons.right;
+                }
             } else {
                 final String str = (String) cs;
                 pos -= str.length();
@@ -109,7 +131,7 @@
 
         left = new String(chars);
         right = "";
-        flat = true;
+        state = STATE_FLATTENED;
     }
 
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk/nashorn/internal/runtime/Context.java
index 9f2c521..15d4ba4 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java
@@ -26,10 +26,9 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.CONSTANTS;
-import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT;
+import static jdk.nashorn.internal.codegen.CompilerConstants.CREATE_PROGRAM_FUNCTION;
 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
 import static jdk.nashorn.internal.codegen.CompilerConstants.STRICT_MODE;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
@@ -39,11 +38,11 @@
 import java.io.PrintWriter;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.util.concurrent.atomic.AtomicLong;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.security.AccessControlContext;
@@ -55,20 +54,33 @@
 import java.security.PrivilegedActionException;
 import java.security.PrivilegedExceptionAction;
 import java.security.ProtectionDomain;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
-
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Consumer;
+import java.util.function.Supplier;
+import java.util.logging.Level;
+import javax.script.ScriptEngine;
 import jdk.internal.org.objectweb.asm.ClassReader;
 import jdk.internal.org.objectweb.asm.util.CheckClassAdapter;
+import jdk.nashorn.api.scripting.ClassFilter;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Parser;
+import jdk.nashorn.internal.runtime.events.RuntimeEvent;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
 import jdk.nashorn.internal.runtime.options.Options;
 
 /**
@@ -111,6 +123,9 @@
     private static final String LOAD_FX = "fx:";
     private static final String LOAD_NASHORN = "nashorn:";
 
+    private static MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+    private static MethodType CREATE_PROGRAM_FUNCTION_TYPE = MethodType.methodType(ScriptFunction.class, ScriptObject.class);
+
     /* Force DebuggerSupport to be loaded. */
     static {
         DebuggerSupport.FORCELOAD = true;
@@ -141,32 +156,33 @@
         }
 
         @Override
-        public Class<?> install(final String className, final byte[] bytecode, final Source source, final Object[] constants) {
-            Compiler.LOG.fine("Installing class ", className);
-
+        public Class<?> install(final String className, final byte[] bytecode) {
             final String   binaryName = Compiler.binaryName(className);
-            final Class<?> clazz      = loader.installClass(binaryName, bytecode, codeSource);
+            return loader.installClass(binaryName, bytecode, codeSource);
+        }
 
+        @Override
+        public void initialize(final Collection<Class<?>> classes, final Source source, final Object[] constants) {
             try {
-                // Need doPrivileged because these fields are private
                 AccessController.doPrivileged(new PrivilegedExceptionAction<Void>() {
                     @Override
                     public Void run() throws Exception {
-                        //use reflection to write source and constants table to installed classes
-                        final Field sourceField    = clazz.getDeclaredField(SOURCE.symbolName());
-                        final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
-                        sourceField.setAccessible(true);
-                        constantsField.setAccessible(true);
-                        sourceField.set(null, source);
-                        constantsField.set(null, constants);
+                        for (final Class<?> clazz : classes) {
+                            //use reflection to write source and constants table to installed classes
+                            final Field sourceField = clazz.getDeclaredField(SOURCE.symbolName());
+                            sourceField.setAccessible(true);
+                            sourceField.set(null, source);
+
+                            final Field constantsField = clazz.getDeclaredField(CONSTANTS.symbolName());
+                            constantsField.setAccessible(true);
+                            constantsField.set(null, constants);
+                        }
                         return null;
                     }
                 });
             } catch (final PrivilegedActionException e) {
                 throw new RuntimeException(e);
             }
-
-            return clazz;
         }
 
         @Override
@@ -185,16 +201,21 @@
         }
 
         @Override
-        public void storeCompiledScript(final Source source, final String mainClassName,
-                                        final Map<String, byte[]> classBytes, final Object[] constants) {
+        public void storeScript(final String classInfoFile, final Source source, final String mainClassName,
+                                final Map<String,byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers,
+                                final Object[] constants, final int compilationId) {
             if (context.codeStore != null) {
-                try {
-                    context.codeStore.putScript(source, mainClassName, classBytes, constants);
-                } catch (final IOException e) {
-                    throw new RuntimeException(e);
-                }
+                context.codeStore.storeScript(classInfoFile, source, mainClassName, classBytes, initializers, constants, compilationId);
             }
         }
+
+        @Override
+        public StoredScript loadScript(final Source source, final String functionKey) {
+            if (context.codeStore != null) {
+                return context.codeStore.loadScript(source, functionKey);
+            }
+            return null;
+        }
     }
 
     /** Is Context global debug mode enabled ? */
@@ -236,6 +257,11 @@
     public static void setGlobal(final Global global) {
         // This class in a package.access protected package.
         // Trusted code only can call this method.
+        assert getGlobal() != global;
+        //same code can be cached between globals, then we need to invalidate method handle constants
+        if (global != null) {
+            Global.getConstants().invalidateAll();
+        }
         currentGlobal.set(global);
     }
 
@@ -276,7 +302,6 @@
      * @param str  text to write
      * @param crlf write a carriage return/new line after text
      */
-    @SuppressWarnings("resource")
     public static void err(final String str, final boolean crlf) {
         final PrintWriter err = Context.getCurrentErr();
         if (err != null) {
@@ -312,6 +337,9 @@
     /** Unique id for 'eval' */
     private final AtomicLong uniqueEvalId;
 
+    /** Optional class filter to use for Java classes. Can be null. */
+    private final ClassFilter classFilter;
+
     private static final ClassLoader myLoader = Context.class.getClassLoader();
     private static final StructureLoader sharedLoader;
 
@@ -366,7 +394,19 @@
      * @param appLoader application class loader
      */
     public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader) {
-        this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader);
+        this(options, errors, appLoader, (ClassFilter)null);
+    }
+
+    /**
+     * Constructor
+     *
+     * @param options options from command line or Context creator
+     * @param errors  error manger
+     * @param appLoader application class loader
+     * @param classFilter class filter to use
+     */
+    public Context(final Options options, final ErrorManager errors, final ClassLoader appLoader, final ClassFilter classFilter) {
+        this(options, errors, new PrintWriter(System.out, true), new PrintWriter(System.err, true), appLoader, classFilter);
     }
 
     /**
@@ -379,11 +419,26 @@
      * @param appLoader application class loader
      */
     public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader) {
+        this(options, errors, out, err, appLoader, (ClassFilter)null);
+    }
+
+    /**
+     * Constructor
+     *
+     * @param options options from command line or Context creator
+     * @param errors  error manger
+     * @param out     output writer for this Context
+     * @param err     error writer for this Context
+     * @param appLoader application class loader
+     * @param classFilter class filter to use
+     */
+    public Context(final Options options, final ErrorManager errors, final PrintWriter out, final PrintWriter err, final ClassLoader appLoader, final ClassFilter classFilter) {
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             sm.checkPermission(new RuntimePermission(NASHORN_CREATE_CONTEXT));
         }
 
+        this.classFilter = classFilter;
         this.env       = new ScriptEnvironment(options, out, err);
         this._strict   = env._strict;
         this.appLoader = appLoader;
@@ -400,7 +455,7 @@
         // if user passed -classpath option, make a class loader with that and set it as
         // thread context class loader so that script can access classes from that path.
         final String classPath = options.getString("classpath");
-        if (! env._compile_only && classPath != null && !classPath.isEmpty()) {
+        if (!env._compile_only && classPath != null && !classPath.isEmpty()) {
             // make sure that caller can create a class loader.
             if (sm != null) {
                 sm.checkPermission(new RuntimePermission("createClassLoader"));
@@ -416,15 +471,11 @@
         }
 
         if (env._persistent_cache) {
-            if (env._lazy_compilation || env._specialize_calls != null) {
-                getErr().println("Can not use persistent class caching with lazy compilation or call specialization.");
-            } else {
-                try {
-                    final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache");
-                    codeStore = new CodeStore(cacheDir);
-                } catch (IOException e) {
-                    throw new RuntimeException("Error initializing code cache", e);
-                }
+            try {
+                final String cacheDir = Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache");
+                codeStore = new CodeStore(this, cacheDir);
+            } catch (final IOException e) {
+                throw new RuntimeException("Error initializing code cache", e);
             }
         }
 
@@ -436,6 +487,17 @@
         if (env._fullversion) {
             getErr().println("nashorn full version " + Version.fullVersion());
         }
+
+        initLoggers();
+    }
+
+
+    /**
+     * Get the class filter for this context
+     * @return class filter
+     */
+    public ClassFilter getClassFilter() {
+        return classFilter;
     }
 
     /**
@@ -512,13 +574,12 @@
      */
     public MultiGlobalCompiledScript compileScript(final Source source) {
         final Class<?> clazz = compile(source, this.errors, this._strict);
-        final MethodHandle runMethodHandle = getRunScriptHandle(clazz);
-        final boolean strict = isStrict(clazz);
+        final MethodHandle createProgramFunctionHandle = getCreateProgramFunctionHandle(clazz);
 
         return new MultiGlobalCompiledScript() {
             @Override
             public ScriptFunction getFunction(final Global newGlobal) {
-                return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, newGlobal, strict);
+                return invokeCreateProgramFunctionHandle(createProgramFunctionHandle, newGlobal);
             }
         };
     }
@@ -531,15 +592,31 @@
      * @param callThis     "this" to be passed to the evaluated code
      * @param location     location of the eval call
      * @param strict       is this {@code eval} call from a strict mode code?
+     * @return the return value of the {@code eval}
+     */
+    public Object eval(final ScriptObject initialScope, final String string,
+            final Object callThis, final Object location, final boolean strict) {
+        return eval(initialScope, string, callThis, location, strict, false);
+    }
+
+    /**
+     * Entry point for {@code eval}
+     *
+     * @param initialScope The scope of this eval call
+     * @param string       Evaluated code as a String
+     * @param callThis     "this" to be passed to the evaluated code
+     * @param location     location of the eval call
+     * @param strict       is this {@code eval} call from a strict mode code?
+     * @param evalCall     is this called from "eval" builtin?
      *
      * @return the return value of the {@code eval}
      */
-    public Object eval(final ScriptObject initialScope, final String string, final Object callThis, final Object location, final boolean strict) {
-        final String  file       = (location == UNDEFINED || location == null) ? "<eval>" : location.toString();
-        final Source  source     = sourceFor(file, string);
+    public Object eval(final ScriptObject initialScope, final String string,
+            final Object callThis, final Object location, final boolean strict, final boolean evalCall) {
+        final String  file       = location == UNDEFINED || location == null ? "<eval>" : location.toString();
+        final Source  source     = sourceFor(file, string, evalCall);
         final boolean directEval = location != UNDEFINED; // is this direct 'eval' call or indirectly invoked eval?
         final Global  global = Context.getGlobal();
-
         ScriptObject scope = initialScope;
 
         // ECMA section 10.1.1 point 2 says eval code is strict if it begins
@@ -581,10 +658,10 @@
             scope = strictEvalScope;
         }
 
-        ScriptFunction func = getRunScriptFunction(clazz, scope);
+        final ScriptFunction func = getProgramFunction(clazz, scope);
         Object evalThis;
         if (directEval) {
-            evalThis = (callThis instanceof ScriptObject || strictFlag) ? callThis : global;
+            evalThis = callThis instanceof ScriptObject || strictFlag ? callThis : global;
         } else {
             evalThis = global;
         }
@@ -603,7 +680,7 @@
                         public Source run() {
                             try {
                                 final URL resURL = Context.class.getResource(resource);
-                                return (resURL != null)? sourceFor(srcStr, resURL) : null;
+                                return resURL != null ? sourceFor(srcStr, resURL) : null;
                             } catch (final IOException exp) {
                                 return null;
                             }
@@ -626,7 +703,7 @@
      * @throws IOException if source cannot be found or loaded
      */
     public Object load(final ScriptObject scope, final Object from) throws IOException {
-        final Object src = (from instanceof ConsString)?  from.toString() : from;
+        final Object src = from instanceof ConsString ? from.toString() : from;
         Source source = null;
 
         // load accepts a String (which could be a URL or a file name), a File, a URL
@@ -634,8 +711,8 @@
         if (src instanceof String) {
             final String srcStr = (String)src;
             if (srcStr.startsWith(LOAD_CLASSPATH)) {
-                URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
-                source = (url != null)? sourceFor(url.toString(), url) : null;
+                final URL url = getResourceURL(srcStr.substring(LOAD_CLASSPATH.length()));
+                source = url != null ? sourceFor(url.toString(), url) : null;
             } else {
                 final File file = new File(srcStr);
                 if (srcStr.indexOf(':') != -1) {
@@ -739,11 +816,12 @@
      *
      * @throws ClassNotFoundException if structure class cannot be resolved
      */
-    public static Class<?> forStructureClass(final String fullName) throws ClassNotFoundException {
+    @SuppressWarnings("unchecked")
+    public static Class<? extends ScriptObject> forStructureClass(final String fullName) throws ClassNotFoundException {
         if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) {
             throw new ClassNotFoundException(fullName);
         }
-        return Class.forName(fullName, true, sharedLoader);
+        return (Class<? extends ScriptObject>)Class.forName(fullName, true, sharedLoader);
     }
 
     /**
@@ -839,6 +917,11 @@
             throw new ClassNotFoundException(fullName);
         }
 
+        // give chance to ClassFilter to filter out, if present
+        if (classFilter != null && !classFilter.exposeToScripts(fullName)) {
+            throw new ClassNotFoundException(fullName);
+        }
+
         // check package access as soon as possible!
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
@@ -912,16 +995,17 @@
      * Initialize given global scope object.
      *
      * @param global the global
+     * @param engine the associated ScriptEngine instance, can be null
      * @return the initialized global scope object.
      */
-    public Global initGlobal(final Global global) {
+    public Global initGlobal(final Global global, final ScriptEngine engine) {
         // Need only minimal global object, if we are just compiling.
         if (!env._compile_only) {
             final Global oldGlobal = Context.getGlobal();
             try {
                 Context.setGlobal(global);
                 // initialize global scope with builtin global objects
-                global.initBuiltinObjects();
+                global.initBuiltinObjects(engine);
             } finally {
                 Context.setGlobal(oldGlobal);
             }
@@ -931,8 +1015,14 @@
     }
 
     /**
-     * Trusted variant - package-private
+     * Initialize given global scope object.
+     *
+     * @param global the global
+     * @return the initialized global scope object.
      */
+    public Global initGlobal(final Global global) {
+        return initGlobal(global, null);
+    }
 
     /**
      * Return the current global's context
@@ -942,6 +1032,11 @@
         return ((ScriptObject)Context.getGlobal()).getContext();
     }
 
+    static Context getContextTrustedOrNull() {
+        final Global global = Context.getGlobal();
+        return global == null ? null : ((ScriptObject)global).getContext();
+    }
+
     /**
      * Try to infer Context instance from the Class. If we cannot,
      * then get it from the thread local variable.
@@ -983,40 +1078,33 @@
         return ScriptRuntime.apply(script, thiz);
     }
 
-    private static MethodHandle getRunScriptHandle(final Class<?> script) {
-        return MH.findStatic(
-                    MethodHandles.lookup(),
-                    script,
-                    RUN_SCRIPT.symbolName(),
-                    MH.type(
-                        Object.class,
-                        ScriptFunction.class,
-                        Object.class));
-    }
-
-    private static boolean isStrict(final Class<?> script) {
-        try {
-            return script.getField(STRICT_MODE.symbolName()).getBoolean(null);
-        } catch (final NoSuchFieldException | SecurityException | IllegalArgumentException | IllegalAccessException e) {
-            return false;
-        }
-    }
-
-    private static ScriptFunction getRunScriptFunction(final Class<?> script, final ScriptObject scope) {
+    private static ScriptFunction getProgramFunction(final Class<?> script, final ScriptObject scope) {
         if (script == null) {
             return null;
         }
+        return invokeCreateProgramFunctionHandle(getCreateProgramFunctionHandle(script), scope);
+    }
 
-        // Get run method - the entry point to the script
-        final MethodHandle runMethodHandle = getRunScriptHandle(script);
-        boolean strict = isStrict(script);
+    private static MethodHandle getCreateProgramFunctionHandle(final Class<?> script) {
+        try {
+            return LOOKUP.findStatic(script, CREATE_PROGRAM_FUNCTION.symbolName(), CREATE_PROGRAM_FUNCTION_TYPE);
+        } catch (NoSuchMethodException | IllegalAccessException e) {
+            throw new AssertionError("Failed to retrieve a handle for the program function for " + script.getName(), e);
+        }
+    }
 
-        // Package as a JavaScript function and pass function back to shell.
-        return Context.getGlobal().newScriptFunction(RUN_SCRIPT.symbolName(), runMethodHandle, scope, strict);
+    private static ScriptFunction invokeCreateProgramFunctionHandle(final MethodHandle createProgramFunctionHandle, final ScriptObject scope) {
+        try {
+            return (ScriptFunction)createProgramFunctionHandle.invokeExact(scope);
+        } catch (final RuntimeException|Error e) {
+            throw e;
+        } catch (final Throwable t) {
+            throw new AssertionError("Failed to create a program function", t);
+        }
     }
 
     private ScriptFunction compileScript(final Source source, final ScriptObject scope, final ErrorManager errMan) {
-        return getRunScriptFunction(compile(source, errMan, this._strict), scope);
+        return getProgramFunction(compile(source, errMan, this._strict), scope);
     }
 
     private synchronized Class<?> compile(final Source source, final ErrorManager errMan, final boolean strict) {
@@ -1025,35 +1113,35 @@
 
         Class<?> script = findCachedClass(source);
         if (script != null) {
-            Compiler.LOG.fine("Code cache hit for ", source, " avoiding recompile.");
+            final DebugLogger log = getLogger(Compiler.class);
+            if (log.isEnabled()) {
+                log.fine(new RuntimeEvent<>(Level.INFO, source), "Code cache hit for ", source, " avoiding recompile.");
+            }
             return script;
         }
 
-        CompiledScript compiledScript = null;
+        StoredScript storedScript = null;
         FunctionNode functionNode = null;
+        final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
+        final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;
 
-        if (!env._parse_only && codeStore != null) {
-            try {
-                compiledScript = codeStore.getScript(source);
-            } catch (IOException | ClassNotFoundException e) {
-                Compiler.LOG.warning("Error loading ", source, " from cache: ", e);
-                // Fall back to normal compilation
-            }
+        if (useCodeStore) {
+            storedScript = codeStore.loadScript(source, cacheKey);
         }
 
-        if (compiledScript == null) {
-            functionNode = new Parser(env, source, errMan, strict).parse();
+        if (storedScript == null) {
+            functionNode = new Parser(env, source, errMan, strict, getLogger(Parser.class)).parse();
 
             if (errors.hasErrors()) {
                 return null;
             }
 
-            if (env._print_ast) {
+            if (env._print_ast || functionNode.getFlag(FunctionNode.IS_PRINT_AST)) {
                 getErr().println(new ASTWriter(functionNode));
             }
 
-            if (env._print_parse) {
-                getErr().println(new PrintVisitor(functionNode));
+            if (env._print_parse || functionNode.getFlag(FunctionNode.IS_PRINT_PARSE)) {
+                getErr().println(new PrintVisitor(functionNode, true, false));
             }
         }
 
@@ -1066,12 +1154,22 @@
         final CodeSource   cs     = new CodeSource(url, (CodeSigner[])null);
         final CodeInstaller<ScriptEnvironment> installer = new ContextCodeInstaller(this, loader, cs);
 
-        if (functionNode != null) {
-            final Compiler compiler = new Compiler(installer, strict);
-            final FunctionNode newFunctionNode = compiler.compile(functionNode);
-            script = compiler.install(newFunctionNode);
+        if (storedScript == null) {
+            final CompilationPhases phases = Compiler.CompilationPhases.COMPILE_ALL;
+
+            final Compiler compiler = new Compiler(
+                    this,
+                    env,
+                    installer,
+                    source,
+                    strict | functionNode.isStrict());
+
+            final FunctionNode compiledFunction = compiler.compile(functionNode, phases);
+            script = compiledFunction.getRootClass();
+            compiler.persistClassInfo(cacheKey, compiledFunction);
         } else {
-            script = install(compiledScript, installer);
+            Compiler.updateCompilationId(storedScript.getCompilationId());
+            script = install(storedScript, source, installer);
         }
 
         cacheClass(source, script);
@@ -1096,40 +1194,48 @@
         return uniqueScriptId.getAndIncrement();
     }
 
-
     /**
      * Install a previously compiled class from the code cache.
      *
-     * @param compiledScript cached script containing class bytes and constants
+     * @param storedScript cached script containing class bytes and constants
      * @return main script class
      */
-    private Class<?> install(final CompiledScript compiledScript, final CodeInstaller<ScriptEnvironment> installer) {
+    private static Class<?> install(final StoredScript storedScript, final Source source, final CodeInstaller<ScriptEnvironment> installer) {
 
         final Map<String, Class<?>> installedClasses = new HashMap<>();
-        final Source   source        = compiledScript.getSource();
-        final Object[] constants     = compiledScript.getConstants();
-        final String   rootClassName = compiledScript.getMainClassName();
-        final byte[]   rootByteCode  = compiledScript.getClassBytes().get(rootClassName);
-        final Class<?> rootClass     = installer.install(rootClassName, rootByteCode, source, constants);
+        final Object[] constants       = storedScript.getConstants();
+        final String   mainClassName   = storedScript.getMainClassName();
+        final byte[]   mainClassBytes  = storedScript.getClassBytes().get(mainClassName);
+        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
+        final Map<Integer, FunctionInitializer> initialzers = storedScript.getInitializers();
 
-        installedClasses.put(rootClassName, rootClass);
+        installedClasses.put(mainClassName, mainClass);
 
-        for (final Map.Entry<String, byte[]> entry : compiledScript.getClassBytes().entrySet()) {
+        for (final Map.Entry<String, byte[]> entry : storedScript.getClassBytes().entrySet()) {
             final String className = entry.getKey();
-            if (className.equals(rootClassName)) {
+            if (className.equals(mainClassName)) {
                 continue;
             }
             final byte[] code = entry.getValue();
 
-            installedClasses.put(className, installer.install(className, code, source, constants));
+            installedClasses.put(className, installer.install(className, code));
         }
-        for (Object constant : constants) {
+
+        installer.initialize(installedClasses.values(), source, constants);
+
+        for (final Object constant : constants) {
             if (constant instanceof RecompilableScriptFunctionData) {
-                ((RecompilableScriptFunctionData) constant).setCodeAndSource(installedClasses, source);
+                final RecompilableScriptFunctionData data = (RecompilableScriptFunctionData) constant;
+                data.initTransients(source, installer);
+                if (initialzers != null) {
+                    final FunctionInitializer initializer = initialzers.get(data.getFunctionNodeId());
+                    initializer.setCode(installedClasses.get(initializer.getClassName()));
+                    data.initializeCode(initializer);
+                }
             }
         }
 
-        return rootClass;
+        return mainClass;
     }
 
     /**
@@ -1140,7 +1246,7 @@
         private final int size;
         private final ReferenceQueue<Class<?>> queue;
 
-        ClassCache(int size) {
+        ClassCache(final int size) {
             super(size, 0.75f, true);
             this.size = size;
             this.queue = new ReferenceQueue<>();
@@ -1156,7 +1262,7 @@
         }
 
         @Override
-        public ClassReference get(Object key) {
+        public ClassReference get(final Object key) {
             for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) {
                 remove(ref.source);
             }
@@ -1176,7 +1282,7 @@
 
     // Class cache management
     private Class<?> findCachedClass(final Source source) {
-        ClassReference ref = classCache == null ? null : classCache.get(source);
+        final ClassReference ref = classCache == null ? null : classCache.get(source);
         return ref != null ? ref.get() : null;
     }
 
@@ -1186,5 +1292,91 @@
         }
     }
 
+    // logging
+    private final Map<String, DebugLogger> loggers = new HashMap<>();
+
+    private void initLoggers() {
+        ((Loggable)MethodHandleFactory.getFunctionality()).initLogger(this);
+    }
+
+    /**
+     * Get a logger, given a loggable class
+     * @param clazz a Loggable class
+     * @return debuglogger associated with that class
+     */
+    public DebugLogger getLogger(final Class<? extends Loggable> clazz) {
+        return getLogger(clazz, null);
+    }
+
+    /**
+     * Get a logger, given a loggable class
+     * @param clazz a Loggable class
+     * @param initHook an init hook - if this is the first time the logger is created in the context, run the init hook
+     * @return debuglogger associated with that class
+     */
+    public DebugLogger getLogger(final Class<? extends Loggable> clazz, final Consumer<DebugLogger> initHook) {
+        final String name = getLoggerName(clazz);
+        DebugLogger logger = loggers.get(name);
+        if (logger == null) {
+            if (!env.hasLogger(name)) {
+                return DebugLogger.DISABLED_LOGGER;
+            }
+            final LoggerInfo info = env._loggers.get(name);
+            logger = new DebugLogger(name, info.getLevel(), info.isQuiet());
+            if (initHook != null) {
+                initHook.accept(logger);
+            }
+            loggers.put(name, logger);
+        }
+        return logger;
+    }
+
+    /**
+     * Given a Loggable class, weave debug info info a method handle for that logger.
+     * Level.INFO is used
+     *
+     * @param clazz loggable
+     * @param mh    method handle
+     * @param text  debug printout to add
+     *
+     * @return instrumented method handle, or null if logger not enabled
+     */
+    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final MethodHandle mh, final Supplier<String> text) {
+        return addLoggingToHandle(clazz, Level.INFO, mh, Integer.MAX_VALUE, false, text);
+    }
+
+    /**
+     * Given a Loggable class, weave debug info info a method handle for that logger.
+     *
+     * @param clazz            loggable
+     * @param level            log level
+     * @param mh               method handle
+     * @param paramStart       first parameter to print
+     * @param printReturnValue should we print the return vaulue?
+     * @param text             debug printout to add
+     *
+     * @return instrumented method handle, or null if logger not enabled
+     */
+    public MethodHandle addLoggingToHandle(final Class<? extends Loggable> clazz, final Level level, final MethodHandle mh, final int paramStart, final boolean printReturnValue, final Supplier<String> text) {
+        final DebugLogger log = getLogger(clazz);
+        if (log.isEnabled()) {
+            return MethodHandleFactory.addDebugPrintout(log, level, mh, paramStart, printReturnValue, text.get());
+        }
+        return mh;
+    }
+
+    private static String getLoggerName(final Class<?> clazz) {
+        Class<?> current = clazz;
+        while (current != null) {
+            final Logger log = current.getAnnotation(Logger.class);
+            if (log != null) {
+                assert !"".equals(log.name());
+                return log.name();
+            }
+            current = current.getSuperclass();
+        }
+        assert false;
+        return null;
+    }
 
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Debug.java b/nashorn/src/jdk/nashorn/internal/runtime/Debug.java
index b712f1d..c152418 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Debug.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Debug.java
@@ -41,6 +41,29 @@
     }
 
     /**
+     * Return the topmost JavaScript frame in a stack trace
+     * @param e
+     * @return line describing the topmost JavaScript frame
+     */
+    public static String firstJSFrame(final Throwable e) {
+        for (final StackTraceElement ste : e.getStackTrace()) {
+            if(ECMAErrors.isScriptFrame(ste)) {
+                return ste.toString();
+            }
+        }
+        return "<native code>";
+    }
+
+    /**
+     * Return the topmost JavaScript frame from the current
+     * continuation
+     * @return line describing the topmost JavaScript frame
+     */
+    public static String firstJSFrame() {
+        return firstJSFrame(new Throwable());
+    }
+
+    /**
      * Return the system identity hashcode for an object as a human readable
      * string
      *
@@ -48,7 +71,18 @@
      * @return system identity hashcode as string
      */
     public static String id(final Object x) {
-        return "0x" + Integer.toHexString(System.identityHashCode(x));
+        return String.format("0x%08x", System.identityHashCode(x));
+    }
+
+    /**
+     * Same as {@link Debug#id} but returns the identity hashcode as
+     * an integer
+     *
+     * @param x object
+     * @return system identity hashcode
+     */
+    public static int intId(final Object x) {
+        return System.identityHashCode(x);
     }
 
     /**
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java b/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java
deleted file mode 100644
index e832c86..0000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/DebugLogger.java
+++ /dev/null
@@ -1,304 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import java.io.PrintWriter;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import jdk.nashorn.internal.runtime.options.Options;
-
-/**
- * Wrapper class for Logging system. This is how you are supposed to register a logger and use it
- */
-
-public final class DebugLogger {
-    private final Logger  logger;
-    private final boolean isEnabled;
-
-    private int indent;
-
-    private static final int INDENT_SPACE = 4;
-
-    /**
-     * Constructor
-     *
-     * @param loggerName name of logger - this is the unique key with which it can be identified
-     */
-    public DebugLogger(final String loggerName) {
-        this(loggerName, null);
-    }
-
-    /**
-     * Constructor
-     *
-     * A logger can be paired with a property, e.g. {@code --log:codegen:info} is equivalent to {@code -Dnashorn.codegen.log}
-     *
-     * @param loggerName name of logger - this is the unique key with which it can be identified
-     * @param property   system property activating the logger on {@code info} level
-     */
-    public DebugLogger(final String loggerName, final String property) {
-        if (property != null && Options.getBooleanProperty(property)) {
-            this.logger = Logging.getOrCreateLogger(loggerName, Level.INFO);
-        } else {
-            this.logger = Logging.getLogger(loggerName);
-        }
-        assert logger != null;
-        this.isEnabled = getLevel() != Level.OFF;
-    }
-
-    /**
-     * Do not currently support chaining this with parent logger. Logger level null
-     * means disabled
-     * @return level
-     */
-    private Level getLevel() {
-        return logger.getLevel() == null ? Level.OFF : logger.getLevel();
-    }
-
-    /**
-     * Get the output writer for the logger. Loggers always default to
-     * stderr for output as they are used mainly to output debug info
-     *
-     * Can be inherited so this should not be static.
-     *
-     * @return print writer for log output.
-     */
-    @SuppressWarnings("static-method")
-    public PrintWriter getOutputStream() {
-        return Context.getCurrentErr();
-    }
-
-    /**
-     * Check if the logger is enabled
-     * @return true if enabled
-     */
-    public boolean isEnabled() {
-        return isEnabled;
-    }
-
-    /**
-     * If you want to change the indent level of your logger, call indent with a new position.
-     * Positions start at 0 and are increased by one for a new "tab"
-     *
-     * @param pos indent position
-     */
-    public void indent(final int pos) {
-        if (isEnabled) {
-           indent += pos * INDENT_SPACE;
-        }
-    }
-
-    /**
-     * Add an indent position
-     */
-    public void indent() {
-        indent += INDENT_SPACE;
-    }
-
-    /**
-     * Unindent a position
-     */
-    public void unindent() {
-        indent -= INDENT_SPACE;
-        if (indent < 0) {
-            indent = 0;
-        }
-    }
-
-    /**
-     * Check if the logger is above of the level of detail given
-     * @see java.util.logging.Level
-     *
-     * @param level logging level
-     * @return true if level is above the given one
-     */
-    public boolean levelAbove(final Level level) {
-        return getLevel().intValue() > level.intValue();
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger
-     * @param str the string to log
-     */
-    public void finest(final String str) {
-        log(Level.FINEST, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINEST} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void finest(final Object... objs) {
-        log(Level.FINEST, objs);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINER} on this logger
-     * @param str the string to log
-     */
-    public void finer(final String str) {
-        log(Level.FINER, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINER} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void finer(final Object... objs) {
-        log(Level.FINER, objs);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINE} on this logger
-     * @param str the string to log
-     */
-    public void fine(final String str) {
-        log(Level.FINE, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINE} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void fine(final Object... objs) {
-        log(Level.FINE, objs);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#CONFIG} on this logger
-     * @param str the string to log
-     */
-    public void config(final String str) {
-        log(Level.CONFIG, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#CONFIG} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void config(final Object... objs) {
-        log(Level.CONFIG, objs);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#INFO} on this logger
-     * @param str the string to log
-     */
-    public void info(final String str) {
-        log(Level.INFO, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINE} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void info(final Object... objs) {
-        log(Level.INFO, objs);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#WARNING} on this logger
-     * @param str the string to log
-     */
-    public void warning(final String str) {
-        log(Level.WARNING, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINE} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void warning(final Object... objs) {
-        log(Level.WARNING, objs);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#SEVERE} on this logger
-     * @param str the string to log
-     */
-    public void severe(final String str) {
-        log(Level.SEVERE, str);
-    }
-
-    /**
-     * Shorthand for outputting a log string as log level
-     * {@link java.util.logging.Level#FINE} on this logger
-     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
-     */
-    public void severe(final Object... objs) {
-        log(Level.SEVERE, objs);
-    }
-
-    /**
-     * Output log line on this logger at a given level of verbosity
-     * @see java.util.logging.Level
-     *
-     * @param level minimum log level required for logging to take place
-     * @param str   string to log
-     */
-    public void log(final Level level, final String str) {
-        if (isEnabled) {
-            final StringBuilder sb = new StringBuilder();
-            for (int i = 0 ; i < indent ; i++) {
-                sb.append(' ');
-            }
-            sb.append(str);
-            logger.log(level, sb.toString());
-        }
-    }
-
-    /**
-     * Output log line on this logger at a given level of verbosity
-     * @see java.util.logging.Level
-     *
-     * @param level minimum log level required for logging to take place
-     * @param objs  objects for which to invoke toString and concatenate to log
-     */
-    public void log(final Level level, final Object... objs) {
-        if (isEnabled) {
-            final StringBuilder sb = new StringBuilder();
-            for (int i = 0 ; i < indent ; i++) {
-                sb.append(' ');
-            }
-            for (final Object obj : objs) {
-                sb.append(obj);
-            }
-            logger.log(level, sb.toString());
-        }
-    }
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java b/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
index 38e5d85..d5dc560 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DebuggerSupport.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.SOURCE;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.reflect.Field;
@@ -53,6 +54,7 @@
          * available to external debuggers.
          */
         @SuppressWarnings("unused")
+        final
         DebuggerValueDesc forceLoad = new DebuggerValueDesc(null, false, null, null);
 
         // Hook to force the loading of the SourceInfo class
@@ -155,7 +157,7 @@
 
         try {
             return context.eval(initialScope, string, callThis, ScriptRuntime.UNDEFINED, false);
-        } catch (Throwable ex) {
+        } catch (final Throwable ex) {
             return returnException ? ex : null;
         }
     }
@@ -237,12 +239,12 @@
 
         if (ScriptObject.isArray(object)) {
             sb.append('[');
-            final long length = object.getLong("length");
+            final long length = object.getLong("length", INVALID_PROGRAM_POINT);
 
             for (long i = 0; i < length; i++) {
                 if (object.has(i)) {
                     final Object valueAsObject = object.get(i);
-                    final boolean isUndefined = JSType.of(valueAsObject) == JSType.UNDEFINED;
+                    final boolean isUndefined = valueAsObject == ScriptRuntime.UNDEFINED;
 
                     if (isUndefined) {
                         if (i != 0) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java b/nashorn/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
index dcceccb..c1ae1f5 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/DefaultPropertyAccess.java
@@ -34,63 +34,63 @@
 public abstract class DefaultPropertyAccess implements PropertyAccess {
 
     @Override
-    public int getInt(final Object key) {
+    public int getInt(final Object key, final int programPoint) {
         return JSType.toInt32(get(key));
     }
 
     @Override
-    public int getInt(final double key) {
-        return getInt(JSType.toObject(key));
+    public int getInt(final double key, final int programPoint) {
+        return getInt(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public int getInt(final long key) {
-        return getInt(JSType.toObject(key));
+    public int getInt(final long key, final int programPoint) {
+        return getInt(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public int getInt(final int key) {
-        return getInt(JSType.toObject(key));
+    public int getInt(final int key, final int programPoint) {
+        return getInt(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public long getLong(final Object key) {
+    public long getLong(final Object key, final int programPoint) {
         return JSType.toLong(get(key));
     }
 
     @Override
-    public long getLong(final double key) {
-        return getLong(JSType.toObject(key));
+    public long getLong(final double key, final int programPoint) {
+        return getLong(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public long getLong(final long key) {
-        return getLong(JSType.toObject(key));
+    public long getLong(final long key, final int programPoint) {
+        return getLong(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public long getLong(final int key) {
-        return getLong(JSType.toObject(key));
+    public long getLong(final int key, final int programPoint) {
+        return getLong(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public double getDouble(final Object key) {
+    public double getDouble(final Object key, final int programPoint) {
         return JSType.toNumber(get(key));
     }
 
     @Override
-    public double getDouble(final double key) {
-        return getDouble(JSType.toObject(key));
+    public double getDouble(final double key, final int programPoint) {
+        return getDouble(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public double getDouble(final long key) {
-        return getDouble(JSType.toObject(key));
+    public double getDouble(final long key, final int programPoint) {
+        return getDouble(JSType.toObject(key), programPoint);
     }
 
     @Override
-    public double getDouble(final int key) {
-        return getDouble(JSType.toObject(key));
+    public double getDouble(final int key, final int programPoint) {
+        return getDouble(JSType.toObject(key), programPoint);
     }
 
     @Override
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
index affba49..9dbd642 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java
@@ -28,10 +28,9 @@
 import java.text.MessageFormat;
 import java.util.Locale;
 import java.util.ResourceBundle;
-import jdk.nashorn.api.scripting.NashornException;
-import jdk.nashorn.internal.scripts.JS;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.scripts.JS;
 
 /**
  * Helper class to throw various standard "ECMA error" exceptions such as Error, ReferenceError, TypeError etc.
@@ -47,7 +46,7 @@
     /** We assume that compiler generates script classes into the known package. */
     private static final String scriptPackage;
     static {
-        String name = JS.class.getName();
+        final String name = JS.class.getName();
         scriptPackage = name.substring(0, name.lastIndexOf('.'));
     }
 
@@ -403,14 +402,10 @@
         final String className = frame.getClassName();
 
         // Look for script package in class name (into which compiler puts generated code)
-        if (className.startsWith(scriptPackage) && !frame.getMethodName().startsWith(CompilerConstants.INTERNAL_METHOD_PREFIX)) {
+        if (className.startsWith(scriptPackage) && !CompilerConstants.isInternalMethodName(frame.getMethodName())) {
             final String source = frame.getFileName();
-            /*
-             * Make sure that it is not some Java code that Nashorn has in that package!
-             * also, we don't want to report JavaScript code that lives in script engine implementation
-             * We want to report only user's own scripts and not any of our own scripts like "engine.js"
-             */
-            return source != null && !source.endsWith(".java") && !source.contains(NashornException.ENGINE_SCRIPT_SOURCE_NAME);
+            // Make sure that it is not some Java code that Nashorn has in that package!
+            return source != null && !source.endsWith(".java");
         }
         return false;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
index c900963..ce691af 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAException.java
@@ -96,8 +96,8 @@
         // If thrown object is an Error or sub-object like TypeError, then
         // an ECMAException object has been already initialized at constructor.
         if (thrown instanceof ScriptObject) {
-            ScriptObject sobj = (ScriptObject)thrown;
-            Object exception = getException(sobj);
+            final ScriptObject sobj = (ScriptObject)thrown;
+            final Object exception = getException(sobj);
             if (exception instanceof ECMAException) {
                 // copy over file name, line number and column number.
                 final ECMAException ee = (ECMAException)exception;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
index f16cf41..f75dc82 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FinalScriptFunctionData.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.lookup.Lookup.MH;
-
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodType;
+import java.util.List;
 
 /**
  * This is a subclass that represents a script function that may not be regenerated.
@@ -35,6 +35,8 @@
  */
 final class FinalScriptFunctionData extends ScriptFunctionData {
 
+    private static final long serialVersionUID = -930632846167768864L;
+
     /**
      * Constructor - used for bind
      *
@@ -43,9 +45,10 @@
      * @param functions precompiled code
      * @param flags     {@link ScriptFunctionData} flags
      */
-    FinalScriptFunctionData(final String name, final int arity, final CompiledFunctions functions, final int flags) {
+    FinalScriptFunctionData(final String name, final int arity, final List<CompiledFunction> functions, final int flags) {
         super(name, arity, flags);
         code.addAll(functions);
+        assert !needsCallee();
     }
 
     /**
@@ -58,7 +61,7 @@
      * @param flags {@link ScriptFunctionData} flags
      */
     FinalScriptFunctionData(final String name, final MethodHandle mh, final MethodHandle[] specs, final int flags) {
-        super(name, arity(mh), flags);
+        super(name, methodHandleArity(mh), flags);
 
         addInvoker(mh);
         if (specs != null) {
@@ -68,22 +71,64 @@
         }
     }
 
+    @Override
+    boolean isRecompilable() {
+        return false;
+    }
+
+    @Override
+    protected boolean needsCallee() {
+        final boolean needsCallee = code.getFirst().needsCallee();
+        assert allNeedCallee(needsCallee);
+        return needsCallee;
+    }
+
+    private boolean allNeedCallee(final boolean needCallee) {
+        for (final CompiledFunction inv : code) {
+            if(inv.needsCallee() != needCallee) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    MethodType getGenericType() {
+        // We need to ask the code for its generic type. We can't just rely on this function data's arity, as it's not
+        // actually correct for lots of built-ins. E.g. ECMAScript 5.1 section 15.5.3.2 prescribes that
+        // Script.fromCharCode([char0[, char1[, ...]]]) has a declared arity of 1 even though it's a variable arity
+        // method.
+        int max = 0;
+        for(final CompiledFunction fn: code) {
+            final MethodType t = fn.type();
+            if(ScriptFunctionData.isVarArg(t)) {
+                // 2 for (callee, this, args[])
+                return MethodType.genericMethodType(2, true);
+            }
+            final int paramCount = t.parameterCount() - (ScriptFunctionData.needsCallee(t) ? 1 : 0);
+            if(paramCount > max) {
+                max = paramCount;
+            }
+        }
+        // +1 for callee
+        return MethodType.genericMethodType(max + 1);
+    }
+
     private void addInvoker(final MethodHandle mh) {
+        assert !needsCallee(mh);
         if (isConstructor(mh)) {
             // only nasgen constructors: (boolean, self, args) are subject to binding a boolean newObj. isConstructor
             // is too conservative a check. However, isConstructor(mh) always implies isConstructor param
             assert isConstructor();
-            final MethodHandle invoker = MH.insertArguments(mh, 0, false);
-            final MethodHandle constructor = composeConstructor(MH.insertArguments(mh, 0, true));
-            code.add(new CompiledFunction(mh.type(), invoker, constructor));
+            code.add(CompiledFunction.createBuiltInConstructor(mh));
         } else {
-            code.add(new CompiledFunction(mh.type(), mh));
+            code.add(new CompiledFunction(mh));
         }
     }
 
-    private static int arity(final MethodHandle mh) {
+    private static int methodHandleArity(final MethodHandle mh) {
         if (isVarArg(mh)) {
-            return -1;
+            return MAX_ARITY;
         }
 
         //drop self, callee and boolean constructor flag to get real arity
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
index 87a8c74..61daf6d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FindProperty.java
@@ -26,6 +26,7 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 
 import java.lang.invoke.MethodHandle;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
@@ -63,15 +64,28 @@
      * @see ObjectClassGenerator
      *
      * @param type type of getter, e.g. int.class if we want a function with {@code get()I} signature
+     * @param programPoint program point, or INVALID_PROGRAM_POINT if pessimistic
      * @return method handle for the getter
      */
-    public MethodHandle getGetter(final Class<?> type) {
-        MethodHandle getter = property.getGetter(type);
+    public MethodHandle getGetter(final Class<?> type, final int programPoint) {
+        final MethodHandle getter;
+        if (isValid(programPoint)) {
+            getter = property.getOptimisticGetter(type, programPoint);
+        } else {
+            getter = property.getGetter(type);
+        }
+        return getGetterInner(getter);
+    }
+
+    private MethodHandle getGetterInner(final MethodHandle getter) {
         if (property instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc = (UserAccessorProperty)property;
-            getter = MH.insertArguments(getter, 0, isInherited() ? getOwner() : null, uc.getGetterSlot());
+            final UserAccessorProperty uc        = (UserAccessorProperty)property;
+            final ScriptObject         owner     = getOwner();
+            final ScriptObject         container = (owner != null) ? owner : self;
+            return MH.insertArguments(getter, 0, uc.getAccessors(container));
         }
         return getter;
+
     }
 
     /**
@@ -86,11 +100,12 @@
      * @return method handle for the getter
      */
     public MethodHandle getSetter(final Class<?> type, final boolean strict) {
-        MethodHandle setter = property.getSetter(type, getOwner().getMap());
+        final MethodHandle setter = property.getSetter(type, getOwner().getMap());
         if (property instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc = (UserAccessorProperty) property;
-            setter = MH.insertArguments(setter, 0, isInherited() ? getOwner() : null,
-                    uc.getSetterSlot(), strict? property.getKey() : null);
+            final UserAccessorProperty uc        = (UserAccessorProperty)property;
+            final ScriptObject         owner     = getOwner();
+            final ScriptObject         container = (owner != null) ? owner : self;
+            return MH.insertArguments(setter, 0, uc.getAccessors(container), strict ? property.getKey() : null);
         }
 
         return setter;
@@ -155,7 +170,27 @@
 
     /**
      * Get the property value from self as object.
-     *
+     * @return the property value
+     */
+    public int getIntValue() {
+        return property.getIntValue(getGetterReceiver(), getOwner());
+    }
+    /**
+     * Get the property value from self as object.
+     * @return the property value
+     */
+    public long getLongValue() {
+        return property.getLongValue(getGetterReceiver(), getOwner());
+    }
+    /**
+     * Get the property value from self as object.
+     * @return the property value
+     */
+    public double getDoubleValue() {
+        return property.getDoubleValue(getGetterReceiver(), getOwner());
+    }
+    /**
+     * Get the property value from self as object.
      * @return the property value
      */
     public Object getObjectValue() {
@@ -168,8 +203,38 @@
      * @param value the new value
      * @param strict strict flag
      */
-    public void setObjectValue(final Object value, final boolean strict) {
-        property.setObjectValue(getSetterReceiver(), getOwner(), value, strict);
+    public void setValue(final int value, final boolean strict) {
+        property.setValue(getSetterReceiver(), getOwner(), value, strict);
+    }
+
+    /**
+     * Set the property value in self.
+     *
+     * @param value the new value
+     * @param strict strict flag
+     */
+    public void setValue(final long value, final boolean strict) {
+        property.setValue(getSetterReceiver(), getOwner(), value, strict);
+    }
+
+    /**
+     * Set the property value in self.
+     *
+     * @param value the new value
+     * @param strict strict flag
+     */
+    public void setValue(final double value, final boolean strict) {
+        property.setValue(getSetterReceiver(), getOwner(), value, strict);
+    }
+
+    /**
+     * Set the property value in self.
+     *
+     * @param value the new value
+     * @param strict strict flag
+     */
+    public void setValue(final Object value, final boolean strict) {
+        property.setValue(getSetterReceiver(), getOwner(), value, strict);
     }
 
     /**
@@ -187,5 +252,10 @@
         return length;
     }
 
+    @Override
+    public String toString() {
+        return "[FindProperty: " + property.getKey() + ']';
+    }
+
 }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FunctionInitializer.java b/nashorn/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
new file mode 100644
index 0000000..e2912a2
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FunctionInitializer.java
@@ -0,0 +1,149 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.lang.invoke.MethodType;
+import java.util.Map;
+import jdk.nashorn.internal.codegen.CompileUnit;
+import jdk.nashorn.internal.codegen.FunctionSignature;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.ir.FunctionNode;
+
+/**
+ * Class that contains information allowing us to look up a method handle implementing a JavaScript function
+ * from a generated class. This is used both for code coming from codegen and for persistent serialized code.
+ */
+public final class FunctionInitializer implements Serializable {
+
+    private final String className;
+    private final MethodType methodType;
+    private final int flags;
+    private transient Map<Integer, Type> invalidatedProgramPoints;
+    private transient Class<?> code;
+
+    private static final long serialVersionUID = -5420835725902966692L;
+
+    /**
+     * Constructor.
+     *
+     * @param functionNode the function node
+     */
+    public FunctionInitializer(final FunctionNode functionNode) {
+        this(functionNode, null);
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param functionNode the function node
+     * @param invalidatedProgramPoints invalidated program points
+     */
+    public FunctionInitializer(final FunctionNode functionNode, final Map<Integer, Type> invalidatedProgramPoints) {
+        this.className  = functionNode.getCompileUnit().getUnitClassName();
+        this.methodType = new FunctionSignature(functionNode).getMethodType();
+        this.flags = functionNode.getFlags();
+        this.invalidatedProgramPoints = invalidatedProgramPoints;
+
+        final CompileUnit cu = functionNode.getCompileUnit();
+        if (cu != null) {
+            this.code = cu.getCode();
+        }
+
+        assert className != null;
+    }
+
+    /**
+     * Returns the name of the class implementing the function.
+     *
+     * @return the class name
+     */
+    public String getClassName() {
+        return className;
+    }
+
+    /**
+     * Returns the type of the method implementing the function.
+     *
+     * @return the method type
+     */
+    public MethodType getMethodType() {
+        return methodType;
+    }
+
+    /**
+     * Returns the function flags.
+     *
+     * @return function flags
+     */
+    public int getFlags() {
+        return flags;
+    }
+
+    /**
+     * Returns the class implementing the function.
+     *
+     * @return the class
+     */
+    public Class<?> getCode() {
+        return code;
+    }
+
+    /**
+     * Set the class implementing the function
+     * @param code the class
+     */
+    public void setCode(final Class<?> code) {
+        // Make sure code has not been set and has expected class name
+        if (this.code != null) {
+            throw new IllegalStateException("code already set");
+        }
+        assert className.equals(code.getTypeName().replace('.', '/')) : "unexpected class name";
+        this.code = code;
+    }
+
+    /**
+     * Returns the map of invalidated program points.
+     *
+     * @return invalidated program points
+     */
+    public Map<Integer, Type> getInvalidatedProgramPoints() {
+        return invalidatedProgramPoints;
+    }
+
+    private void writeObject(final ObjectOutputStream out) throws IOException {
+        out.defaultWriteObject();
+        Type.writeTypeMap(invalidatedProgramPoints, out);
+    }
+
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        invalidatedProgramPoints = Type.readTypeMap(in);
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/FunctionScope.java b/nashorn/src/jdk/nashorn/internal/runtime/FunctionScope.java
index b3872c4..133c64f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/FunctionScope.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/FunctionScope.java
@@ -72,6 +72,19 @@
     }
 
     /**
+     * Constructor
+     *
+     * @param map            property map
+     * @param primitiveSpill primitive spill pool
+     * @param objectSpill    reference spill pool
+     */
+    public FunctionScope(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+        super(map, primitiveSpill, objectSpill);
+        this.arguments = null;
+    }
+
+
+    /**
      * Get the current split state.
      * @return current split state
      */
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java b/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java
new file mode 100644
index 0000000..cc6a2de
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalConstants.java
@@ -0,0 +1,435 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.SwitchPoint;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.DynamicLinker;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * Each global owns one of these. This is basically table of accessors
+ * for global properties. A global constant is evaluated to a MethodHandle.constant
+ * for faster access and to avoid walking to proto chain looking for it.
+ *
+ * We put a switchpoint on the global setter, which invalidates the
+ * method handle constant getters, and reverts to the standard access strategy
+ *
+ * However, there is a twist - while certain globals like "undefined" and "Math"
+ * are usually never reassigned, a global value can be reset once, and never again.
+ * This is a rather common pattern, like:
+ *
+ * x = function(something) { ...
+ *
+ * Thus everything registered as a global constant gets an extra chance. Set once,
+ * reregister the switchpoint. Set twice or more - don't try again forever, or we'd
+ * just end up relinking our way into megamorphisism.
+ *
+ * We can extend this to ScriptObjects in general (GLOBAL_ONLY=false), which requires
+ * a receiver guard on the constant getter, but it currently leaks memory and its benefits
+ * have not yet been investigated property.
+ *
+ * As long as all Globals share the same constant instance, we need synchronization
+ * whenever we access the instance.
+ */
+@Logger(name="const")
+public final class GlobalConstants implements Loggable {
+
+    /**
+     * Should we only try to link globals as constants, and not generic script objects.
+     * Script objects require a receiver guard, which is memory intensive, so this is currently
+     * disabled. We might implement a weak reference based approach to this later.
+     */
+    private static final boolean GLOBAL_ONLY = true;
+
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    private static final MethodHandle INVALIDATE_SP  = virtualCall(LOOKUP, GlobalConstants.class, "invalidateSwitchPoint", Object.class, Object.class, Access.class).methodHandle();
+    private static final MethodHandle RECEIVER_GUARD = staticCall(LOOKUP, GlobalConstants.class, "receiverGuard", boolean.class, Access.class, Object.class, Object.class).methodHandle();
+
+    /** Logger for constant getters */
+    private final DebugLogger log;
+
+    /**
+     * Access map for this global - associates a symbol name with an Access object, with getter
+     * and invalidation information
+     */
+    private final Map<String, Access> map = new HashMap<>();
+
+    /**
+     * Constructor - used only by global
+     * @param log logger, or null if none
+     */
+    public GlobalConstants(final DebugLogger log) {
+        this.log = log == null ? DebugLogger.DISABLED_LOGGER : log;
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return DebugLogger.DISABLED_LOGGER;
+    }
+
+    /**
+     * Information about a constant access and its potential invalidations
+     */
+    private static class Access {
+        /** name of symbol */
+        private final String name;
+
+        /** switchpoint that invalidates the getters and setters for this access */
+        private SwitchPoint sp;
+
+        /** invalidation count for this access, i.e. how many times has this property been reset */
+        private int invalidations;
+
+        /** has a guard guarding this property getter failed? */
+        private boolean guardFailed;
+
+        private static final int MAX_RETRIES = 2;
+
+        private Access(final String name, final SwitchPoint sp) {
+            this.name      = name;
+            this.sp        = sp;
+        }
+
+        private boolean hasBeenInvalidated() {
+            return sp.hasBeenInvalidated();
+        }
+
+        private boolean guardFailed() {
+            return guardFailed;
+        }
+
+        private void failGuard() {
+            invalidateOnce();
+            guardFailed = true;
+        }
+
+        private void newSwitchPoint() {
+            assert hasBeenInvalidated();
+            sp = new SwitchPoint();
+        }
+
+        private void invalidate(final int count) {
+            if (!sp.hasBeenInvalidated()) {
+                SwitchPoint.invalidateAll(new SwitchPoint[] { sp });
+                invalidations += count;
+            }
+        }
+
+        /**
+         * Invalidate the access, but do not contribute to the invalidation count
+         */
+        private void invalidateUncounted() {
+            invalidate(0);
+        }
+
+        /**
+         * Invalidate the access, and contribute 1 to the invalidation count
+         */
+        private void invalidateOnce() {
+            invalidate(1);
+        }
+
+        /**
+         * Invalidate the access and make sure that we never try to turn this into
+         * a MethodHandle.constant getter again
+         */
+        private void invalidateForever() {
+            invalidate(MAX_RETRIES);
+        }
+
+        /**
+         * Are we allowed to relink this as constant getter, even though it
+         * it has been reset
+         * @return true if we can relink as constant, one retry is allowed
+         */
+        private boolean mayRetry() {
+            return invalidations < MAX_RETRIES;
+        }
+
+        @Override
+        public String toString() {
+            return "[" + quote(name) + " <id=" + Debug.id(this) + "> inv#=" + invalidations + '/' + MAX_RETRIES + " sp_inv=" + sp.hasBeenInvalidated() + ']';
+        }
+
+        String getName() {
+            return name;
+        }
+
+        SwitchPoint getSwitchPoint() {
+            return sp;
+        }
+    }
+
+    /**
+     * To avoid an expensive global guard "is this the same global", similar to the
+     * receiver guard on the ScriptObject level, we invalidate all getters once
+     * when we switch globals. This is used from the class cache. We _can_ reuse
+     * the same class for a new global, but the builtins and global scoped variables
+     * will have changed.
+     */
+    public synchronized void invalidateAll() {
+        log.info("New global created - invalidating all constant callsites without increasing invocation count.");
+        for (final Access acc : map.values()) {
+            acc.invalidateUncounted();
+        }
+    }
+
+    /**
+     * Invalidate the switchpoint of an access - we have written to
+     * the property
+     *
+     * @param obj receiver
+     * @param acc access
+     *
+     * @return receiver, so this can be used as param filter
+     */
+    @SuppressWarnings("unused")
+    private synchronized Object invalidateSwitchPoint(final Object obj, final Access acc) {
+        if (log.isEnabled()) {
+            log.info("*** Invalidating switchpoint " + acc.getSwitchPoint() + " for receiver=" + obj + " access=" + acc);
+        }
+        acc.invalidateOnce();
+        if (acc.mayRetry()) {
+            if (log.isEnabled()) {
+                log.info("Retry is allowed for " + acc + "... Creating a new switchpoint.");
+            }
+            acc.newSwitchPoint();
+        } else {
+            if (log.isEnabled()) {
+                log.info("This was the last time I allowed " + quote(acc.getName()) + " to relink as constant.");
+            }
+        }
+        return obj;
+    }
+
+    private synchronized Access getOrCreateSwitchPoint(final String name) {
+        Access acc = map.get(name);
+        if (acc != null) {
+            return acc;
+        }
+        final SwitchPoint sp = new SwitchPoint();
+        map.put(name, acc = new Access(name, sp));
+        return acc;
+    }
+
+    /**
+     * Called from script object on property deletion to erase a property
+     * that might be linked as MethodHandle.constant and force relink
+     * @param name name of property
+     */
+    void delete(final String name) {
+        final Access acc = map.get(name);
+        if (acc != null) {
+            acc.invalidateForever();
+        }
+    }
+
+    /**
+     * Receiver guard is used if we extend the global constants to script objects in general.
+     * As the property can have different values in different script objects, while Global is
+     * by definition a singleton, we need this for ScriptObject constants (currently disabled)
+     *
+     * TODO: Note - this seems to cause memory leaks. Use weak references? But what is leaking seems
+     * to be the Access objects, which isn't the case for Globals. Weird.
+     *
+     * @param acc            access
+     * @param boundReceiver  the receiver bound to the callsite
+     * @param receiver       the receiver to check against
+     *
+     * @return true if this receiver is still the one we bound to the callsite
+     */
+    @SuppressWarnings("unused")
+    private static boolean receiverGuard(final Access acc, final Object boundReceiver, final Object receiver) {
+        final boolean id = receiver == boundReceiver;
+        if (!id) {
+            acc.failGuard();
+        }
+        return id;
+    }
+
+    private static boolean isGlobalSetter(final ScriptObject receiver, final FindProperty find) {
+        if (find == null) {
+            return receiver.isScope();
+        }
+        return find.getOwner().isGlobal();
+    }
+
+    /**
+     * Augment a setter with switchpoint for invalidating its getters, should the setter be called
+     *
+     * @param find    property lookup
+     * @param inv     normal guarded invocation for this setter, as computed by the ScriptObject linker
+     * @param desc    callsite descriptr
+     * @param request link request
+     *
+     * @return null if failed to set up constant linkage
+     */
+    synchronized GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) {
+        if (GLOBAL_ONLY && !isGlobalSetter(receiver, find)) {
+            return null;
+        }
+
+        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+
+        final Access acc  = getOrCreateSwitchPoint(name);
+
+        if (log.isEnabled()) {
+            log.fine("Trying to link constant SETTER ", acc);
+        }
+
+        if (!acc.mayRetry()) {
+            log.info("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
+            return null;
+        }
+
+        assert acc.mayRetry();
+
+        if (acc.hasBeenInvalidated()) {
+            log.info("New chance for " + acc);
+            acc.newSwitchPoint();
+        }
+
+        assert !acc.hasBeenInvalidated();
+
+        // if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter
+        final MethodHandle target           = inv.getInvocation();
+        final Class<?>     receiverType     = target.type().parameterType(0);
+        final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP,  this);
+        final MethodHandle invalidator      = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType));
+        final MethodHandle mh               = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc));
+
+        assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints());
+        log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint());
+        return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException());
+    }
+
+    /**
+     * Try to reuse constant method handles for getters
+     * @param c constant value
+     * @return method handle (with dummy receiver) that returns this constant
+     */
+    private MethodHandle constantGetter(final Object c) {
+        final MethodHandle mh = MH.dropArguments(JSType.unboxConstant(c), 0, Object.class);
+        if (log.isEnabled()) {
+            return MethodHandleFactory.addDebugPrintout(log, Level.FINEST, mh, "getting as constant");
+        }
+        return mh;
+    }
+
+    /**
+     * Try to turn a getter into a MethodHandle.constant, if possible
+     *
+     * @param find      property lookup
+     * @param receiver  receiver
+     * @param desc      callsite descriptor
+     * @param request   link request
+     * @param operator  operator
+     *
+     * @return resulting getter, or null if failed to create constant
+     */
+    synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+        if (GLOBAL_ONLY && !find.getOwner().isGlobal()) {
+            return null;
+        }
+
+        final int programPoint         = NashornCallSiteDescriptor.isOptimistic(desc) ?
+            NashornCallSiteDescriptor.getProgramPoint(desc) :
+            UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+        final boolean     isOptimistic = programPoint != UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+        final Class<?>    retType      = desc.getMethodType().returnType();
+        final String      name         = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+
+        final Access acc = getOrCreateSwitchPoint(name);
+
+        log.fine("Starting to look up object value " + name);
+        final Object c = find.getObjectValue();
+
+        if (log.isEnabled()) {
+            log.fine("Trying to link constant GETTER " + acc + " value = " + c);
+        }
+
+        if (acc.hasBeenInvalidated() || acc.guardFailed()) {
+            log.fine("*** GET: Giving up on " + quote(name) + " - retry count has exceeded");
+            return null;
+        }
+
+        final MethodHandle cmh = constantGetter(c);
+
+        MethodHandle mh;
+        MethodHandle guard;
+
+        if (isOptimistic) {
+            if (JSType.getAccessorTypeIndex(cmh.type().returnType()) <= JSType.getAccessorTypeIndex(retType)) {
+                //widen return type - this is pessimistic, so it will always work
+                mh = MH.asType(cmh, cmh.type().changeReturnType(retType));
+            } else {
+                //immediately invalidate - we asked for a too wide constant as a narrower one
+                mh = MH.dropArguments(MH.insertArguments(JSType.THROW_UNWARRANTED.methodHandle(), 0, c, programPoint), 0, Object.class);
+            }
+        } else {
+            //pessimistic return type filter
+            mh = Lookup.filterReturnType(cmh, retType);
+        }
+
+        if (find.getOwner().isGlobal()) {
+            guard = null;
+        } else {
+            guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver);
+        }
+
+        if (log.isEnabled()) {
+            log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint());
+            mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc);
+        }
+
+        return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null);
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
index 10747a1..2776cc6 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java
@@ -25,7 +25,6 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.runtime.JSType.digit;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.lang.invoke.MethodHandle;
@@ -38,7 +37,13 @@
 public final class GlobalFunctions {
 
     /** Methodhandle to implementation of ECMA 15.1.2.2, parseInt */
-    public static final MethodHandle PARSEINT = findOwnMH("parseInt",   double.class, Object.class, Object.class, Object.class);
+    public static final MethodHandle PARSEINT = findOwnMH("parseInt", double.class, Object.class, Object.class, Object.class);
+
+    /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */
+    public static final MethodHandle PARSEINT_OI = findOwnMH("parseInt", double.class, Object.class, Object.class, int.class);
+
+    /** Methodhandle (specialized) to implementation of ECMA 15.1.2.2, parseInt */
+    public static final MethodHandle PARSEINT_O = findOwnMH("parseInt", double.class, Object.class, Object.class);
 
     /** Methodhandle to implementation of ECMA 15.1.2.3, parseFloat */
     public static final MethodHandle PARSEFLOAT = findOwnMH("parseFloat", double.class, Object.class, Object.class);
@@ -78,19 +83,44 @@
     /**
      * ECMA 15.1.2.2 parseInt implementation
      *
-     * TODO: specialize
+     * @param self   self reference
+     * @param string string to parse
+     * @param rad    radix
+     *
+     * @return numeric type representing string contents as an int
+     */
+    public static double parseInt(final Object self, final Object string, final Object rad) {
+        return parseIntInternal(JSType.trimLeft(JSType.toString(string)), JSType.toInt32(rad));
+    }
+
+    /**
+     * ECMA 15.1.2.2 parseInt implementation specialized for int radix
      *
      * @param self   self reference
      * @param string string to parse
      * @param rad    radix
      *
-     * @return numeric type representing string contents as an int (TODO: specialize for int case)
+     * @return numeric type representing string contents as an int
      */
-    //TODO specialize
-    public static double parseInt(final Object self, final Object string, final Object rad) {
-        final String str    = JSType.trimLeft(JSType.toString(string));
-        final int    length = str.length();
-        int          radix  = JSType.toInt32(rad);
+    public static double parseInt(final Object self, final Object string, final int rad) {
+        return parseIntInternal(JSType.trimLeft(JSType.toString(string)), rad);
+    }
+
+    /**
+     * ECMA 15.1.2.2 parseInt implementation specialized for no radix argument
+     *
+     * @param self   self reference
+     * @param string string to parse
+     *
+     * @return numeric type representing string contents as an int
+     */
+    public static double parseInt(final Object self, final Object string) {
+        return parseIntInternal(JSType.trimLeft(JSType.toString(string)), 0);
+    }
+
+    private static double parseIntInternal(final String str, final int rad) {
+        final int length = str.length();
+        int radix = rad;
 
         // empty string is not valid
         if (length == 0) {
@@ -142,7 +172,7 @@
         // we should see atleast one valid digit
         boolean entered = false;
         while (idx < length) {
-            digit = digit(str.charAt(idx++), radix, true);
+            digit = fastDigit(str.charAt(idx++), radix);
             if (digit < 0) {
                 break;
             }
@@ -456,6 +486,20 @@
         return ScriptRuntime.UNDEFINED;
     }
 
+    private static int fastDigit(final int ch, final int radix) {
+        int n = -1;
+        if (ch >= '0' && ch <= '9') {
+            n = ch - '0';
+        } else if (radix > 10) {
+            if (ch >= 'a' && ch <= 'z') {
+                n = ch - 'a' + 10;
+            } else if (ch >= 'A' && ch <= 'Z') {
+                n = ch - 'A' + 10;
+            }
+        }
+        return n < radix ? n : -1;
+    }
+
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), GlobalFunctions.class, name, MH.type(rtype, types));
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
index ab1de42..5fe5772 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSONFunctions.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+
 import java.lang.invoke.MethodHandle;
 import java.util.Iterator;
 import java.util.concurrent.Callable;
@@ -39,8 +41,6 @@
 import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-
 /**
  * Utilities used by "JSON" object implementation.
  */
@@ -90,7 +90,7 @@
         }
 
         final Global global = Context.getGlobal();
-        Object unfiltered = convertNode(global, node);
+        final Object unfiltered = convertNode(global, node);
         return applyReviver(global, unfiltered, reviver);
     }
 
@@ -139,8 +139,6 @@
 
     // Converts IR node to runtime value
     private static Object convertNode(final Global global, final Node node) {
-        assert global instanceof Global;
-
         if (node instanceof LiteralNode) {
             // check for array literal
             if (node.tokenType() == TokenType.ARRAY) {
@@ -188,7 +186,7 @@
         } else if (node instanceof UnaryNode) {
             // UnaryNode used only to represent negative number JSON value
             final UnaryNode unaryNode = (UnaryNode)node;
-            return -((LiteralNode<?>)unaryNode.rhs()).getNumber();
+            return -((LiteralNode<?>)unaryNode.getExpression()).getNumber();
         } else {
             return null;
         }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
index 3c430b2..e1357d6 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java
@@ -45,12 +45,12 @@
     }
 
     @Override
-    protected Object getAt(int index) {
+    protected Object getAt(final int index) {
         return ((JSObject)obj).getSlot(index);
     }
 
     @Override
-    protected void setAt(int index, Object element) {
+    protected void setAt(final int index, final Object element) {
         ((JSObject)obj).setSlot(index, element);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
index 11cecbf..350c502 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java
@@ -26,16 +26,21 @@
 package jdk.nashorn.internal.runtime;
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.Collections;
 import java.util.Deque;
 import java.util.List;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator;
@@ -72,58 +77,184 @@
     /** Max value for an uint32 in JavaScript */
     public static final long MAX_UINT = 0xFFFF_FFFFL;
 
-    private static final MethodHandles.Lookup myLookup = MethodHandles.lookup();
+    private static final MethodHandles.Lookup JSTYPE_LOOKUP = MethodHandles.lookup();
 
     /** JavaScript compliant conversion function from Object to boolean */
-    public static final Call TO_BOOLEAN = staticCall(myLookup, JSType.class, "toBoolean", boolean.class, Object.class);
+    public static final Call TO_BOOLEAN = staticCall(JSTYPE_LOOKUP, JSType.class, "toBoolean", boolean.class, Object.class);
 
     /** JavaScript compliant conversion function from number to boolean */
-    public static final Call TO_BOOLEAN_D = staticCall(myLookup, JSType.class, "toBoolean", boolean.class, double.class);
+    public static final Call TO_BOOLEAN_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toBoolean", boolean.class, double.class);
 
     /** JavaScript compliant conversion function from Object to integer */
-    public static final Call TO_INTEGER = staticCall(myLookup, JSType.class, "toInteger", int.class, Object.class);
+    public static final Call TO_INTEGER = staticCall(JSTYPE_LOOKUP, JSType.class, "toInteger", int.class, Object.class);
 
     /** JavaScript compliant conversion function from Object to long */
-    public static final Call TO_LONG = staticCall(myLookup, JSType.class, "toLong", long.class, Object.class);
+    public static final Call TO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "toLong", long.class, Object.class);
+
+    /** JavaScript compliant conversion function from double to long */
+    public static final Call TO_LONG_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toLong", long.class, double.class);
 
     /** JavaScript compliant conversion function from Object to number */
-    public static final Call TO_NUMBER = staticCall(myLookup, JSType.class, "toNumber", double.class, Object.class);
+    public static final Call TO_NUMBER = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumber", double.class, Object.class);
+
+    /** JavaScript compliant conversion function from Object to number with type check */
+    public static final Call TO_NUMBER_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toNumberOptimistic", double.class, Object.class, int.class);
 
     /** JavaScript compliant conversion function from Object to String */
-    public static final Call TO_STRING = staticCall(myLookup, JSType.class, "toString", String.class, Object.class);
+    public static final Call TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, Object.class);
 
     /** JavaScript compliant conversion function from Object to int32 */
-    public static final Call TO_INT32 = staticCall(myLookup, JSType.class, "toInt32", int.class, Object.class);
+    public static final Call TO_INT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, Object.class);
+
+    /** JavaScript compliant conversion function from Object to int32 */
+    public static final Call TO_INT32_L = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, long.class);
+
+    /** JavaScript compliant conversion function from Object to int32 with type check */
+    public static final Call TO_INT32_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32Optimistic", int.class, Object.class, int.class);
 
     /** JavaScript compliant conversion function from double to int32 */
-    public static final Call TO_INT32_D = staticCall(myLookup, JSType.class, "toInt32", int.class, double.class);
+    public static final Call TO_INT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toInt32", int.class, double.class);
 
     /** JavaScript compliant conversion function from Object to uint32 */
-    public static final Call TO_UINT32 = staticCall(myLookup, JSType.class, "toUint32", long.class, Object.class);
+    public static final Call TO_UINT32 = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, Object.class);
+
+    /** JavaScript compliant conversion function from Object to long with type check */
+    public static final Call TO_LONG_OPTIMISTIC = staticCall(JSTYPE_LOOKUP, JSType.class, "toLongOptimistic", long.class, Object.class, int.class);
 
     /** JavaScript compliant conversion function from number to uint32 */
-    public static final Call TO_UINT32_D = staticCall(myLookup, JSType.class, "toUint32", long.class, double.class);
-
-    /** JavaScript compliant conversion function from Object to int64 */
-    public static final Call TO_INT64 = staticCall(myLookup, JSType.class, "toInt64", long.class, Object.class);
-
-    /** JavaScript compliant conversion function from number to int64 */
-    public static final Call TO_INT64_D = staticCall(myLookup, JSType.class, "toInt64", long.class, double.class);
+    public static final Call TO_UINT32_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toUint32", long.class, double.class);
 
     /** JavaScript compliant conversion function from number to String */
-    public static final Call TO_STRING_D = staticCall(myLookup, JSType.class, "toString", String.class, double.class);
+    public static final Call TO_STRING_D = staticCall(JSTYPE_LOOKUP, JSType.class, "toString", String.class, double.class);
 
     /** Combined call to toPrimitive followed by toString. */
-    public static final Call TO_PRIMITIVE_TO_STRING = staticCall(myLookup, JSType.class, "toPrimitiveToString", String.class,  Object.class);
+    public static final Call TO_PRIMITIVE_TO_STRING = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToString", String.class, Object.class);
+
+    /** Combined call to toPrimitive followed by toCharSequence. */
+    public static final Call TO_PRIMITIVE_TO_CHARSEQUENCE = staticCall(JSTYPE_LOOKUP, JSType.class, "toPrimitiveToCharSequence", CharSequence.class, Object.class);
+
+    /** Throw an unwarranted optimism exception */
+    public static final Call THROW_UNWARRANTED = staticCall(JSTYPE_LOOKUP, JSType.class, "throwUnwarrantedOptimismException", Object.class, Object.class, int.class);
+
+    /** Add exact wrapper for potentially overflowing integer operations */
+    public static final Call ADD_EXACT       = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", int.class, int.class, int.class, int.class);
+
+    /** Sub exact wrapper for potentially overflowing integer operations */
+    public static final Call SUB_EXACT       = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", int.class, int.class, int.class, int.class);
+
+    /** Multiply exact wrapper for potentially overflowing integer operations */
+    public static final Call MUL_EXACT       = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", int.class, int.class, int.class, int.class);
+
+    /** Div exact wrapper for potentially integer division that turns into float point */
+    public static final Call DIV_EXACT       = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class);
+
+    /** Mod exact wrapper for potentially integer remainders that turns into float point */
+    public static final Call REM_EXACT       = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class);
+
+    /** Decrement exact wrapper for potentially overflowing integer operations */
+    public static final Call DECREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact",   int.class, int.class, int.class);
+
+    /** Increment exact wrapper for potentially overflowing integer operations */
+    public static final Call INCREMENT_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact",   int.class, int.class, int.class);
+
+    /** Negate exact exact wrapper for potentially overflowing integer operations */
+    public static final Call NEGATE_EXACT         = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact", int.class, int.class, int.class);
+
+    /** Add exact wrapper for potentially overflowing long operations */
+    public static final Call ADD_EXACT_LONG       = staticCall(JSTYPE_LOOKUP, JSType.class, "addExact", long.class, long.class, long.class, int.class);
+
+    /** Sub exact wrapper for potentially overflowing long operations */
+    public static final Call SUB_EXACT_LONG       = staticCall(JSTYPE_LOOKUP, JSType.class, "subExact", long.class, long.class, long.class, int.class);
+
+    /** Multiply exact wrapper for potentially overflowing long operations */
+    public static final Call MUL_EXACT_LONG       = staticCall(JSTYPE_LOOKUP, JSType.class, "mulExact", long.class, long.class, long.class, int.class);
+
+    /** Div exact wrapper for potentially integer division that turns into float point */
+    public static final Call DIV_EXACT_LONG       = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class);
+
+    /** Mod exact wrapper for potentially integer remainders that turns into float point */
+    public static final Call REM_EXACT_LONG       = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class);
+
+    /** Decrement exact wrapper for potentially overflowing long operations */
+    public static final Call DECREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "decrementExact",  long.class, long.class, int.class);
+
+    /** Increment exact wrapper for potentially overflowing long operations */
+    public static final Call INCREMENT_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "incrementExact",  long.class, long.class, int.class);
+
+    /** Negate exact exact wrapper for potentially overflowing long operations */
+    public static final Call NEGATE_EXACT_LONG    = staticCall(JSTYPE_LOOKUP, JSType.class, "negateExact",     long.class, long.class, int.class);
 
     /** Method handle to convert a JS Object to a Java array. */
-    public static final Call TO_JAVA_ARRAY = staticCall(myLookup, JSType.class, "toJavaArray", Object.class, Object.class, Class.class);
+    public static final Call TO_JAVA_ARRAY = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaArray", Object.class, Object.class, Class.class);
 
     /** Method handle to convert a JS Object to a Java List. */
-    public static final Call TO_JAVA_LIST = staticCall(myLookup, JSType.class, "toJavaList", List.class, Object.class);
+    public static final Call TO_JAVA_LIST = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaList", List.class, Object.class);
 
     /** Method handle to convert a JS Object to a Java deque. */
-   public static final Call TO_JAVA_DEQUE = staticCall(myLookup, JSType.class, "toJavaDeque", Deque.class, Object.class);
+    public static final Call TO_JAVA_DEQUE = staticCall(JSTYPE_LOOKUP, JSType.class, "toJavaDeque", Deque.class, Object.class);
+
+    /** Method handle for void returns. */
+    public static final Call VOID_RETURN = staticCall(JSTYPE_LOOKUP, JSType.class, "voidReturn", void.class);
+
+
+    /**
+     * The list of available accessor types in width order. This order is used for type guesses narrow{@literal ->} wide
+     *  in the dual--fields world
+     */
+    private static final List<Type> ACCESSOR_TYPES = Collections.unmodifiableList(
+            Arrays.asList(
+                Type.INT,
+                Type.LONG,
+                Type.NUMBER,
+                Type.OBJECT));
+
+    /** table index for undefined type - hard coded so it can be used in switches at compile time */
+    public static final int TYPE_UNDEFINED_INDEX = -1;
+    /** table index for integer type - hard coded so it can be used in switches at compile time */
+    public static final int TYPE_INT_INDEX    = 0; //getAccessorTypeIndex(int.class);
+    /** table index for long type - hard coded so it can be used in switches at compile time */
+    public static final int TYPE_LONG_INDEX   = 1; //getAccessorTypeIndex(long.class);
+    /** table index for double type - hard coded so it can be used in switches at compile time */
+    public static final int TYPE_DOUBLE_INDEX = 2; //getAccessorTypeIndex(double.class);
+    /** table index for object type - hard coded so it can be used in switches at compile time */
+    public static final int TYPE_OBJECT_INDEX = 3; //getAccessorTypeIndex(Object.class);
+
+    /** object conversion quickies with JS semantics - used for return value and parameter filter */
+    public static final List<MethodHandle> CONVERT_OBJECT = toUnmodifiableList(
+        JSType.TO_INT32.methodHandle(),
+        JSType.TO_UINT32.methodHandle(),
+        JSType.TO_NUMBER.methodHandle(),
+        null
+    );
+
+    /**
+     * object conversion quickies with JS semantics - used for return value and parameter filter, optimistic
+     * throws exception upon incompatible type (asking for a narrower one than the storage)
+     */
+    public static final List<MethodHandle> CONVERT_OBJECT_OPTIMISTIC = toUnmodifiableList(
+        JSType.TO_INT32_OPTIMISTIC.methodHandle(),
+        JSType.TO_LONG_OPTIMISTIC.methodHandle(),
+        JSType.TO_NUMBER_OPTIMISTIC.methodHandle(),
+        null
+    );
+
+    /** The value of Undefined cast to an int32 */
+    public static final int    UNDEFINED_INT    = 0;
+    /** The value of Undefined cast to a long */
+    public static final long   UNDEFINED_LONG   = 0L;
+    /** The value of Undefined cast to a double */
+    public static final double UNDEFINED_DOUBLE = Double.NaN;
+
+    /**
+     * Method handles for getters that return undefined coerced
+     * to the appropriate type
+     */
+    public static final List<MethodHandle> GET_UNDEFINED = toUnmodifiableList(
+        MH.constant(int.class, UNDEFINED_INT),
+        MH.constant(long.class, UNDEFINED_LONG),
+        MH.constant(double.class, UNDEFINED_DOUBLE),
+        MH.constant(Object.class, Undefined.getUndefined())
+    );
 
     private static final double INT32_LIMIT = 4294967296.0;
 
@@ -159,7 +290,7 @@
         }
 
         if (obj instanceof ScriptObject) {
-            return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT;
+            return obj instanceof ScriptFunction ? JSType.FUNCTION : JSType.OBJECT;
         }
 
         if (obj instanceof Boolean) {
@@ -182,6 +313,52 @@
     }
 
     /**
+     * Similar to {@link #of(Object)}, but does not distinguish between {@link #FUNCTION} and {@link #OBJECT}, returning
+     * {@link #OBJECT} in both cases. The distinction is costly, and the EQ and STRICT_EQ predicates don't care about it
+     * so we maintain this version for their use.
+     *
+     * @param obj an object
+     *
+     * @return the JSType for the object; returns {@link #OBJECT} instead of {@link #FUNCTION} for functions.
+     */
+    public static JSType ofNoFunction(final Object obj) {
+        // Order of these statements is tuned for performance (see JDK-8024476)
+        if (obj == null) {
+            return JSType.NULL;
+        }
+
+        if (obj instanceof ScriptObject) {
+            return JSType.OBJECT;
+        }
+
+        if (obj instanceof Boolean) {
+            return JSType.BOOLEAN;
+        }
+
+        if (obj instanceof String || obj instanceof ConsString) {
+            return JSType.STRING;
+        }
+
+        if (obj instanceof Number) {
+            return JSType.NUMBER;
+        }
+
+        if (obj == ScriptRuntime.UNDEFINED) {
+            return JSType.UNDEFINED;
+        }
+
+        return JSType.OBJECT;
+    }
+
+    /**
+     * Void return method handle glue
+     */
+    public static void voidReturn() {
+        //empty
+        //TODO: fix up SetMethodCreator better so we don't need this stupid thing
+    }
+
+    /**
      * Returns true if double number can be represented as an int
      *
      * @param number a long to inspect
@@ -193,7 +370,8 @@
     }
 
     /**
-     * Returns true if double number can be represented as an int
+     * Returns true if double number can be represented as an int. Note that it returns true for negative zero. If you
+     * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}.
      *
      * @param number a double to inspect
      *
@@ -204,7 +382,22 @@
     }
 
     /**
-     * Returns true if double number can be represented as a long
+     * Returns true if Object can be represented as an int
+     *
+     * @param obj an object to inspect
+     *
+     * @return true for int representable objects
+     */
+    public static boolean isRepresentableAsInt(final Object obj) {
+        if (obj instanceof Number) {
+            return isRepresentableAsInt(((Number)obj).doubleValue());
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if double number can be represented as a long. Note that it returns true for negative zero. If you
+     * need to exclude negative zero, combine this check with {@link #isNegativeZero(double)}.
      *
      * @param number a double to inspect
      * @return true for long representable doubles
@@ -214,13 +407,36 @@
     }
 
     /**
+     * Returns true if Object can be represented as a long
+     *
+     * @param obj an object to inspect
+     *
+     * @return true for long representable objects
+     */
+    public static boolean isRepresentableAsLong(final Object obj) {
+        if (obj instanceof Number) {
+            return isRepresentableAsLong(((Number)obj).doubleValue());
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if the number is the negative zero ({@code -0.0d}).
+     * @param number the number to test
+     * @return true if it is the negative zero, false otherwise.
+     */
+    public static boolean isNegativeZero(final double number) {
+        return number == 0.0d && Double.doubleToRawLongBits(number) == 0x8000000000000000L;
+    }
+
+    /**
      * Check whether an object is primitive
      *
      * @param obj an object
      *
      * @return true if object is primitive (includes null and undefined)
      */
-   public static boolean isPrimitive(final Object obj) {
+    public static boolean isPrimitive(final Object obj) {
         return obj == null ||
                obj == ScriptRuntime.UNDEFINED ||
                obj instanceof Boolean ||
@@ -270,11 +486,21 @@
      *
      * @return the string form of the primitive form of the object
      */
-    public static String toPrimitiveToString(Object obj) {
+    public static String toPrimitiveToString(final Object obj) {
         return toString(toPrimitive(obj));
     }
 
     /**
+     * Like {@link #toPrimitiveToString(Object)}, but avoids conversion of ConsString to String.
+     *
+     * @param obj  an object
+     * @return the CharSequence form of the primitive form of the object
+     */
+    public static CharSequence toPrimitiveToCharSequence(final Object obj) {
+        return toCharSequence(toPrimitive(obj));
+    }
+
+    /**
      * JavaScript compliant conversion of number to boolean
      *
      * @param num a number
@@ -494,6 +720,35 @@
     }
 
     /**
+     * Optimistic number conversion - throws UnwarrantedOptimismException if Object
+     *
+     * @param obj           object to convert
+     * @param programPoint  program point
+     * @return double
+     */
+    public static double toNumberOptimistic(final Object obj, final int programPoint) {
+        if (obj != null) {
+            final Class<?> clz = obj.getClass();
+            if (clz == Double.class || clz == Integer.class || clz == Long.class) {
+                return ((Number)obj).doubleValue();
+            }
+        }
+        throw new UnwarrantedOptimismException(obj, programPoint);
+    }
+
+    /**
+     * Object to number conversion that delegates to either {@link #toNumber(Object)} or to
+     * {@link #toNumberOptimistic(Object, int)} depending on whether the program point is valid or not.
+     * @param obj the object to convert
+     * @param programPoint the program point; can be invalid.
+     * @return the value converted to a number
+     * @throws UnwarrantedOptimismException if the value can't be represented as a number and the program point is valid.
+     */
+    public static double toNumberMaybeOptimistic(final Object obj, final int programPoint) {
+        return UnwarrantedOptimismException.isValid(programPoint) ? toNumberOptimistic(obj, programPoint) : toNumber(obj);
+    }
+
+    /**
      * Digit representation for a character
      *
      * @param ch     a character
@@ -612,7 +867,7 @@
     }
 
     /**
-     * JavaScript compliant Object to long conversion. See ECMA 9.4 ToInteger
+     * Converts an Object to long.
      *
      * <p>Note that this returns {@link java.lang.Long#MAX_VALUE} or {@link java.lang.Long#MIN_VALUE}
      * for double values that exceed the long range, including positive and negative Infinity. It is the
@@ -622,7 +877,46 @@
      * @return a long
      */
     public static long toLong(final Object obj) {
-        return (long)toNumber(obj);
+        return obj instanceof Long ? ((Long)obj).longValue() : toLong(toNumber(obj));
+    }
+
+    /**
+     * Converts a double to long.
+     *
+     * @param num the double to convert
+     * @return the converted long value
+     */
+    public static long toLong(final double num) {
+        return (long)num;
+    }
+
+    /**
+     * Optimistic long conversion - throws UnwarrantedOptimismException if double or Object
+     *
+     * @param obj           object to convert
+     * @param programPoint  program point
+     * @return long
+     */
+    public static long toLongOptimistic(final Object obj, final int programPoint) {
+        if (obj != null) {
+            final Class<?> clz = obj.getClass();
+            if (clz == Long.class || clz == Integer.class) {
+                return ((Number)obj).longValue();
+            }
+        }
+        throw new UnwarrantedOptimismException(obj, programPoint);
+    }
+
+    /**
+     * Object to int conversion that delegates to either {@link #toLong(Object)} or to
+     * {@link #toLongOptimistic(Object, int)} depending on whether the program point is valid or not.
+     * @param obj the object to convert
+     * @param programPoint the program point; can be invalid.
+     * @return the value converted to long
+     * @throws UnwarrantedOptimismException if the value can't be represented as long and the program point is valid.
+     */
+    public static long toLongMaybeOptimistic(final Object obj, final int programPoint) {
+        return UnwarrantedOptimismException.isValid(programPoint) ? toLongOptimistic(obj, programPoint) : toLong(obj);
     }
 
     /**
@@ -637,15 +931,49 @@
     }
 
     /**
+     * Optimistic int conversion - throws UnwarrantedOptimismException if double, long or Object
+     *
+     * @param obj           object to convert
+     * @param programPoint  program point
+     * @return double
+     */
+    public static int toInt32Optimistic(final Object obj, final int programPoint) {
+        if (obj != null) {
+            final Class<?> clz = obj.getClass();
+            if (clz == Integer.class) {
+                return ((Integer)obj).intValue();
+            }
+        }
+        throw new UnwarrantedOptimismException(obj, programPoint);
+    }
+
+    /**
+     * Object to int conversion that delegates to either {@link #toInt32(Object)} or to
+     * {@link #toInt32Optimistic(Object, int)} depending on whether the program point is valid or not.
+     * @param obj the object to convert
+     * @param programPoint the program point; can be invalid.
+     * @return the value converted to int
+     * @throws UnwarrantedOptimismException if the value can't be represented as int and the program point is valid.
+     */
+    public static int toInt32MaybeOptimistic(final Object obj, final int programPoint) {
+        return UnwarrantedOptimismException.isValid(programPoint) ? toInt32Optimistic(obj, programPoint) : toInt32(obj);
+    }
+
+    // Minimum and maximum range between which every long value can be precisely represented as a double.
+    private static final long MAX_PRECISE_DOUBLE = 1L << 53;
+    private static final long MIN_PRECISE_DOUBLE = -MAX_PRECISE_DOUBLE;
+
+    /**
      * JavaScript compliant long to int32 conversion
      *
      * @param num a long
      * @return an int32
      */
     public static int toInt32(final long num) {
-        return (int)num;
+        return (int)(num >= MIN_PRECISE_DOUBLE && num <= MAX_PRECISE_DOUBLE ? num : (long)(num % INT32_LIMIT));
     }
 
+
     /**
      * JavaScript compliant number to int32 conversion
      *
@@ -657,29 +985,6 @@
     }
 
     /**
-     * JavaScript compliant Object to int64 conversion
-     *
-     * @param obj an object
-     * @return an int64
-     */
-    public static long toInt64(final Object obj) {
-        return toInt64(toNumber(obj));
-    }
-
-    /**
-     * JavaScript compliant number to int64 conversion
-     *
-     * @param num a number
-     * @return an int64
-     */
-    public static long toInt64(final double num) {
-        if (Double.isInfinite(num)) {
-            return 0L;
-        }
-        return (long)num;
-    }
-
-    /**
      * JavaScript compliant Object to uint32 conversion
      *
      * @param obj an object
@@ -727,7 +1032,7 @@
      * @return a uint16
      */
     public static int toUint16(final long num) {
-        return ((int)num) & 0xffff;
+        return (int)num & 0xffff;
     }
 
     /**
@@ -737,7 +1042,7 @@
      * @return a uint16
      */
     public static int toUint16(final double num) {
-        return ((int)doubleToInt32(num)) & 0xffff;
+        return (int)doubleToInt32(num) & 0xffff;
     }
 
     private static long doubleToInt32(final double num) {
@@ -751,7 +1056,7 @@
             return 0;
         }
         // This is rather slow and could probably be sped up using bit-fiddling.
-        final double d = (num >= 0) ? Math.floor(num) : Math.ceil(num);
+        final double d = num >= 0 ? Math.floor(num) : Math.ceil(num);
         return (long)(d % INT32_LIMIT);
     }
 
@@ -1014,6 +1319,404 @@
         return str.substring(start);
     }
 
+    /**
+     * Throw an unwarranted optimism exception for a program point
+     * @param value         real return value
+     * @param programPoint  program point
+     * @return
+     */
+    @SuppressWarnings("unused")
+    private static Object throwUnwarrantedOptimismException(final Object value, final int programPoint) {
+        throw new UnwarrantedOptimismException(value, programPoint);
+    }
+
+    /**
+     * Wrapper for addExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static int addExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.addExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((long)x + (long)y, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for addExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static long addExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.addExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((double)x + (double)y, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for subExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static int subExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.subtractExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((long)x - (long)y, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for subExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static long subExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.subtractExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((double)x - (double)y, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for mulExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static int mulExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.multiplyExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((long)x * (long)y, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for mulExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static long mulExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.multiplyExact(x, y);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((double)x * (double)y, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as
+     * int.
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if the result of the division can't be represented as int.
+     */
+    public static int divExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+        final int res;
+        try {
+            res = x / y;
+        } catch (final ArithmeticException e) {
+            assert y == 0; // Only div by zero anticipated
+            throw new UnwarrantedOptimismException(x > 0 ? Double.POSITIVE_INFINITY : x < 0 ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint);
+        }
+        final int rem = x % y;
+        if (rem == 0) {
+            return res;
+        }
+        // go directly to double here, as anything with non zero remainder is a floating point number in JavaScript
+        throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
+    }
+
+    /**
+     * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if the modulo can't be represented as int.
+     */
+    public static int remExact(final int x, final int y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return x % y;
+        } catch (final ArithmeticException e) {
+            assert y == 0; // Only mod by zero anticipated
+            throw new UnwarrantedOptimismException(Double.NaN, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for divExact. Throws UnwarrantedOptimismException if the result of the division can't be represented as
+     * long.
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if the result of the division can't be represented as long.
+     */
+    public static long divExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+        final long res;
+        try {
+            res = x / y;
+        } catch (final ArithmeticException e) {
+            assert y == 0L; // Only div by zero anticipated
+            throw new UnwarrantedOptimismException(x > 0L ? Double.POSITIVE_INFINITY : x < 0L ? Double.NEGATIVE_INFINITY : Double.NaN, programPoint);
+        }
+        final long rem = x % y;
+        if (rem == 0L) {
+            return res;
+        }
+        throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
+    }
+
+    /**
+     * Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
+     *
+     * @param x first term
+     * @param y second term
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if the modulo can't be represented as int.
+     */
+    public static long remExact(final long x, final long y, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return x % y;
+        } catch (final ArithmeticException e) {
+            assert y == 0L; // Only mod by zero anticipated
+            throw new UnwarrantedOptimismException(Double.NaN, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for decrementExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x number to negate
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static int decrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.decrementExact(x);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((long)x - 1, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for decrementExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x number to negate
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static long decrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.decrementExact(x);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((double)x - 1L, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for incrementExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x the number to increment
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static int incrementExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.incrementExact(x);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((long)x + 1, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for incrementExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x the number to increment
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static long incrementExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            return Math.incrementExact(x);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException((double)x + 1L, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for negateExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x the number to negate
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static int negateExact(final int x, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            if (x == 0) {
+                throw new UnwarrantedOptimismException(-0.0, programPoint);
+            }
+            return Math.negateExact(x);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException(-(long)x, programPoint);
+        }
+    }
+
+    /**
+     * Wrapper for negateExact
+     *
+     * Catches ArithmeticException and rethrows as UnwarrantedOptimismException
+     * containing the result and the program point of the failure
+     *
+     * @param x the number to negate
+     * @param programPoint program point id
+     * @return the result
+     * @throws UnwarrantedOptimismException if overflow occurs
+     */
+    public static long negateExact(final long x, final int programPoint) throws UnwarrantedOptimismException {
+        try {
+            if (x == 0L) {
+                throw new UnwarrantedOptimismException(-0.0, programPoint);
+            }
+            return Math.negateExact(x);
+        } catch (final ArithmeticException e) {
+            throw new UnwarrantedOptimismException(-(double)x, programPoint);
+        }
+    }
+
+    /**
+     * Given a type of an accessor, return its index in [0..getNumberOfAccessorTypes())
+     *
+     * @param type the type
+     *
+     * @return the accessor index, or -1 if no accessor of this type exists
+     */
+    public static int getAccessorTypeIndex(final Type type) {
+        return getAccessorTypeIndex(type.getTypeClass());
+    }
+
+    /**
+     * Given a class of an accessor, return its index in [0..getNumberOfAccessorTypes())
+     *
+     * Note that this is hardcoded with respect to the dynamic contents of the accessor
+     * types array for speed. Hotspot got stuck with this as 5% of the runtime in
+     * a benchmark when it looped over values and increased an index counter. :-(
+     *
+     * @param type the type
+     *
+     * @return the accessor index, or -1 if no accessor of this type exists
+     */
+    public static int getAccessorTypeIndex(final Class<?> type) {
+        if (type == null) {
+            return TYPE_UNDEFINED_INDEX;
+        } else if (type == int.class) {
+            return TYPE_INT_INDEX;
+        } else if (type == long.class) {
+            return TYPE_LONG_INDEX;
+        } else if (type == double.class) {
+            return TYPE_DOUBLE_INDEX;
+        } else if (!type.isPrimitive()) {
+            return TYPE_OBJECT_INDEX;
+        }
+        return -1;
+    }
+
+    /**
+     * Return the accessor type based on its index in [0..getNumberOfAccessorTypes())
+     * Indexes are ordered narrower{@literal ->}wider / optimistic{@literal ->}pessimistic. Invalidations always
+     * go to a type of higher index
+     *
+     * @param index accessor type index
+     *
+     * @return a type corresponding to the index.
+     */
+
+    public static Type getAccessorType(final int index) {
+        return ACCESSOR_TYPES.get(index);
+    }
+
+    /**
+     * Return the number of accessor types available.
+     *
+     * @return number of accessor types in system
+     */
+    public static int getNumberOfAccessorTypes() {
+        return ACCESSOR_TYPES.size();
+    }
+
     private static double parseRadix(final char chars[], final int start, final int length, final int radix) {
         int pos = 0;
 
@@ -1074,4 +1777,50 @@
             throw new RuntimeException(t);
         }
     }
+
+    /**
+     * Create a method handle constant of the correct primitive type
+     * for a constant object
+     * @param o object
+     * @return constant function that returns object
+     */
+    public static MethodHandle unboxConstant(final Object o) {
+        if (o != null) {
+            if (o.getClass() == Integer.class) {
+                return MH.constant(int.class, ((Integer)o).intValue());
+            } else if (o.getClass() == Long.class) {
+                return MH.constant(long.class, ((Long)o).longValue());
+            } else if (o.getClass() == Double.class) {
+                return MH.constant(double.class, ((Double)o).doubleValue());
+            }
+        }
+        return MH.constant(Object.class, o);
+    }
+
+    /**
+     * Get the unboxed (primitive) type for an object
+     * @param o object
+     * @return primive type or Object.class if not primitive
+     */
+    public static Class<?> unboxedFieldType(final Object o) {
+        if (OBJECT_FIELDS_ONLY) {
+            return Object.class;
+        }
+
+        if (o == null) {
+            return Object.class;
+        } else if (o.getClass() == Integer.class) {
+            return int.class;
+        } else if (o.getClass() == Long.class) {
+            return long.class;
+        } else if (o.getClass() == Double.class) {
+            return double.class;
+        } else {
+            return Object.class;
+        }
+    }
+
+    private static final List<MethodHandle> toUnmodifiableList(final MethodHandle... methodHandles) {
+        return Collections.unmodifiableList(Arrays.asList(methodHandles));
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
index 9a3408f..25179a5 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java
@@ -34,7 +34,6 @@
 import java.util.concurrent.Callable;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
-import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.InvokeByName;
 
@@ -174,7 +173,7 @@
      */
     protected abstract void setAt(final int index, final Object element);
 
-    private void checkRange(int index) {
+    private void checkRange(final int index) {
         if(index < 0 || index >= size()) {
             throw invalidIndex(index);
         }
@@ -200,7 +199,7 @@
             unshiftInvoker.getInvoker().invokeExact(fn, obj, e);
         } catch(RuntimeException | Error ex) {
             throw ex;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
@@ -214,7 +213,7 @@
             pushInvoker.getInvoker().invokeExact(fn, obj, e);
         } catch(RuntimeException | Error ex) {
             throw ex;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
@@ -328,7 +327,7 @@
             return shiftInvoker.getInvoker().invokeExact(fn, obj);
         } catch(RuntimeException | Error ex) {
             throw ex;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
@@ -341,7 +340,7 @@
             return popInvoker.getInvoker().invokeExact(fn, obj);
         } catch(RuntimeException | Error ex) {
             throw ex;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
@@ -359,7 +358,7 @@
             spliceRemoveInvoker.getInvoker().invokeExact(fn, obj, fromIndex, count);
         } catch(RuntimeException | Error ex) {
             throw ex;
-        } catch(Throwable t) {
+        } catch(final Throwable t) {
             throw new RuntimeException(t);
         }
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Logging.java b/nashorn/src/jdk/nashorn/internal/runtime/Logging.java
deleted file mode 100644
index 54d83b7..0000000
--- a/nashorn/src/jdk/nashorn/internal/runtime/Logging.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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.
- */
-
-package jdk.nashorn.internal.runtime;
-
-import java.security.AccessControlContext;
-import java.security.AccessController;
-import java.security.Permissions;
-import java.security.PrivilegedAction;
-import java.security.ProtectionDomain;
-import java.util.HashMap;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.logging.ConsoleHandler;
-import java.util.logging.Formatter;
-import java.util.logging.Handler;
-import java.util.logging.Level;
-import java.util.logging.LogRecord;
-import java.util.logging.Logger;
-import java.util.logging.LoggingPermission;
-
-/**
- * Logging system for getting loggers for arbitrary subsystems as
- * specified on the command line. Supports all standard log levels
- *
- */
-public final class Logging {
-
-    private Logging() {
-    }
-
-    /** Loggers */
-
-    private static final Logger disabledLogger = Logger.getLogger("disabled");
-
-    private static AccessControlContext createLoggerControlAccCtxt() {
-        final Permissions perms = new Permissions();
-        perms.add(new LoggingPermission("control", null));
-        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
-    }
-
-    static {
-        AccessController.doPrivileged(new PrivilegedAction<Void>() {
-            @Override
-            public Void run() {
-                Logging.disabledLogger.setLevel(Level.OFF);
-                return null;
-            }
-        }, createLoggerControlAccCtxt());
-    }
-
-    /** Maps logger name to loggers. Names are typically per package */
-    private static final Map<String, Logger> loggers = new HashMap<>();
-
-    private static String lastPart(final String packageName) {
-        final String[] parts = packageName.split("\\.");
-        if (parts.length == 0) {
-            return packageName;
-        }
-        return parts[parts.length - 1];
-    }
-
-    /**
-     * Get a logger for a given class, generating a logger name based on the
-     * class name
-     *
-     * @param name the name to use as key for the logger
-     * @return the logger
-     */
-    public static Logger getLogger(final String name) {
-        final Logger logger = Logging.loggers.get(name);
-        if (logger != null) {
-            return logger;
-        }
-        return Logging.disabledLogger;
-    }
-
-    /**
-     * Get a logger for a given name or create it if not already there, typically
-     * used for mapping system properties to loggers
-     *
-     * @param name the name to use as key
-     * @param level log lever to reset existing logger with, or create new logger with
-     * @return the logger
-     */
-    public static Logger getOrCreateLogger(final String name, final Level level) {
-        final Logger logger = Logging.loggers.get(name);
-        if (logger == null) {
-            return instantiateLogger(name, level);
-        }
-        logger.setLevel(level);
-        return logger;
-    }
-
-    /**
-     * Initialization function that is called to instantiate the logging system. It takes
-     * logger names (keys) and logging labels respectively
-     *
-     * @param map a map where the key is a logger name and the value a logging level
-     * @throws IllegalArgumentException if level or names cannot be parsed
-     */
-    public static void initialize(final Map<String, String> map) throws IllegalArgumentException {
-        try {
-            for (final Entry<String, String> entry : map.entrySet()) {
-                Level level;
-
-                final String key   = entry.getKey();
-                final String value = entry.getValue();
-                if ("".equals(value)) {
-                    level = Level.INFO;
-                } else {
-                    level = Level.parse(value.toUpperCase(Locale.ENGLISH));
-                }
-
-                final String name = Logging.lastPart(key);
-                final Logger logger = instantiateLogger(name, level);
-
-                Logging.loggers.put(name, logger);
-            }
-        } catch (final IllegalArgumentException | SecurityException e) {
-            throw e;
-        }
-    }
-
-    private static Logger instantiateLogger(final String name, final Level level) {
-        final Logger logger = java.util.logging.Logger.getLogger(name);
-        for (final Handler h : logger.getHandlers()) {
-            logger.removeHandler(h);
-        }
-
-        logger.setLevel(level);
-        logger.setUseParentHandlers(false);
-        final Handler c = new ConsoleHandler();
-
-        c.setFormatter(new Formatter() {
-            @Override
-            public String format(final LogRecord record) {
-                final StringBuilder sb = new StringBuilder();
-
-                sb.append('[')
-                   .append(record.getLoggerName())
-                   .append("] ")
-                   .append(record.getMessage())
-                   .append('\n');
-
-                return sb.toString();
-            }
-        });
-        logger.addHandler(c);
-        c.setLevel(level);
-
-        return logger;
-    }
-
-}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java
index e783701..423b87d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java
@@ -92,7 +92,7 @@
     }
 
     @Override
-    protected PermissionCollection getPermissions(CodeSource codesource) {
+    protected PermissionCollection getPermissions(final CodeSource codesource) {
         final Permissions permCollection = new Permissions();
         for (final Permission perm : SCRIPT_PERMISSIONS) {
             permCollection.add(perm);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
index fbca1c3..27c9bca 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java
@@ -25,10 +25,14 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
 import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.beans.BeansLinker;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
@@ -135,12 +139,12 @@
     }
 
     @Override
-    protected GuardedInvocation findNewMethod(CallSiteDescriptor desc) {
+    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         return createClassNotFoundInvocation(desc);
     }
 
     @Override
-    protected GuardedInvocation findCallMethod(CallSiteDescriptor desc, LinkRequest request) {
+    protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         return createClassNotFoundInvocation(desc);
     }
 
@@ -202,8 +206,12 @@
     }
 
     @Override
-    protected Object invokeNoSuchProperty(final String name) {
-        return createProperty(name);
+    protected Object invokeNoSuchProperty(final String key, final int programPoint) {
+        final Object retval = createProperty(key);
+        if (isValid(programPoint)) {
+            throw new UnwarrantedOptimismException(retval, programPoint);
+        }
+        return retval;
     }
 
     @Override
@@ -226,6 +234,35 @@
             //ignored
         }
 
+        // Check for explicit constructor signature use
+        // Example: new (java.awt["Color(int, int,int)"])(2, 3, 4);
+        final int openBrace = propertyName.indexOf('(');
+        final int closeBrace = propertyName.lastIndexOf(')');
+        if (openBrace != -1 || closeBrace != -1) {
+            final int lastChar = propertyName.length() - 1;
+            if (openBrace == -1 || closeBrace != lastChar) {
+                throw typeError("improper.constructor.signature", propertyName);
+            }
+
+            // get the class name and try to load it
+            final String className = name + "." + propertyName.substring(0, openBrace);
+            try {
+                javaClass = context.findClass(className);
+            } catch (final NoClassDefFoundError | ClassNotFoundException e) {
+                throw typeError(e, "no.such.java.class", className);
+            }
+
+            // try to find a matching constructor
+            final Object constructor = BeansLinker.getConstructorMethod(
+                    javaClass, propertyName.substring(openBrace + 1, lastChar));
+            if (constructor != null) {
+                set(propertyName, constructor, false);
+                return constructor;
+            }
+            // we didn't find a matching constructor!
+            throw typeError("no.such.java.constructor", propertyName);
+        }
+
         final Object propertyValue;
         if (javaClass == null) {
             propertyValue = new NativeJavaPackage(fullName, getProto());
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java b/nashorn/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
new file mode 100644
index 0000000..4f768e1
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/OptimisticReturnFilters.java
@@ -0,0 +1,276 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.support.TypeUtilities;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+
+/**
+ * Optimistic return value filters
+ */
+public final class OptimisticReturnFilters {
+    private static final MethodHandle[] ENSURE_INT;
+    private static final MethodHandle[] ENSURE_LONG;
+    private static final MethodHandle[] ENSURE_NUMBER;
+
+    private static final int BOOLEAN_TYPE_INDEX;
+    private static final int CHAR_TYPE_INDEX;
+    private static final int FLOAT_TYPE_INDEX;
+    private static final int VOID_TYPE_INDEX;
+
+    static {
+        final MethodHandle INT_DOUBLE = findOwnMH("ensureInt", int.class, double.class, int.class);
+        ENSURE_INT = new MethodHandle[] {
+                null,
+                findOwnMH("ensureInt", int.class, long.class, int.class),
+                INT_DOUBLE,
+                findOwnMH("ensureInt", int.class, Object.class, int.class),
+                findOwnMH("ensureInt", int.class, int.class),
+                findOwnMH("ensureInt", int.class, boolean.class, int.class),
+                findOwnMH("ensureInt", int.class, char.class, int.class),
+                INT_DOUBLE.asType(INT_DOUBLE.type().changeParameterType(0, float.class)),
+        };
+
+        VOID_TYPE_INDEX = ENSURE_INT.length - 4;
+        BOOLEAN_TYPE_INDEX = ENSURE_INT.length - 3;
+        CHAR_TYPE_INDEX = ENSURE_INT.length - 2;
+        FLOAT_TYPE_INDEX = ENSURE_INT.length - 1;
+
+        final MethodHandle LONG_DOUBLE = findOwnMH("ensureLong", long.class, double.class, int.class);
+        ENSURE_LONG = new MethodHandle[] {
+                null,
+                null,
+                LONG_DOUBLE,
+                findOwnMH("ensureLong", long.class, Object.class, int.class),
+                ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(long.class)),
+                ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(long.class)),
+                ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(long.class)),
+                LONG_DOUBLE.asType(LONG_DOUBLE.type().changeParameterType(0, float.class)),
+            };
+
+        ENSURE_NUMBER = new MethodHandle[] {
+                null,
+                null,
+                null,
+                findOwnMH("ensureNumber", double.class, Object.class, int.class),
+                ENSURE_INT[VOID_TYPE_INDEX].asType(ENSURE_INT[VOID_TYPE_INDEX].type().changeReturnType(double.class)),
+                ENSURE_INT[BOOLEAN_TYPE_INDEX].asType(ENSURE_INT[BOOLEAN_TYPE_INDEX].type().changeReturnType(double.class)),
+                ENSURE_INT[CHAR_TYPE_INDEX].asType(ENSURE_INT[CHAR_TYPE_INDEX].type().changeReturnType(double.class)),
+                null
+        };
+    }
+
+    /**
+     * Given a method handle and an expected return type, perform return value filtering
+     * according to the optimistic type coercion rules
+     * @param mh method handle
+     * @param expectedReturnType expected return type
+     * @param programPoint program point
+     * @return filtered method
+     */
+    public static MethodHandle filterOptimisticReturnValue(final MethodHandle mh, final Class<?> expectedReturnType, final int programPoint) {
+        if(!isValid(programPoint)) {
+            return mh;
+        }
+
+        final MethodType type = mh.type();
+        final Class<?> actualReturnType = type.returnType();
+        if(TypeUtilities.isConvertibleWithoutLoss(actualReturnType, expectedReturnType)) {
+            return mh;
+        }
+
+        final MethodHandle guard = getOptimisticTypeGuard(expectedReturnType, actualReturnType);
+        return guard == null ? mh : MH.filterReturnValue(mh, MH.insertArguments(guard, guard.type().parameterCount() - 1, programPoint));
+    }
+
+    /**
+     * Given a guarded invocation and a callsite descriptor, perform return value filtering
+     * according to the optimistic type coercion rules, using the return value from the descriptor
+     * @param inv the invocation
+     * @param desc the descriptor
+     * @return filtered invocation
+     */
+    public static GuardedInvocation filterOptimisticReturnValue(final GuardedInvocation inv, final CallSiteDescriptor desc) {
+        if(!NashornCallSiteDescriptor.isOptimistic(desc)) {
+            return inv;
+        }
+        return inv.replaceMethods(filterOptimisticReturnValue(inv.getInvocation(), desc.getMethodType().returnType(),
+                NashornCallSiteDescriptor.getProgramPoint(desc)), inv.getGuard());
+    }
+
+    private static MethodHandle getOptimisticTypeGuard(final Class<?> actual, final Class<?> provable) {
+        final MethodHandle guard;
+        final int provableTypeIndex = getProvableTypeIndex(provable);
+        if (actual == int.class) {
+            guard = ENSURE_INT[provableTypeIndex];
+        } else if (actual == long.class) {
+            guard = ENSURE_LONG[provableTypeIndex];
+        } else if (actual == double.class) {
+            guard = ENSURE_NUMBER[provableTypeIndex];
+        } else {
+            guard = null;
+            assert !actual.isPrimitive() : actual + ", " + provable;
+        }
+        if(guard != null && !(provable.isPrimitive())) {
+            // Make sure filtering a MethodHandle(...)String works with a filter MethodHandle(Object, int)... Note that
+            // if the return type of the method is incompatible with Number, then the guard will always throw an
+            // UnwarrantedOperationException when invoked, but we must link it anyway as we need the guarded function to
+            // successfully execute and return the non-convertible return value that it'll put into the thrown
+            // UnwarrantedOptimismException.
+            return guard.asType(guard.type().changeParameterType(0, provable));
+        }
+        return guard;
+    }
+
+    private static int getProvableTypeIndex(final Class<?> provable) {
+        final int accTypeIndex = getAccessorTypeIndex(provable);
+        if(accTypeIndex != -1) {
+            return accTypeIndex;
+        } else if(provable == boolean.class) {
+            return BOOLEAN_TYPE_INDEX;
+        } else if(provable == void.class) {
+            return VOID_TYPE_INDEX;
+        } else if(provable == byte.class || provable == short.class) {
+            return 0; // never needs a guard, as it's assignable to int
+        } else if(provable == char.class) {
+            return CHAR_TYPE_INDEX;
+        } else if(provable == float.class) {
+            return FLOAT_TYPE_INDEX;
+        }
+        throw new AssertionError(provable.getName());
+    }
+
+    //maps staticallyProvableCallSiteType to actualCallSiteType, throws exception if impossible
+    @SuppressWarnings("unused")
+    private static int ensureInt(final long arg, final int programPoint) {
+        if (JSType.isRepresentableAsInt(arg)) {
+            return (int)arg;
+        }
+        throw new UnwarrantedOptimismException(arg, programPoint);
+    }
+
+    @SuppressWarnings("unused")
+    private static int ensureInt(final double arg, final int programPoint) {
+        if (JSType.isRepresentableAsInt(arg) && !JSType.isNegativeZero(arg)) {
+            return (int)arg;
+        }
+        throw new UnwarrantedOptimismException(arg, programPoint);
+    }
+
+    /**
+     * Returns the argument value as an int. If the argument is not a Number object that can be exactly represented as
+     * an int, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
+     * can use it. See {code CodeGenerator.ENSURE_INT}.
+     * @param arg the original argument.
+     * @param programPoint the program point used in the exception
+     * @return the value of the argument as an int.
+     * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as an int.
+     */
+    public static int ensureInt(final Object arg, final int programPoint) {
+        // NOTE: this doesn't delegate to ensureInt(double, int) as in that case if arg were a Long, it would throw a
+        // (potentially imprecise) Double in the UnwarrantedOptimismException. This way, it will put the correct valued
+        // Long into the exception.
+        if (arg instanceof Number) {
+            final double d = ((Number)arg).doubleValue();
+            if (JSType.isRepresentableAsInt(d) && !JSType.isNegativeZero(d)) {
+                return (int)d;
+            }
+        }
+        throw new UnwarrantedOptimismException(arg, programPoint);
+    }
+
+    @SuppressWarnings("unused")
+    private static int ensureInt(final boolean arg, final int programPoint) {
+        throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
+    }
+
+    @SuppressWarnings("unused")
+    private static int ensureInt(final char arg, final int programPoint) {
+        throw new UnwarrantedOptimismException(arg, programPoint, Type.OBJECT);
+    }
+
+    @SuppressWarnings("unused")
+    private static int ensureInt(final int programPoint) {
+        // Turns a void into UNDEFINED
+        throw new UnwarrantedOptimismException(ScriptRuntime.UNDEFINED, programPoint, Type.OBJECT);
+    }
+
+    private static long ensureLong(final double arg, final int programPoint) {
+        if (JSType.isRepresentableAsLong(arg) && !JSType.isNegativeZero(arg)) {
+            return (long)arg;
+        }
+        throw new UnwarrantedOptimismException(arg, programPoint);
+    }
+
+    /**
+     * Returns the argument value as a long. If the argument is not a Number object that can be exactly represented as
+     * a long, throw an {@link UnwarrantedOptimismException}.This method is only public so that generated script code
+     * can use it. See {code CodeGenerator.ENSURE_LONG}.
+     * @param arg the original argument.
+     * @param programPoint the program point used in the exception
+     * @return the value of the argument as a long.
+     * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long.
+     */
+    public static long ensureLong(final Object arg, final int programPoint) {
+        if (arg instanceof Long) {
+            // Must check for Long separately, as Long.doubleValue() isn't precise.
+            return ((Long)arg).longValue();
+        } else if (arg instanceof Number) {
+            return ensureLong(((Number)arg).doubleValue(), programPoint);
+        }
+        throw new UnwarrantedOptimismException(arg, programPoint);
+    }
+
+    /**
+     * Returns the argument value as a double. If the argument is not a Number object, throw an
+     * {@link UnwarrantedOptimismException}.This method is only public so that generated script code can use it. See
+     * {code CodeGenerator.ENSURE_NUMBER}.
+     * @param arg the original argument.
+     * @param programPoint the program point used in the exception
+     * @return the value of the argument as a double.
+     * @throws UnwarrantedOptimismException if the argument is not a Number that can be exactly represented as a long.
+     */
+    public static double ensureNumber(final Object arg, final int programPoint) {
+        if (arg instanceof Number) { // arg == null -> false
+            return ((Number)arg).doubleValue();
+        }
+        throw new UnwarrantedOptimismException(arg, programPoint);
+    }
+
+    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), OptimisticReturnFilters.class, name, MH.type(rtype, types));
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Property.java b/nashorn/src/jdk/nashorn/internal/runtime/Property.java
index b3f1e0a..4688682 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Property.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Property.java
@@ -31,9 +31,9 @@
 
 import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.SwitchPoint;
 import java.util.Objects;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
-import jdk.nashorn.internal.codegen.types.Type;
 
 /**
  * This is the abstract superclass representing a JavaScript Property.
@@ -65,42 +65,41 @@
     /** ECMA 8.6.1 - Is this property not configurable? */
     public static final int NOT_CONFIGURABLE = 1 << 2;
 
-    private static final int MODIFY_MASK     = (NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE);
-
-    /** Is this a spill property? See {@link AccessorProperty} */
-    public static final int IS_SPILL         = 1 << 3;
+    private static final int MODIFY_MASK     = NOT_WRITABLE | NOT_ENUMERABLE | NOT_CONFIGURABLE;
 
     /** Is this a function parameter? */
-    public static final int IS_PARAMETER     = 1 << 4;
+    public static final int IS_PARAMETER     = 1 << 3;
 
     /** Is parameter accessed thru arguments? */
-    public static final int HAS_ARGUMENTS    = 1 << 5;
-
-    /** Is this property always represented as an Object? See {@link ObjectClassGenerator} and dual fields flag. */
-    public static final int IS_ALWAYS_OBJECT = 1 << 6;
-
-    /** Can this property be primitive? */
-    public static final int CAN_BE_PRIMITIVE = 1 << 7;
-
-    /** Can this property be undefined? */
-    public static final int CAN_BE_UNDEFINED = 1 << 8;
+    public static final int HAS_ARGUMENTS    = 1 << 4;
 
     /** Is this a function declaration property ? */
-    public static final int IS_FUNCTION_DECLARATION = 1 << 9;
+    public static final int IS_FUNCTION_DECLARATION = 1 << 5;
+
+    /**
+     * Is this is a primitive field given to us by Nasgen, i.e.
+     * something we can be sure remains a constant whose type
+     * is narrower than object, e.g. Math.PI which is declared
+     * as a double
+     */
+    public static final int IS_NASGEN_PRIMITIVE = 1 << 6;
 
     /** Is this property bound to a receiver? This means get/set operations will be delegated to
      *  a statically defined object instead of the object passed as callsite parameter. */
-    public static final int IS_BOUND = 1 << 10;
+    public static final int IS_BOUND = 1 << 8;
 
     /** Property key. */
     private final String key;
 
     /** Property flags. */
-    protected int flags;
+    private int flags;
 
     /** Property field number or spill slot. */
     private final int slot;
 
+    /** SwitchPoint that is invalidated when property is changed, optional */
+    protected SwitchPoint changeCallback;
+
     private static final long serialVersionUID = 2099814273074501176L;
 
     /**
@@ -122,10 +121,11 @@
      *
      * @param property source property
      */
-    Property(final Property property) {
-        this.key   = property.key;
-        this.flags = property.flags;
-        this.slot  = property.slot;
+    Property(final Property property, final int flags) {
+        this.key            = property.key;
+        this.slot           = property.slot;
+        this.changeCallback = property.changeCallback;
+        this.flags          = flags;
     }
 
     /**
@@ -133,7 +133,15 @@
      *
      * @return cloned property
      */
-    abstract Property copy();
+    public abstract Property copy();
+
+    /**
+     * Copy function
+     *
+     * @param  newType new type
+     * @return cloned property with new type
+     */
+    public abstract Property copy(final Class<?> newType);
 
     /**
      * Property flag utility method for {@link PropertyDescriptor}s. Given two property descriptors,
@@ -166,6 +174,16 @@
     }
 
     /**
+     * Set the change callback for this property, i.e. a SwitchPoint
+     * that will be invalidated when the value of the property is
+     * changed
+     * @param sp SwitchPoint to use for change callback
+     */
+    public final void setChangeCallback(final SwitchPoint sp) {
+        this.changeCallback = sp;
+    }
+
+    /**
      * Property flag utility method for {@link PropertyDescriptor}. Get the property flags
      * conforming to any Property using this PropertyDescriptor
      *
@@ -255,7 +273,7 @@
      * @return true if spill property
      */
     public boolean isSpill() {
-        return (flags & IS_SPILL) == IS_SPILL;
+        return false;
     }
 
     /**
@@ -269,18 +287,6 @@
     }
 
     /**
-     * Does this property use any slots in the spill array described in
-     * {@link Property#isSpill}? In that case how many. Currently a property
-     * only uses max one spill slot, but this may change in future representations
-     * Only {@link AccessorProperty} instances use spill slots
-     *
-     * @return number of spill slots a property is using
-     */
-    public int getSpillCount() {
-        return isSpill() ? 1 : 0;
-    }
-
-    /**
      * Add more property flags to the property. Properties are immutable here,
      * so any property change that results in a larger flag set results in the
      * property being cloned. Use only the return value
@@ -298,6 +304,16 @@
     }
 
     /**
+     * Check if a flag is set for a property
+     * @param property property
+     * @param flag     flag to check
+     * @return true if flag is set
+     */
+    public static boolean checkFlag(final Property property, final int flag) {
+        return (property.getFlags() & flag) == flag;
+    }
+
+    /**
      * Get the flags for this property
      * @return property flags
      */
@@ -361,6 +377,14 @@
     public abstract MethodHandle getGetter(final Class<?> type);
 
     /**
+     * Get an optimistic getter that throws an exception if type is not the known given one
+     * @param type          type
+     * @param programPoint  program point
+     * @return getter
+     */
+    public abstract MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint);
+
+    /**
      * Hook to initialize method handles after deserialization.
      *
      * @param structure the structure class
@@ -384,6 +408,46 @@
     }
 
     /**
+     * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+     * getter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner of the property
+     * @return  the property value
+     */
+    public abstract int getIntValue(final ScriptObject self, final ScriptObject owner);
+
+    /**
+     * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+     * getter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner of the property
+     * @return  the property value
+     */
+    public abstract long getLongValue(final ScriptObject self, final ScriptObject owner);
+
+    /**
+     * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+     * getter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner of the property
+     * @return  the property value
+     */
+    public abstract double getDoubleValue(final ScriptObject self, final ScriptObject owner);
+
+    /**
+     * get the Object value of this property from {@code owner}. This allows to bypass creation of the
+     * getter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner of the property
+     * @return  the property value
+     */
+    public abstract Object getObjectValue(final ScriptObject self, final ScriptObject owner);
+
+    /**
      * Set the value of this property in {@code owner}. This allows to bypass creation of the
      * setter MethodHandle for spill and user accessor properties.
      *
@@ -392,17 +456,40 @@
      * @param value the new property value
      * @param strict is this a strict setter?
      */
-    public abstract void setObjectValue(ScriptObject self, ScriptObject owner, Object value, boolean strict);
+    public abstract void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict);
 
     /**
-     * Set the Object value of this property from {@code owner}. This allows to bypass creation of the
-     * getter MethodHandle for spill and user accessor properties.
+     * Set the value of this property in {@code owner}. This allows to bypass creation of the
+     * setter MethodHandle for spill and user accessor properties.
      *
      * @param self the this object
      * @param owner the owner object
-     * @return  the property value
+     * @param value the new property value
+     * @param strict is this a strict setter?
      */
-    public abstract Object getObjectValue(ScriptObject self, ScriptObject owner);
+    public abstract void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict);
+
+    /**
+     * Set the value of this property in {@code owner}. This allows to bypass creation of the
+     * setter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner object
+     * @param value the new property value
+     * @param strict is this a strict setter?
+     */
+    public abstract void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict);
+
+    /**
+     * Set the value of this property in {@code owner}. This allows to bypass creation of the
+     * setter MethodHandle for spill and user accessor properties.
+     *
+     * @param self the this object
+     * @param owner the owner object
+     * @param value the new property value
+     * @param strict is this a strict setter?
+     */
+    public abstract void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict);
 
     /**
      * Abstract method for retrieving the setter for the property. We do not know
@@ -466,30 +553,71 @@
 
         final Property otherProperty = (Property)other;
 
-        return getFlags()       == otherProperty.getFlags() &&
-               getSlot()        == otherProperty.getSlot() &&
-               getCurrentType() == otherProperty.getCurrentType() &&
-               getKey().equals(otherProperty.getKey());
+        return equalsWithoutType(otherProperty) &&
+               getCurrentType() == otherProperty.getCurrentType();
     }
 
+    boolean equalsWithoutType(final Property otherProperty) {
+        return getFlags() == otherProperty.getFlags() &&
+                getSlot() == otherProperty.getSlot() &&
+                getKey().equals(otherProperty.getKey());
+    }
+
+    private static final String type(final Class<?> type) {
+        if (type == null) {
+            return "undef";
+        } else if (type == int.class) {
+            return "i";
+        } else if (type == long.class) {
+            return "j";
+        } else if (type == double.class) {
+            return "d";
+        } else {
+            return "o";
+        }
+    }
+
+    /**
+     * Short toString version
+     * @return short toString
+     */
+    public final String toStringShort() {
+        final StringBuilder sb   = new StringBuilder();
+        final Class<?>      type = getCurrentType();
+        sb.append(getKey()).append(" (").append(type(type)).append(')');
+        return sb.toString();
+    }
+
+    private static String indent(final String str, final int indent) {
+        final StringBuilder sb = new StringBuilder();
+        sb.append(str);
+        for (int i = 0; i < indent - str.length(); i++) {
+            sb.append(' ');
+        }
+        return sb.toString();
+     }
+
     @Override
     public String toString() {
         final StringBuilder sb   = new StringBuilder();
         final Class<?>      type = getCurrentType();
 
-        sb.append(getKey()).
-            append("(0x").
-            append(Integer.toHexString(flags)).
+        sb.append(indent(getKey(), 20)).
+            append(" id=").
+            append(Debug.id(this)).
+            append(" (0x").
+            append(indent(Integer.toHexString(flags), 4)).
             append(") ").
             append(getClass().getSimpleName()).
             append(" {").
-            append(type == null ? "UNDEFINED" : Type.typeFor(type).getDescriptor()).
+            append(indent(type(type), 5)).
             append('}');
 
         if (slot != -1) {
-            sb.append('[');
-            sb.append(slot);
-            sb.append(']');
+            sb.append(" [").
+               append("slot=").
+               append(slot).
+               append(']');
         }
 
         return sb.toString();
@@ -503,9 +631,13 @@
      *
      * @return current type of property, null means undefined
      */
-    public Class<?> getCurrentType() {
-        return Object.class;
-    }
+    public abstract Class<?> getCurrentType();
+
+    /**
+     * Reset the current type of this property
+     * @param currentType new current type
+     */
+    public abstract void setCurrentType(final Class<?> currentType);
 
     /**
      * Check whether this Property can ever change its type. The default is false, and if
@@ -517,40 +649,6 @@
     }
 
     /**
-     * Check whether this Property is ever used as anything but an Object. If this is used only
-     * as an object, dual fields mode need not even try to represent it as a primitive at any
-     * callsite, saving map rewrites for performance.
-     *
-     * @return true if representation should always be an object field
-     */
-    public boolean isAlwaysObject() {
-        return (flags & IS_ALWAYS_OBJECT) == IS_ALWAYS_OBJECT;
-    }
-
-    /**
-     * Check whether this property can be primitive. This is a conservative
-     * analysis result, so {@code false} might mean that it can still be
-     * primitive
-     *
-     * @return can be primitive status
-     */
-    public boolean canBePrimitive() {
-        return (flags & CAN_BE_PRIMITIVE) == CAN_BE_PRIMITIVE;
-    }
-
-    /**
-     * Check whether this property can be primitive. This is a conservative
-     * analysis result, so {@code true} might mean that it can still be
-     * defined, but it will never say that a property can not be undefined
-     * if it can
-     *
-     * @return can be undefined status
-     */
-    public boolean canBeUndefined() {
-        return (flags & CAN_BE_UNDEFINED) == CAN_BE_UNDEFINED;
-    }
-
-    /**
      * Check whether this property represents a function declaration.
      * @return whether this property is a function declaration or not.
      */
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyAccess.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyAccess.java
index 165344c..6f09e99 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyAccess.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyAccess.java
@@ -38,86 +38,98 @@
     /**
      * Get the value for a given key and return it as an int
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public int getInt(Object key);
+    public int getInt(Object key, int programPoint);
 
     /**
      * Get the value for a given key and return it as an int
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public int getInt(double key);
+    public int getInt(double key, int programPoint);
 
     /**
      * Get the value for a given key and return it as an int
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public int getInt(final long key);
+    public int getInt(long key, int programPoint);
 
     /**
      * Get the value for a given key and return it as an int
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public int getInt(int key);
+    public int getInt(int key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a long
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public long getLong(Object key);
+    public long getLong(Object key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a long
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public long getLong(double key);
+    public long getLong(double key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a long
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public long getLong(long key);
+    public long getLong(long key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a long
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public long getLong(int key);
+    public long getLong(int key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a double
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public double getDouble(Object key);
+    public double getDouble(Object key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a double
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public double getDouble(double key);
+    public double getDouble(double key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a double
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public double getDouble(long key);
+    public double getDouble(long key, int programPoint);
 
     /**
      * Get the value for a given key and return it as a double
      * @param key the key
+     * @param programPoint or INVALID_PROGRAM_POINT if pessimistic
      * @return the value
      */
-    public double getDouble(int key);
+    public double getDouble(int key, int programPoint);
 
     /**
      * Get the value for a given key and return it as an Object
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
index f36bd45..e00759b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyDescriptor.java
@@ -154,8 +154,8 @@
 
     /**
      * Check existence and compare attributes of descriptors.
-     *
-     * @return true if every field of this desc exists in otherDesc and has the same value.
+     * @param otherDesc other descriptor to compare to
+     * @return true if every field of this descriptor exists in otherDesc and has the same value.
      */
     public boolean hasAndEquals(PropertyDescriptor otherDesc);
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
index bfa0692..ba64af3 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyHashMap.java
@@ -164,6 +164,19 @@
     }
 
     /**
+     * Clone a property map, replacing a property with a new one in the same place,
+     * which is important for property iterations if a property changes types
+     * @param property    old property
+     * @param newProperty new property
+     * @return new property map
+     */
+    public PropertyHashMap immutableReplace(final Property property, final Property newProperty) {
+        assert property.getKey().equals(newProperty.getKey()) : "replacing properties with different keys: '" + property.getKey() + "' != '" + newProperty.getKey() + "'";
+        assert findElement(property.getKey()) != null         : "replacing property that doesn't exist in map: '" + property.getKey() + "'";
+        return cloneMap().replaceNoClone(property.getKey(), newProperty);
+    }
+
+    /**
      * Clone a {@link PropertyHashMap} and add a {@link Property}.
      *
      * @param property {@link Property} to add.
@@ -289,7 +302,7 @@
      * @return The bin index.
      */
     private static int binIndex(final Element[] bins, final String key) {
-        return  key.hashCode() & (bins.length - 1);
+        return  key.hashCode() & bins.length - 1;
     }
 
     /**
@@ -301,7 +314,7 @@
      */
     private static int binsNeeded(final int n) {
         // 50% padding
-        return 1 << (32 - Integer.numberOfLeadingZeros((n + (n >>> 1)) | (INITIAL_BINS - 1)));
+        return 1 << 32 - Integer.numberOfLeadingZeros(n + (n >>> 1) | INITIAL_BINS - 1);
     }
 
     /**
@@ -327,8 +340,9 @@
         final Element[] newBins = new Element[binSize];
         for (Element element = list; element != null; element = element.getLink()) {
             final Property property = element.getProperty();
-            final String key = property.getKey();
-            final int binIndex = binIndex(newBins, key);
+            final String   key      = property.getKey();
+            final int      binIndex = binIndex(newBins, key);
+
             newBins[binIndex] = new Element(newBins[binIndex], property);
         }
         return newBins;
@@ -366,6 +380,11 @@
         return null;
     }
 
+
+    private PropertyHashMap cloneMap() {
+        return new PropertyHashMap(size, bins == null ? null : bins.clone(), list);
+    }
+
     /**
      * Clone {@link PropertyHashMap} to accommodate new size.
      *
@@ -385,6 +404,8 @@
         return new PropertyHashMap(newSize, newBins, list);
     }
 
+
+
     /**
      * Add a {@link Property} to a temporary {@link PropertyHashMap}, that has
      * been already cloned.  Removes duplicates if necessary.
@@ -416,6 +437,18 @@
         return new PropertyHashMap(newSize, bins, newList);
     }
 
+    private PropertyHashMap replaceNoClone(final String key, final Property property) {
+        if (bins != null) {
+            final int binIndex = binIndex(bins, key);
+            Element bin = bins[binIndex];
+            bin = replaceInList(bin, key, property);
+            bins[binIndex] = bin;
+        }
+        Element newList = list;
+        newList = replaceInList(newList, key, property);
+        return new PropertyHashMap(size, bins, newList);
+    }
+
     /**
      * Removes an {@link Element} from a specific list, avoiding duplication.
      *
@@ -446,6 +479,30 @@
         return list;
     }
 
+    // for element x. if x get link matches,
+    private static Element replaceInList(final Element list, final String key, final Property property) {
+        assert list != null;
+        final int hashCode = key.hashCode();
+
+        if (list.match(key, hashCode)) {
+            return new Element(list.getLink(), property);
+        }
+
+        final Element head = new Element(null, list.getProperty());
+        Element previous = head;
+        for (Element element = list.getLink(); element != null; element = element.getLink()) {
+            if (element.match(key, hashCode)) {
+                previous.setLink(new Element(element.getLink(), property));
+                return head;
+            }
+            final Element next = new Element(null, element.getProperty());
+            previous.setLink(next);
+            previous = next;
+        }
+        return list;
+    }
+
+
     /*
      * Map implementation
      */
@@ -617,6 +674,26 @@
             throw new UnsupportedOperationException("Immutable map.");
         }
 
+        @Override
+        public String toString() {
+            final StringBuffer sb = new StringBuffer();
+
+            sb.append('[');
+
+            Element elem = this;
+            do {
+                sb.append(elem.getValue());
+                elem = elem.link;
+                if (elem != null) {
+                    sb.append(" -> ");
+                }
+            } while (elem != null);
+
+            sb.append(']');
+
+            return sb.toString();
+        }
+
         /*
          * Accessors
          */
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java
index 532969c..03b2c93 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyListeners.java
@@ -111,7 +111,7 @@
         if (listeners == null) {
             return false;
         }
-        WeakPropertyMapSet set = listeners.get(key);
+        final WeakPropertyMapSet set = listeners.get(key);
         return set != null && set.contains(propertyMap);
     }
 
@@ -145,9 +145,9 @@
      */
     public synchronized void propertyAdded(final Property prop) {
         if (listeners != null) {
-            WeakPropertyMapSet set = listeners.get(prop.getKey());
+            final WeakPropertyMapSet set = listeners.get(prop.getKey());
             if (set != null) {
-                for (PropertyMap propertyMap : set.elements()) {
+                for (final PropertyMap propertyMap : set.elements()) {
                     propertyMap.propertyAdded(prop);
                 }
                 listeners.remove(prop.getKey());
@@ -162,9 +162,9 @@
      */
     public synchronized void propertyDeleted(final Property prop) {
         if (listeners != null) {
-            WeakPropertyMapSet set = listeners.get(prop.getKey());
+            final WeakPropertyMapSet set = listeners.get(prop.getKey());
             if (set != null) {
-                for (PropertyMap propertyMap : set.elements()) {
+                for (final PropertyMap propertyMap : set.elements()) {
                     propertyMap.propertyDeleted(prop);
                 }
                 listeners.remove(prop.getKey());
@@ -181,9 +181,9 @@
      */
     public synchronized void propertyModified(final Property oldProp, final Property newProp) {
         if (listeners != null) {
-            WeakPropertyMapSet set = listeners.get(oldProp.getKey());
+            final WeakPropertyMapSet set = listeners.get(oldProp.getKey());
             if (set != null) {
-                for (PropertyMap propertyMap : set.elements()) {
+                for (final PropertyMap propertyMap : set.elements()) {
                     propertyMap.propertyModified(oldProp, newProp);
                 }
                 listeners.remove(oldProp.getKey());
@@ -191,10 +191,13 @@
         }
     }
 
+    /**
+     * Callback for when a proto is changed
+     */
     public synchronized void protoChanged() {
         if (listeners != null) {
-            for (WeakPropertyMapSet set : listeners.values()) {
-                for (PropertyMap propertyMap : set.elements()) {
+            for (final WeakPropertyMapSet set : listeners.values()) {
+                for (final PropertyMap propertyMap : set.elements()) {
                     propertyMap.protoChanged();
                 }
             }
@@ -204,7 +207,7 @@
 
     private static class WeakPropertyMapSet {
 
-        private WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
+        private final WeakHashMap<PropertyMap, Boolean> map = new WeakHashMap<>();
 
         void add(final PropertyMap propertyMap) {
             map.put(propertyMap, Boolean.TRUE);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
index e2e07fd..0246b53 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/PropertyMap.java
@@ -36,6 +36,7 @@
 import java.lang.invoke.SwitchPoint;
 import java.lang.ref.SoftReference;
 import java.util.Arrays;
+import java.util.BitSet;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -68,7 +69,7 @@
     private int fieldCount;
 
     /** Number of fields available. */
-    private int fieldMaximum;
+    private final int fieldMaximum;
 
     /** Length of spill in use. */
     private int spillLength;
@@ -88,6 +89,8 @@
     /** property listeners */
     private transient PropertyListeners listeners;
 
+    private transient BitSet freeSlots;
+
     private static final long serialVersionUID = -7041836752008732533L;
 
     /**
@@ -129,6 +132,7 @@
         this.fieldMaximum = propertyMap.fieldMaximum;
         // We inherit the parent property listeners instance. It will be cloned when a new listener is added.
         this.listeners    = propertyMap.listeners;
+        this.freeSlots    = propertyMap.freeSlots;
 
         if (Context.DEBUG) {
             count++;
@@ -145,21 +149,6 @@
         this(propertyMap, propertyMap.properties);
     }
 
-    /**
-     * Duplicates this PropertyMap instance. This is used to duplicate 'shared'
-     * maps {@link PropertyMap} used as process wide singletons. Shared maps are
-     * duplicated for every global scope object. That way listeners, proto and property
-     * histories are scoped within a global scope.
-     *
-     * @return Duplicated {@link PropertyMap}.
-     */
-    public PropertyMap duplicate() {
-        if (Context.DEBUG) {
-            duplicatedCount++;
-        }
-        return new PropertyMap(this.properties, this.className, 0, 0, 0, containsArrayKeys());
-    }
-
     private void writeObject(final ObjectOutputStream out) throws IOException {
         out.defaultWriteObject();
         out.writeObject(properties.getProperties());
@@ -173,7 +162,7 @@
 
         assert className != null;
         final Class<?> structure = Context.forStructureClass(className);
-        for (Property prop : props) {
+        for (final Property prop : props) {
             prop.initMethodHandles(structure);
         }
     }
@@ -185,13 +174,14 @@
      * properties with keys that are valid array indices.</p>
      *
      * @param properties   Collection of initial properties.
+     * @param className    class name
      * @param fieldCount   Number of fields in use.
      * @param fieldMaximum Number of fields available.
      * @param spillLength  Number of used spill slots.
      * @return New {@link PropertyMap}.
      */
     public static PropertyMap newMap(final Collection<Property> properties, final String className, final int fieldCount, final int fieldMaximum,  final int spillLength) {
-        PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
+        final PropertyHashMap newProperties = EMPTY_HASHMAP.immutableAdd(properties);
         return new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength, false);
     }
 
@@ -205,7 +195,7 @@
      * @return New {@link PropertyMap}.
      */
     public static PropertyMap newMap(final Collection<Property> properties) {
-        return (properties == null || properties.isEmpty())? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
+        return properties == null || properties.isEmpty()? newMap() : newMap(properties, JO.class.getName(), 0, 0, 0);
     }
 
     /**
@@ -364,6 +354,51 @@
         return addPropertyNoHistory(new AccessorProperty(property, bindTo));
     }
 
+    // Get a logical slot index for a property, with spill slot 0 starting at fieldMaximum.
+    private int logicalSlotIndex(final Property property) {
+        final int slot = property.getSlot();
+        if (slot < 0) {
+            return -1;
+        }
+        return property.isSpill() ? slot + fieldMaximum : slot;
+    }
+
+    // Update boundaries and flags after a property has been added
+    private void updateFlagsAndBoundaries(final Property newProperty) {
+        if(newProperty.isSpill()) {
+            spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
+        } else {
+            fieldCount = Math.max(fieldCount, newProperty.getSlot() + 1);
+        }
+        if (isValidArrayIndex(getArrayIndex(newProperty.getKey()))) {
+            setContainsArrayKeys();
+        }
+    }
+
+    // Update the free slots bitmap for a property that has been deleted and/or added.
+    private void updateFreeSlots(final Property oldProperty, final Property newProperty) {
+        // Free slots bitset is possibly shared with parent map, so we must clone it before making modifications.
+        boolean freeSlotsCloned = false;
+        if (oldProperty != null) {
+            final int slotIndex = logicalSlotIndex(oldProperty);
+            if (slotIndex >= 0) {
+                final BitSet newFreeSlots = freeSlots == null ? new BitSet() : (BitSet)freeSlots.clone();
+                assert !newFreeSlots.get(slotIndex);
+                newFreeSlots.set(slotIndex);
+                freeSlots = newFreeSlots;
+                freeSlotsCloned = true;
+            }
+        }
+        if (freeSlots != null && newProperty != null) {
+            final int slotIndex = logicalSlotIndex(newProperty);
+            if (slotIndex > -1 && freeSlots.get(slotIndex)) {
+                final BitSet newFreeSlots = freeSlotsCloned ? freeSlots : ((BitSet)freeSlots.clone());
+                newFreeSlots.clear(slotIndex);
+                freeSlots = newFreeSlots.isEmpty() ? null : newFreeSlots;
+            }
+        }
+    }
+
     /**
      * Add a property to the map without adding it to the history. This should be used for properties that
      * can't be shared such as bound properties, or properties that are expected to be added only once.
@@ -377,15 +412,9 @@
         }
         final PropertyHashMap newProperties = properties.immutableAdd(property);
         final PropertyMap newMap = new PropertyMap(this, newProperties);
+        newMap.updateFlagsAndBoundaries(property);
+        newMap.updateFreeSlots(null, property);
 
-        if(!property.isSpill()) {
-            newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
-        }
-        if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
-            newMap.setContainsArrayKeys();
-        }
-
-        newMap.spillLength += property.getSpillCount();
         return newMap;
     }
 
@@ -406,15 +435,8 @@
             final PropertyHashMap newProperties = properties.immutableAdd(property);
             newMap = new PropertyMap(this, newProperties);
             addToHistory(property, newMap);
-
-            if(!property.isSpill()) {
-                newMap.fieldCount = Math.max(newMap.fieldCount, property.getSlot() + 1);
-            }
-            if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
-                newMap.setContainsArrayKeys();
-            }
-
-            newMap.spillLength += property.getSpillCount();
+            newMap.updateFlagsAndBoundaries(property);
+            newMap.updateFreeSlots(null, property);
         }
 
         return newMap;
@@ -436,7 +458,20 @@
 
         if (newMap == null && properties.containsKey(key)) {
             final PropertyHashMap newProperties = properties.immutableRemove(key);
-            newMap = new PropertyMap(this, newProperties);
+            final boolean isSpill = property.isSpill();
+            final int slot = property.getSlot();
+            // If deleted property was last field or spill slot we can make it reusable by reducing field/slot count.
+            // Otherwise mark it as free in free slots bitset.
+            if (isSpill && slot >= 0 && slot == spillLength - 1) {
+                newMap = new PropertyMap(newProperties, className, fieldCount, fieldMaximum, spillLength - 1, containsArrayKeys());
+                newMap.freeSlots = freeSlots;
+            } else if (!isSpill && slot >= 0 && slot == fieldCount - 1) {
+                newMap = new PropertyMap(newProperties, className, fieldCount - 1, fieldMaximum, spillLength, containsArrayKeys());
+                newMap.freeSlots = freeSlots;
+            } else {
+                newMap = new PropertyMap(this, newProperties);
+                newMap.updateFreeSlots(property, null);
+            }
             addToHistory(property, newMap);
         }
 
@@ -456,9 +491,8 @@
             listeners.propertyModified(oldProperty, newProperty);
         }
         // Add replaces existing property.
-        final PropertyHashMap newProperties = properties.immutableAdd(newProperty);
+        final PropertyHashMap newProperties = properties.immutableReplace(oldProperty, newProperty);
         final PropertyMap newMap = new PropertyMap(this, newProperties);
-
         /*
          * See ScriptObject.modifyProperty and ScriptObject.setUserAccessors methods.
          *
@@ -474,10 +508,11 @@
          * the old property is an AccessorProperty and the new one is a UserAccessorProperty property.
          */
 
-        final boolean sameType = (oldProperty.getClass() == newProperty.getClass());
+        final boolean sameType = oldProperty.getClass() == newProperty.getClass();
         assert sameType ||
-                (oldProperty instanceof AccessorProperty &&
-                newProperty instanceof UserAccessorProperty) : "arbitrary replaceProperty attempted";
+                oldProperty instanceof AccessorProperty &&
+                newProperty instanceof UserAccessorProperty :
+            "arbitrary replaceProperty attempted " + sameType + " oldProperty=" + oldProperty.getClass() + " newProperty=" + newProperty.getClass() + " [" + oldProperty.getCurrentType() + " => " + newProperty.getCurrentType() + "]";
 
         newMap.flags = flags;
 
@@ -485,7 +520,10 @@
          * spillLength remains same in case (1) and (2) because of slot reuse. Only for case (3), we need
          * to add spill count of the newly added UserAccessorProperty property.
          */
-        newMap.spillLength = spillLength + (sameType? 0 : newProperty.getSpillCount());
+        if (!sameType) {
+            newMap.spillLength = Math.max(spillLength, newProperty.getSlot() + 1);
+            newMap.updateFreeSlots(oldProperty, newProperty);
+        }
         return newMap;
     }
 
@@ -500,12 +538,7 @@
      * @return the newly created UserAccessorProperty
      */
     public UserAccessorProperty newUserAccessors(final String key, final int propertyFlags) {
-        int oldSpillLength = spillLength;
-
-        final int getterSlot = oldSpillLength++;
-        final int setterSlot = oldSpillLength++;
-
-        return new UserAccessorProperty(key, propertyFlags, getterSlot, setterSlot);
+        return new UserAccessorProperty(key, propertyFlags, getFreeSpillSlot());
     }
 
     /**
@@ -533,10 +566,11 @@
 
         final PropertyMap newMap = new PropertyMap(this, newProperties);
         for (final Property property : otherProperties) {
+            // This method is only safe to use with non-slotted, native getter/setter properties
+            assert property.getSlot() == -1;
             if (isValidArrayIndex(getArrayIndex(property.getKey()))) {
                 newMap.setContainsArrayKeys();
             }
-            newMap.spillLength += property.getSpillCount();
         }
 
         return newMap;
@@ -590,7 +624,7 @@
     PropertyMap freeze() {
         PropertyHashMap newProperties = EMPTY_HASHMAP;
 
-        for (Property oldProperty : properties.getProperties()) {
+        for (final Property oldProperty : properties.getProperties()) {
             int propertyFlags = Property.NOT_CONFIGURABLE;
 
             if (!(oldProperty instanceof UserAccessorProperty)) {
@@ -686,13 +720,11 @@
      * @param newMap   Modified {@link PropertyMap}.
      */
     private void addToHistory(final Property property, final PropertyMap newMap) {
-        if (!properties.isEmpty()) {
-            if (history == null) {
-                history = new WeakHashMap<>();
-            }
-
-            history.put(property, new SoftReference<>(newMap));
+        if (history == null) {
+            history = new WeakHashMap<>();
         }
+
+        history.put(property, new SoftReference<>(newMap));
     }
 
     /**
@@ -705,7 +737,7 @@
     private PropertyMap checkHistory(final Property property) {
 
         if (history != null) {
-            SoftReference<PropertyMap> ref = history.get(property);
+            final SoftReference<PropertyMap> ref = history.get(property);
             final PropertyMap historicMap = ref == null ? null : ref.get();
 
             if (historicMap != null) {
@@ -720,32 +752,44 @@
         return null;
     }
 
+    /**
+     * Returns true if the two maps have identical properties in the same order, but allows the properties to differ in
+     * their types. This method is mostly useful for tests.
+     * @param otherMap the other map
+     * @return true if this map has identical properties in the same order as the other map, allowing the properties to
+     * differ in type.
+     */
+    public boolean equalsWithoutType(final PropertyMap otherMap) {
+        if (properties.size() != otherMap.properties.size()) {
+            return false;
+        }
+
+        final Iterator<Property> iter      = properties.values().iterator();
+        final Iterator<Property> otherIter = otherMap.properties.values().iterator();
+
+        while (iter.hasNext() && otherIter.hasNext()) {
+            if (!iter.next().equalsWithoutType(otherIter.next())) {
+                return false;
+            }
+        }
+
+        return true;
+    }
+
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder();
 
-        sb.append(" [");
-        boolean isFirst = true;
+        sb.append(Debug.id(this));
+        sb.append(" = {\n");
 
-        for (final Property property : properties.values()) {
-            if (!isFirst) {
-                sb.append(", ");
-            }
-
-            isFirst = false;
-
-            sb.append(ScriptRuntime.safeToString(property.getKey()));
-            final Class<?> ctype = property.getCurrentType();
-            sb.append(" <").
-                append(property.getClass().getSimpleName()).
-                append(':').
-                append(ctype == null ?
-                    "undefined" :
-                    ctype.getSimpleName()).
-                append('>');
+        for (final Property property : getProperties()) {
+            sb.append('\t');
+            sb.append(property);
+            sb.append('\n');
         }
 
-        sb.append(']');
+        sb.append('}');
 
         return sb.toString();
     }
@@ -799,29 +843,37 @@
     boolean isFrozen() {
         return !isExtensible() && allFrozen();
     }
+
     /**
-     * Get the number of fields allocated for this {@link PropertyMap}.
+     * Return a free field slot for this map, or {@code -1} if none is available.
      *
-     * @return Number of fields allocated.
+     * @return free field slot or -1
      */
-    int getFieldCount() {
-        return fieldCount;
-    }
-    /**
-     * Get maximum number of fields available for this {@link PropertyMap}.
-     *
-     * @return Number of fields available.
-     */
-    int getFieldMaximum() {
-        return fieldMaximum;
+    int getFreeFieldSlot() {
+        if (freeSlots != null) {
+            final int freeSlot = freeSlots.nextSetBit(0);
+            if (freeSlot > -1 && freeSlot < fieldMaximum) {
+                return freeSlot;
+            }
+        }
+        if (fieldCount < fieldMaximum) {
+            return fieldCount;
+        }
+        return -1;
     }
 
     /**
-     * Get length of spill area associated with this {@link PropertyMap}.
+     * Get a free spill slot for this map.
      *
-     * @return Length of spill area.
+     * @return free spill slot
      */
-    int getSpillLength() {
+    int getFreeSpillSlot() {
+        if (freeSlots != null) {
+            final int freeSlot = freeSlots.nextSetBit(fieldMaximum);
+            if (freeSlot > -1) {
+                return freeSlot - fieldMaximum;
+            }
+        }
         return spillLength;
     }
 
@@ -908,10 +960,60 @@
      * Debugging and statistics.
      */
 
+    /**
+     * Debug helper function that returns the diff of two property maps, only
+     * displaying the information that is different and in which map it exists
+     * compared to the other map. Can be used to e.g. debug map guards and
+     * investigate why they fail, causing relink
+     *
+     * @param map0 the first property map
+     * @param map1 the second property map
+     *
+     * @return property map diff as string
+     */
+    public static String diff(final PropertyMap map0, final PropertyMap map1) {
+        final StringBuilder sb = new StringBuilder();
+
+        if (map0 != map1) {
+           sb.append(">>> START: Map diff");
+           boolean found = false;
+
+           for (final Property p : map0.getProperties()) {
+               final Property p2 = map1.findProperty(p.getKey());
+               if (p2 == null) {
+                   sb.append("FIRST ONLY : [" + p + "]");
+                   found = true;
+               } else if (p2 != p) {
+                   sb.append("DIFFERENT  : [" + p + "] != [" + p2 + "]");
+                   found = true;
+               }
+           }
+
+           for (final Property p2 : map1.getProperties()) {
+               final Property p1 = map0.findProperty(p2.getKey());
+               if (p1 == null) {
+                   sb.append("SECOND ONLY: [" + p2 + "]");
+                   found = true;
+               }
+           }
+
+           //assert found;
+
+           if (!found) {
+                sb.append(map0).
+                    append("!=").
+                    append(map1);
+           }
+
+           sb.append("<<< END: Map diff\n");
+        }
+
+        return sb.toString();
+    }
+
     // counters updated only in debug mode
     private static int count;
     private static int clonedCount;
-    private static int duplicatedCount;
     private static int historyHit;
     private static int protoInvalidations;
     private static int protoHistoryHit;
@@ -932,13 +1034,6 @@
     }
 
     /**
-     * @return The number of maps that are duplicated.
-     */
-    public static int getDuplicatedCount() {
-        return duplicatedCount;
-    }
-
-    /**
      * @return The number of times history was successfully used.
      */
     public static int getHistoryHit() {
@@ -965,5 +1060,4 @@
     public static int getSetProtoNewMapCount() {
         return setProtoNewMapCount;
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
index 9088544..c64f5ad 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RecompilableScriptFunctionData.java
@@ -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
@@ -27,24 +27,34 @@
 
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 
-import java.io.Serializable;
+import java.io.IOException;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.LinkedList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
 import jdk.internal.dynalink.support.NameCodec;
 import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.FunctionSignature;
+import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
+import jdk.nashorn.internal.codegen.TypeMap;
 import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.ir.FunctionNode;
-import jdk.nashorn.internal.ir.FunctionNode.CompilationState;
+import jdk.nashorn.internal.ir.LexicalContext;
+import jdk.nashorn.internal.ir.visitor.NodeVisitor;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.parser.Parser;
 import jdk.nashorn.internal.parser.Token;
 import jdk.nashorn.internal.parser.TokenType;
-import jdk.nashorn.internal.scripts.JS;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * This is a subclass that represents a script function that may be regenerated,
@@ -52,19 +62,21 @@
  * The common denominator is that it can get new invokers during its lifespan,
  * unlike {@code FinalScriptFunctionData}
  */
-public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Serializable {
+@Logger(name="recompile")
+public final class RecompilableScriptFunctionData extends ScriptFunctionData implements Loggable {
+    /** Prefix used for all recompiled script classes */
+    public static final String RECOMPILATION_PREFIX = "Recompilation$";
 
-    /** FunctionNode with the code for this ScriptFunction */
-    private transient FunctionNode functionNode;
+    /** Unique function node id for this function node */
+    private final int functionNodeId;
 
-    /** Source from which FunctionNode was parsed. */
-    private transient Source source;
+    private final String functionName;
 
     /** The line number where this function begins. */
     private final int lineNumber;
 
-    /** Allows us to retrieve the method handle for this function once the code is compiled */
-    private MethodLocator methodLocator;
+    /** Source from which FunctionNode was parsed. */
+    private transient Source source;
 
     /** Token of this function within the source. */
     private final long token;
@@ -81,49 +93,127 @@
     /** lazily generated allocator */
     private transient MethodHandle allocator;
 
+    private final Map<Integer, RecompilableScriptFunctionData> nestedFunctions;
+
+    /** Id to parent function if one exists */
+    private RecompilableScriptFunctionData parent;
+
+    private final boolean isDeclared;
+    private final boolean isAnonymous;
+    private final boolean needsCallee;
+
     private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
-    /**
-     * Used for specialization based on runtime arguments. Whenever we specialize on
-     * callsite parameter types at runtime, we need to use a parameter type guard to
-     * ensure that the specialized version of the script function continues to be
-     * applicable for a particular callsite.
-     */
-    private static final MethodHandle PARAM_TYPE_GUARD = findOwnMH("paramTypeGuard", boolean.class, Type[].class,  Object[].class);
+    private transient DebugLogger log;
 
-    /**
-     * It is usually a good gamble whever we detect a runtime callsite with a double
-     * (or java.lang.Number instance) to specialize the parameter to an integer, if the
-     * parameter in question can be represented as one. The double typically only exists
-     * because the compiler doesn't know any better than "a number type" and conservatively
-     * picks doubles when it can't prove that an integer addition wouldn't overflow.
-     */
-    private static final MethodHandle ENSURE_INT = findOwnMH("ensureInt", int.class, Object.class);
+    private final Map<String, Integer> externalScopeDepths;
+
+    private final Set<String> internalSymbols;
+
+    private static final int GET_SET_PREFIX_LENGTH = "*et ".length();
 
     private static final long serialVersionUID = 4914839316174633726L;
 
     /**
      * Constructor - public as scripts use it
      *
-     * @param functionNode       functionNode that represents this function code
-     * @param installer          installer for code regeneration versions of this function
-     * @param allocatorClassName name of our allocator class, will be looked up dynamically if used as a constructor
-     * @param allocatorMap       allocator map to seed instances with, when constructing
+     * @param functionNode        functionNode that represents this function code
+     * @param installer           installer for code regeneration versions of this function
+     * @param allocatorClassName  name of our allocator class, will be looked up dynamically if used as a constructor
+     * @param allocatorMap        allocator map to seed instances with, when constructing
+     * @param nestedFunctions     nested function map
+     * @param externalScopeDepths external scope depths
+     * @param internalSymbols     internal symbols to method, defined in its scope
      */
-    public RecompilableScriptFunctionData(final FunctionNode functionNode, final CodeInstaller<ScriptEnvironment> installer, final String allocatorClassName, final PropertyMap allocatorMap) {
+    public RecompilableScriptFunctionData(
+        final FunctionNode functionNode,
+        final CodeInstaller<ScriptEnvironment> installer,
+        final String allocatorClassName,
+        final PropertyMap allocatorMap,
+        final Map<Integer, RecompilableScriptFunctionData> nestedFunctions,
+        final Map<String, Integer> externalScopeDepths,
+        final Set<String> internalSymbols) {
+
         super(functionName(functionNode),
-              functionNode.getParameters().size(),
+              Math.min(functionNode.getParameters().size(), MAX_ARITY),
               getFlags(functionNode));
-        this.functionNode       = functionNode;
-        this.source             = functionNode.getSource();
-        this.lineNumber         = functionNode.getLineNumber();
-        this.token              = tokenFor(functionNode);
-        this.installer          = installer;
-        this.allocatorClassName = allocatorClassName;
-        this.allocatorMap       = allocatorMap;
-        if (!functionNode.isLazy()) {
-            methodLocator = new MethodLocator(functionNode);
+
+        this.functionName        = functionNode.getName();
+        this.lineNumber          = functionNode.getLineNumber();
+        this.isDeclared          = functionNode.isDeclared();
+        this.needsCallee         = functionNode.needsCallee();
+        this.isAnonymous         = functionNode.isAnonymous();
+        this.functionNodeId      = functionNode.getId();
+        this.source              = functionNode.getSource();
+        this.token               = tokenFor(functionNode);
+        this.installer           = installer;
+        this.allocatorClassName  = allocatorClassName;
+        this.allocatorMap        = allocatorMap;
+        this.nestedFunctions     = nestedFunctions;
+        this.externalScopeDepths = externalScopeDepths;
+        this.internalSymbols     = new HashSet<>(internalSymbols);
+
+        for (final RecompilableScriptFunctionData nfn : nestedFunctions.values()) {
+            assert nfn.getParent() == null;
+            nfn.setParent(this);
         }
+
+        createLogger();
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context ctxt) {
+        return ctxt.getLogger(this.getClass());
+    }
+
+    /**
+     * Check if a symbol is internally defined in a function. For example
+     * if "undefined" is internally defined in the outermost program function,
+     * it has not been reassigned or overridden and can be optimized
+     *
+     * @param symbolName symbol name
+     * @return true if symbol is internal to this ScriptFunction
+     */
+
+    public boolean hasInternalSymbol(final String symbolName) {
+        return internalSymbols.contains(symbolName);
+    }
+
+    /**
+     * Return the external symbol table
+     * @param symbolName symbol name
+     * @return the external symbol table with proto depths
+     */
+    public int getExternalSymbolDepth(final String symbolName) {
+        final Map<String, Integer> map = externalScopeDepths;
+        if (map == null) {
+            return -1;
+        }
+        final Integer depth = map.get(symbolName);
+        if (depth == null) {
+            return -1;
+        }
+        return depth;
+    }
+
+    /**
+     * Get the parent of this RecompilableScriptFunctionData. If we are
+     * a nested function, we have a parent. Note that "null" return value
+     * can also mean that we have a parent but it is unknown, so this can
+     * only be used for conservative assumptions.
+     * @return parent data, or null if non exists and also null IF UNKNOWN.
+     */
+    public RecompilableScriptFunctionData getParent() {
+       return parent;
+    }
+
+    void setParent(final RecompilableScriptFunctionData parent) {
+        this.parent = parent;
     }
 
     @Override
@@ -135,41 +225,70 @@
         return "function " + (name == null ? "" : name) + "() { [native code] }";
     }
 
-    public void setCodeAndSource(final Map<String, Class<?>> code, final Source source) {
-        this.source = source;
-        if (methodLocator != null) {
-            methodLocator.setClass(code.get(methodLocator.getClassName()));
+    /**
+     * Initialize transient fields on deserialized instances
+     *
+     * @param src source
+     * @param inst code installer
+     */
+    public void initTransients(final Source src, final CodeInstaller<ScriptEnvironment> inst) {
+        if (this.source == null && this.installer == null) {
+            this.source    = src;
+            this.installer = inst;
+        } else if (this.source != src || this.installer != inst) {
+            // Existing values must be same as those passed as parameters
+            throw new IllegalArgumentException();
         }
     }
 
     @Override
     public String toString() {
+        return super.toString() + '@' + functionNodeId;
+    }
+
+    @Override
+    public String toStringVerbose() {
         final StringBuilder sb = new StringBuilder();
 
+        sb.append("fnId=").append(functionNodeId).append(' ');
+
         if (source != null) {
-            sb.append(source.getName()).append(':').append(lineNumber).append(' ');
+            sb.append(source.getName())
+                .append(':')
+                .append(lineNumber)
+                .append(' ');
         }
 
         return sb.toString() + super.toString();
     }
 
+    @Override
+    public String getFunctionName() {
+        return functionName;
+    }
+
+    @Override
+    public boolean inDynamicContext() {
+        return (flags & IN_DYNAMIC_CONTEXT) != 0;
+    }
+
     private static String functionName(final FunctionNode fn) {
         if (fn.isAnonymous()) {
             return "";
-        } else {
-            final FunctionNode.Kind kind = fn.getKind();
-            if (kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
-                final String name = NameCodec.decode(fn.getIdent().getName());
-                return name.substring(4); // 4 is "get " or "set "
-            } else {
-                return fn.getIdent().getName();
-            }
         }
+        final FunctionNode.Kind kind = fn.getKind();
+        if (kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) {
+            final String name = NameCodec.decode(fn.getIdent().getName());
+            return name.substring(GET_SET_PREFIX_LENGTH);
+        }
+        return fn.getIdent().getName();
     }
 
     private static long tokenFor(final FunctionNode fn) {
-        final int  position   = Token.descPosition(fn.getFirstToken());
-        final int  length     = Token.descPosition(fn.getLastToken()) - position + Token.descLength(fn.getLastToken());
+        final int  position  = Token.descPosition(fn.getFirstToken());
+        final long lastToken = Token.withDelimiter(fn.getLastToken());
+        // EOL uses length field to store the line number
+        final int  length    = Token.descPosition(lastToken) - position + (Token.descType(lastToken) == TokenType.EOL ? 0 : Token.descLength(lastToken));
 
         return Token.toDesc(TokenType.FUNCTION, position, length);
     }
@@ -185,10 +304,21 @@
         if (functionNode.usesThis() || functionNode.hasEval()) {
             flags |= USES_THIS;
         }
+        if (functionNode.isVarArg()) {
+            flags |= IS_VARIABLE_ARITY;
+        }
+        if (functionNode.inDynamicContext()) {
+            flags |= IN_DYNAMIC_CONTEXT;
+        }
         return flags;
     }
 
     @Override
+    PropertyMap getAllocatorMap() {
+        return allocatorMap;
+    }
+
+    @Override
     ScriptObject allocate(final PropertyMap map) {
         try {
             ensureHasAllocator(); //if allocatorClass name is set to null (e.g. for bound functions) we don't even try
@@ -206,306 +336,433 @@
         }
     }
 
-    @Override
-    PropertyMap getAllocatorMap() {
-        return allocatorMap;
-    }
+    FunctionNode reparse() {
+        final boolean isProgram = functionNodeId == FunctionNode.FIRST_FUNCTION_ID;
+        // NOTE: If we aren't recompiling the top-level program, we decrease functionNodeId 'cause we'll have a synthetic program node
+        final int descPosition = Token.descPosition(token);
+        final Context context = Context.getContextTrusted();
+        final Parser parser = new Parser(
+            context.getEnv(),
+            source,
+            new Context.ThrowErrorManager(),
+            isStrict(),
+            functionNodeId - (isProgram ? 0 : 1),
+            lineNumber - 1,
+            context.getLogger(Parser.class)); // source starts at line 0, so even though lineNumber is the correct declaration line, back off one to make it exclusive
 
-
-    @Override
-    protected void ensureCompiled() {
-        if (functionNode != null && functionNode.isLazy()) {
-            Compiler.LOG.info("Trampoline hit: need to do lazy compilation of '", functionNode.getName(), "'");
-            final Compiler compiler = new Compiler(installer);
-            functionNode = compiler.compile(functionNode);
-            assert !functionNode.isLazy();
-            compiler.install(functionNode);
-            methodLocator = new MethodLocator(functionNode);
-            flags = getFlags(functionNode);
+        if (isAnonymous) {
+            parser.setFunctionName(functionName);
         }
 
-        if (functionNode != null) {
-            methodLocator.setClass(functionNode.getCompileUnit().getCode());
-        }
+        final FunctionNode program = parser.parse(CompilerConstants.PROGRAM.symbolName(), descPosition, Token.descLength(token), true);
+        // Parser generates a program AST even if we're recompiling a single function, so when we are only recompiling a
+        // single function, extract it from the program.
+        return (isProgram ? program : extractFunctionFromScript(program)).setName(null, functionName);
     }
 
-    @Override
-    protected synchronized void ensureCodeGenerated() {
-        if (!code.isEmpty()) {
-            return; // nothing to do, we have code, at least some.
+    TypeMap typeMap(final MethodType fnCallSiteType) {
+        if (fnCallSiteType == null) {
+            return null;
         }
 
-        ensureCompiled();
-
-        /*
-         * We can't get to this program point unless we have bytecode, either from
-         * eager compilation or from running a lazy compile on the lines above
-         */
-
-        assert functionNode == null || functionNode.hasState(CompilationState.EMITTED) :
-                    functionNode.getName() + " " + functionNode.getState() + " " + Debug.id(functionNode);
-
-        // code exists - look it up and add it into the automatically sorted invoker list
-        addCode(functionNode);
-
-        if (functionNode != null && !functionNode.canSpecialize()) {
-            // allow GC to claim IR stuff that is not needed anymore
-            functionNode = null;
-            installer = null;
+        if (CompiledFunction.isVarArgsType(fnCallSiteType)) {
+            return null;
         }
+
+        return new TypeMap(functionNodeId, explicitParams(fnCallSiteType), needsCallee());
     }
 
-    private MethodHandle addCode(final FunctionNode fn) {
-        return addCode(fn, null, null, null);
+    private static ScriptObject newLocals(final ScriptObject runtimeScope) {
+        final ScriptObject locals = Global.newEmptyInstance();
+        locals.setProto(runtimeScope);
+        return locals;
     }
 
-    private MethodHandle addCode(final FunctionNode fn, final MethodType runtimeType, final MethodHandle guard, final MethodHandle fallback) {
-        assert methodLocator != null;
-        MethodHandle target = methodLocator.getMethodHandle();
-        final MethodType targetType = methodLocator.getMethodType();
+    private Compiler getCompiler(final FunctionNode fn, final MethodType actualCallSiteType, final ScriptObject runtimeScope) {
+        return getCompiler(fn, actualCallSiteType, newLocals(runtimeScope), null, null);
+    }
 
-        /*
-         * For any integer argument. a double that is representable as an integer is OK.
-         * otherwise the guard would have failed. in that case introduce a filter that
-         * casts the double to an integer, which we know will preserve all precision.
-         */
-        for (int i = 0; i < targetType.parameterCount(); i++) {
-            if (targetType.parameterType(i) == int.class) {
-                //representable as int
-                target = MH.filterArguments(target, i, ENSURE_INT);
+    Compiler getCompiler(final FunctionNode functionNode, final MethodType actualCallSiteType,
+            final ScriptObject runtimeScope, final Map<Integer, Type> invalidatedProgramPoints,
+            final int[] continuationEntryPoints) {
+        final TypeMap typeMap = typeMap(actualCallSiteType);
+        final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
+        final Object typeInformationFile = OptimisticTypesPersistence.getLocationDescriptor(source, functionNodeId, paramTypes);
+        final Context context = Context.getContextTrusted();
+        return new Compiler(
+                context,
+                context.getEnv(),
+                installer,
+                functionNode.getSource(),  // source
+                isStrict() | functionNode.isStrict(), // is strict
+                true,       // is on demand
+                this,       // compiledFunction, i.e. this RecompilableScriptFunctionData
+                typeMap,    // type map
+                getEffectiveInvalidatedProgramPoints(invalidatedProgramPoints, typeInformationFile), // invalidated program points
+                typeInformationFile,
+                continuationEntryPoints, // continuation entry points
+                runtimeScope); // runtime scope
+    }
+
+    /**
+     * If the function being compiled already has its own invalidated program points map, use it. Otherwise, attempt to
+     * load invalidated program points map from the persistent type info cache.
+     * @param invalidatedProgramPoints the function's current invalidated program points map. Null if the function
+     * doesn't have it.
+     * @param typeInformationFile the object describing the location of the persisted type information.
+     * @return either the existing map, or a loaded map from the persistent type info cache, or a new empty map if
+     * neither an existing map or a persistent cached type info is available.
+     */
+    private static Map<Integer, Type> getEffectiveInvalidatedProgramPoints(
+            final Map<Integer, Type> invalidatedProgramPoints, final Object typeInformationFile) {
+        if(invalidatedProgramPoints != null) {
+            return invalidatedProgramPoints;
+        }
+        final Map<Integer, Type> loadedProgramPoints = OptimisticTypesPersistence.load(typeInformationFile);
+        return loadedProgramPoints != null ? loadedProgramPoints : new TreeMap<Integer, Type>();
+    }
+
+    private FunctionInitializer compileTypeSpecialization(final MethodType actualCallSiteType, final ScriptObject runtimeScope, final boolean persist) {
+        // We're creating an empty script object for holding local variables. AssignSymbols will populate it with
+        // explicit Undefined values for undefined local variables (see AssignSymbols#defineSymbol() and
+        // CompilationEnvironment#declareLocalSymbol()).
+
+        if (log.isEnabled()) {
+            log.info("Type specialization of '", functionName, "' signature: ", actualCallSiteType);
+        }
+
+        final boolean persistentCache = usePersistentCodeCache() && persist;
+        String cacheKey = null;
+        if (persistentCache) {
+            final TypeMap typeMap = typeMap(actualCallSiteType);
+            final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
+            cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
+            final StoredScript script = installer.loadScript(source, cacheKey);
+
+            if (script != null) {
+                Compiler.updateCompilationId(script.getCompilationId());
+                return install(script);
             }
         }
 
-        MethodHandle mh = target;
-        if (guard != null) {
-            mh = MH.guardWithTest(MH.asCollector(guard, Object[].class, target.type().parameterCount()), MH.asType(target, fallback.type()), fallback);
+        final FunctionNode fn = reparse();
+        final Compiler compiler = getCompiler(fn, actualCallSiteType, runtimeScope);
+        final FunctionNode compiledFn = compiler.compile(fn, CompilationPhases.COMPILE_ALL);
+
+        if (persist && !compiledFn.getFlag(FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION)) {
+            compiler.persistClassInfo(cacheKey, compiledFn);
         }
-
-        final CompiledFunction cf = new CompiledFunction(runtimeType == null ? targetType : runtimeType, mh);
-        code.add(cf);
-
-        return cf.getInvoker();
+        return new FunctionInitializer(compiledFn, compiler.getInvalidatedProgramPoints());
     }
 
-    private static Type runtimeType(final Object arg) {
-        if (arg == null) {
-            return Type.OBJECT;
+
+    /**
+     * Install this script using the given {@code installer}.
+     *
+     * @param script the compiled script
+     * @return the function initializer
+     */
+    private FunctionInitializer install(final StoredScript script) {
+
+        final Map<String, Class<?>> installedClasses = new HashMap<>();
+        final String   mainClassName   = script.getMainClassName();
+        final byte[]   mainClassBytes  = script.getClassBytes().get(mainClassName);
+
+        final Class<?> mainClass       = installer.install(mainClassName, mainClassBytes);
+
+        installedClasses.put(mainClassName, mainClass);
+
+        for (final Map.Entry<String, byte[]> entry : script.getClassBytes().entrySet()) {
+            final String className = entry.getKey();
+            final byte[] code = entry.getValue();
+
+            if (className.equals(mainClassName)) {
+                continue;
+            }
+
+            installedClasses.put(className, installer.install(className, code));
         }
 
-        final Class<?> clazz = arg.getClass();
-        assert !clazz.isPrimitive() : "always boxed";
-        if (clazz == Double.class) {
-            return JSType.isRepresentableAsInt((double)arg) ? Type.INT : Type.NUMBER;
-        } else if (clazz == Integer.class) {
-            return Type.INT;
-        } else if (clazz == Long.class) {
-            return Type.LONG;
-        } else if (clazz == String.class) {
-            return Type.STRING;
+        final Map<Integer, FunctionInitializer> initializers = script.getInitializers();
+        assert initializers != null;
+        assert initializers.size() == 1;
+        final FunctionInitializer initializer = initializers.values().iterator().next();
+
+        final Object[] constants = script.getConstants();
+        for (int i = 0; i < constants.length; i++) {
+            if (constants[i] instanceof RecompilableScriptFunctionData) {
+                // replace deserialized function data with the ones we already have
+                constants[i] = getScriptFunctionData(((RecompilableScriptFunctionData) constants[i]).getFunctionNodeId());
+            }
         }
-        return Type.OBJECT;
+
+        installer.initialize(installedClasses.values(), source, constants);
+        initializer.setCode(installedClasses.get(initializer.getClassName()));
+        return initializer;
     }
 
-    private static boolean canCoerce(final Object arg, final Type type) {
-        Type argType = runtimeType(arg);
-        if (Type.widest(argType, type) == type || arg == ScriptRuntime.UNDEFINED) {
-            return true;
-        }
-        System.err.println(arg + " does not fit in "+ argType + " " + type + " " + arg.getClass());
-        new Throwable().printStackTrace();
-        return false;
+    boolean usePersistentCodeCache() {
+        final ScriptEnvironment env = installer.getOwner();
+        return env._persistent_cache && env._optimistic_types;
     }
 
-    @SuppressWarnings("unused")
-    private static boolean paramTypeGuard(final Type[] paramTypes, final Object... args) {
-        final int length = args.length;
-        assert args.length >= paramTypes.length;
+    private MethodType explicitParams(final MethodType callSiteType) {
+        if (CompiledFunction.isVarArgsType(callSiteType)) {
+            return null;
+        }
 
-        //i==start, skip the this, callee params etc
-        int start = args.length - paramTypes.length;
-        for (int i = start; i < args.length; i++) {
-            final Object arg = args[i];
-            if (!canCoerce(arg, paramTypes[i - start])) {
+        final MethodType noCalleeThisType = callSiteType.dropParameterTypes(0, 2); // (callee, this) is always in call site type
+        final int callSiteParamCount = noCalleeThisType.parameterCount();
+
+        // Widen parameters of reference types to Object as we currently don't care for specialization among reference
+        // types. E.g. call site saying (ScriptFunction, Object, String) should still link to (ScriptFunction, Object, Object)
+        final Class<?>[] paramTypes = noCalleeThisType.parameterArray();
+        boolean changed = false;
+        for (int i = 0; i < paramTypes.length; ++i) {
+            final Class<?> paramType = paramTypes[i];
+            if (!(paramType.isPrimitive() || paramType == Object.class)) {
+                paramTypes[i] = Object.class;
+                changed = true;
+            }
+        }
+        final MethodType generalized = changed ? MethodType.methodType(noCalleeThisType.returnType(), paramTypes) : noCalleeThisType;
+
+        if (callSiteParamCount < getArity()) {
+            return generalized.appendParameterTypes(Collections.<Class<?>>nCopies(getArity() - callSiteParamCount, Object.class));
+        }
+        return generalized;
+    }
+
+    private FunctionNode extractFunctionFromScript(final FunctionNode script) {
+        final Set<FunctionNode> fns = new HashSet<>();
+        script.getBody().accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
+            @Override
+            public boolean enterFunctionNode(final FunctionNode fn) {
+                fns.add(fn);
                 return false;
             }
+        });
+        assert fns.size() == 1 : "got back more than one method in recompilation";
+        final FunctionNode f = fns.iterator().next();
+        assert f.getId() == functionNodeId;
+        if (!isDeclared && f.isDeclared()) {
+            return f.clearFlag(null, FunctionNode.IS_DECLARED);
         }
+        return f;
+    }
+
+    MethodHandle lookup(final FunctionInitializer fnInit) {
+        final MethodType type = fnInit.getMethodType();
+        return lookupCodeMethod(fnInit.getCode(), type);
+    }
+
+    MethodHandle lookup(final FunctionNode fn) {
+        final MethodType type = new FunctionSignature(fn).getMethodType();
+        return lookupCodeMethod(fn.getCompileUnit().getCode(), type);
+    }
+
+    MethodHandle lookupCodeMethod(final Class<?> code, final MethodType targetType) {
+        log.info("Looking up ", DebugLogger.quote(name), " type=", targetType);
+        return MH.findStatic(LOOKUP, code, functionName, targetType);
+    }
+
+    /**
+     * Initializes this function data with the eagerly generated version of the code. This method can only be invoked
+     * by the compiler internals in Nashorn and is public for implementation reasons only. Attempting to invoke it
+     * externally will result in an exception.
+     */
+    public void initializeCode(final FunctionInitializer initializer) {
+        // Since the method is public, we double-check that we aren't invoked with an inappropriate compile unit.
+        if(!code.isEmpty()) {
+            throw new IllegalStateException(name);
+        }
+        addCode(lookup(initializer), null, null, initializer.getFlags());
+    }
+
+    private CompiledFunction addCode(final MethodHandle target, final Map<Integer, Type> invalidatedProgramPoints,
+                                     final MethodType callSiteType, final int fnFlags) {
+        final CompiledFunction cfn = new CompiledFunction(target, this, invalidatedProgramPoints, callSiteType, fnFlags);
+        code.add(cfn);
+        return cfn;
+    }
+
+    /**
+     * Add code with specific call site type. It will adapt the type of the looked up method handle to fit the call site
+     * type. This is necessary because even if we request a specialization that takes an "int" parameter, we might end
+     * up getting one that takes a "double" etc. because of internal function logic causes widening (e.g. assignment of
+     * a wider value to the parameter variable). However, we use the method handle type for matching subsequent lookups
+     * for the same specialization, so we must adapt the handle to the expected type.
+     * @param fnInit the function
+     * @param callSiteType the call site type
+     * @return the compiled function object, with its type matching that of the call site type.
+     */
+    private CompiledFunction addCode(final FunctionInitializer fnInit, final MethodType callSiteType) {
+        if (isVariableArity()) {
+            return addCode(lookup(fnInit), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
+        }
+
+        final MethodHandle handle = lookup(fnInit);
+        final MethodType fromType = handle.type();
+        MethodType toType = needsCallee(fromType) ? callSiteType.changeParameterType(0, ScriptFunction.class) : callSiteType.dropParameterTypes(0, 1);
+        toType = toType.changeReturnType(fromType.returnType());
+
+        final int toCount = toType.parameterCount();
+        final int fromCount = fromType.parameterCount();
+        final int minCount = Math.min(fromCount, toCount);
+        for(int i = 0; i < minCount; ++i) {
+            final Class<?> fromParam = fromType.parameterType(i);
+            final Class<?>   toParam =   toType.parameterType(i);
+            // If method has an Object parameter, but call site had String, preserve it as Object. No need to narrow it
+            // artificially. Note that this is related to how CompiledFunction.matchesCallSite() works, specifically
+            // the fact that various reference types compare to equal (see "fnType.isEquivalentTo(csType)" there).
+            if (fromParam != toParam && !fromParam.isPrimitive() && !toParam.isPrimitive()) {
+                assert fromParam.isAssignableFrom(toParam);
+                toType = toType.changeParameterType(i, fromParam);
+            }
+        }
+        if (fromCount > toCount) {
+            toType = toType.appendParameterTypes(fromType.parameterList().subList(toCount, fromCount));
+        } else if (fromCount < toCount) {
+            toType = toType.dropParameterTypes(fromCount, toCount);
+        }
+
+        return addCode(lookup(fnInit).asType(toType), fnInit.getInvalidatedProgramPoints(), callSiteType, fnInit.getFlags());
+    }
+
+
+    @Override
+    synchronized CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope) {
+        CompiledFunction existingBest = super.getBest(callSiteType, runtimeScope);
+        if (existingBest == null) {
+            existingBest = addCode(compileTypeSpecialization(callSiteType, runtimeScope, true), callSiteType);
+        }
+
+        assert existingBest != null;
+        //we are calling a vararg method with real args
+        boolean applyToCall = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
+
+        //if the best one is an apply to call, it has to match the callsite exactly
+        //or we need to regenerate
+        if (existingBest.isApplyToCall()) {
+            final CompiledFunction best = lookupExactApplyToCall(callSiteType);
+            if (best != null) {
+                return best;
+            }
+            applyToCall = true;
+        }
+
+        if (applyToCall) {
+            final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false);
+            if ((fnInit.getFlags() & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0) { //did the specialization work
+                existingBest = addCode(fnInit, callSiteType);
+            }
+        }
+
+        return existingBest;
+    }
+
+    @Override
+    boolean isRecompilable() {
         return true;
     }
 
-    @SuppressWarnings("unused")
-    private static int ensureInt(final Object arg) {
-        if (arg instanceof Number) {
-            return ((Number)arg).intValue();
-        } else if (arg instanceof Undefined) {
-            return 0;
-        }
-        throw new AssertionError(arg);
-    }
-
-    /**
-     * Given the runtime callsite args, compute a method type that is equivalent to what
-     * was passed - this is typically a lot more specific that what the compiler has been
-     * able to deduce
-     * @param callSiteType callsite type for the compiled callsite target
-     * @param args runtime arguments to the compiled callsite target
-     * @return adjusted method type, narrowed as to conform to runtime callsite type instead
-     */
-    private static MethodType runtimeType(final MethodType callSiteType, final Object[] args) {
-        if (args == null) {
-            //for example bound, or otherwise runtime arguments to callsite unavailable, then
-            //do not change the type
-            return callSiteType;
-        }
-        final Class<?>[] paramTypes = new Class<?>[callSiteType.parameterCount()];
-        final int        start      = args.length - callSiteType.parameterCount();
-        for (int i = start; i < args.length; i++) {
-            paramTypes[i - start] = runtimeType(args[i]).getTypeClass();
-        }
-        return MH.type(callSiteType.returnType(), paramTypes);
-    }
-
-    private static ArrayList<Type> runtimeType(final MethodType mt) {
-        final ArrayList<Type> type = new ArrayList<>();
-        for (int i = 0; i < mt.parameterCount(); i++) {
-            type.add(Type.typeFor(mt.parameterType(i)));
-        }
-        return type;
+    @Override
+    public boolean needsCallee() {
+        return needsCallee;
     }
 
     @Override
-    synchronized MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
-        final MethodType runtimeType = runtimeType(callSiteType, args);
-        assert runtimeType.parameterCount() == callSiteType.parameterCount();
-
-        final MethodHandle mh = super.getBestInvoker(runtimeType, args);
-
-        /*
-         * Not all functions can be specialized, for example, if we deemed memory
-         * footprint too large to store a parse snapshot, or if it is meaningless
-         * to do so, such as e.g. for runScript
-         */
-        if (functionNode == null || !functionNode.canSpecialize()) {
-            return mh;
+    MethodType getGenericType() {
+        // 2 is for (callee, this)
+        if (isVariableArity()) {
+            return MethodType.genericMethodType(2, true);
         }
-
-        /*
-         * Check if best invoker is equally specific or more specific than runtime
-         * type. In that case, we don't need further specialization, but can use
-         * whatever we have already. We know that it will match callSiteType, or it
-         * would not have been returned from getBestInvoker
-         */
-        if (!code.isLessSpecificThan(runtimeType)) {
-            return mh;
-        }
-
-        int i;
-        final FunctionNode snapshot = functionNode.getSnapshot();
-        assert snapshot != null;
-
-        /*
-         * Create a list of the arg types that the compiler knows about
-         * typically, the runtime args are a lot more specific, and we should aggressively
-         * try to use those whenever possible
-         * We WILL try to make an aggressive guess as possible, and add guards if needed.
-         * For example, if the compiler can deduce that we have a number type, but the runtime
-         * passes and int, we might still want to keep it an int, and the gamble to
-         * check that whatever is passed is int representable usually pays off
-         * If the compiler only knows that a parameter is an "Object", it is still worth
-         * it to try to specialize it by looking at the runtime arg.
-         */
-        final LinkedList<Type> compileTimeArgs = new LinkedList<>();
-        for (i = callSiteType.parameterCount() - 1; i >= 0 && compileTimeArgs.size() < snapshot.getParameters().size(); i--) {
-            compileTimeArgs.addFirst(Type.typeFor(callSiteType.parameterType(i)));
-        }
-
-        /*
-         * The classes known at compile time are a safe to generate as primitives without parameter guards
-         * But the classes known at runtime (if more specific than compile time types) are safe to generate as primitives
-         * IFF there are parameter guards
-         */
-        MethodHandle guard = null;
-        final ArrayList<Type> runtimeParamTypes = runtimeType(runtimeType);
-        while (runtimeParamTypes.size() > functionNode.getParameters().size()) {
-            runtimeParamTypes.remove(0);
-        }
-        for (i = 0; i < compileTimeArgs.size(); i++) {
-            final Type rparam = Type.typeFor(runtimeType.parameterType(i));
-            final Type cparam = compileTimeArgs.get(i);
-
-            if (cparam.isObject() && !rparam.isObject()) {
-                //check that the runtime object is still coercible to the runtime type, because compiler can't prove it's always primitive
-                if (guard == null) {
-                    guard = MH.insertArguments(PARAM_TYPE_GUARD, 0, (Object)runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]));
-                }
-            }
-        }
-
-        Compiler.LOG.info("Callsite specialized ", name, " runtimeType=", runtimeType, " parameters=", snapshot.getParameters(), " args=", Arrays.asList(args));
-
-        assert snapshot != functionNode;
-
-        final Compiler compiler = new Compiler(installer);
-
-        final FunctionNode compiledSnapshot = compiler.compile(
-            snapshot.setHints(
-                null,
-                new Compiler.Hints(runtimeParamTypes.toArray(new Type[runtimeParamTypes.size()]))));
-
-        /*
-         * No matter how narrow your types were, they can never be narrower than Attr during recompile made them. I.e. you
-         * can put an int into the function here, if you see it as a runtime type, but if the function uses a multiplication
-         * on it, it will still need to be a double. At least until we have overflow checks. Similarly, if an int is
-         * passed but it is used as a string, it makes no sense to make the parameter narrower than Object. At least until
-         * the "different types for one symbol in difference places" work is done
-         */
-        compiler.install(compiledSnapshot);
-
-        return addCode(compiledSnapshot, runtimeType, guard, mh);
-    }
-
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        return MH.findStatic(MethodHandles.lookup(), RecompilableScriptFunctionData.class, name, MH.type(rtype, types));
+        return MethodType.genericMethodType(2 + getArity());
     }
 
     /**
-     * Helper class that allows us to retrieve the method handle for this function once it has been generated.
+     * Return the function node id.
+     * @return the function node id
      */
-    private static class MethodLocator implements Serializable {
-        private transient Class<?> clazz;
-        private final String className;
-        private final String methodName;
-        private final MethodType methodType;
+    public int getFunctionNodeId() {
+        return functionNodeId;
+    }
 
-        private static final long serialVersionUID = -5420835725902966692L;
+    public Source getSource() {
+        return source;
+    }
 
-        MethodLocator(final FunctionNode functionNode) {
-            this.className  = functionNode.getCompileUnit().getUnitClassName();
-            this.methodName = functionNode.getName();
-            this.methodType = new FunctionSignature(functionNode).getMethodType();
-
-            assert className != null;
-            assert methodName != null;
+    /**
+     * Return a script function data based on a function id, either this function if
+     * the id matches or a nested function based on functionId. This goes down into
+     * nested functions until all leaves are exhausted.
+     *
+     * @param functionId function id
+     * @return script function data or null if invalid id
+     */
+    public RecompilableScriptFunctionData getScriptFunctionData(final int functionId) {
+        if (functionId == functionNodeId) {
+            return this;
         }
+        RecompilableScriptFunctionData data;
 
-        void setClass(final Class<?> clazz) {
-            if (!JS.class.isAssignableFrom(clazz)) {
-                throw new IllegalArgumentException();
+        data = nestedFunctions == null ? null : nestedFunctions.get(functionId);
+        if (data != null) {
+            return data;
+        }
+        for (final RecompilableScriptFunctionData ndata : nestedFunctions.values()) {
+            data = ndata.getScriptFunctionData(functionId);
+            if (data != null) {
+                return data;
             }
-            this.clazz = clazz;
         }
+        return null;
+    }
 
-        String getClassName() {
-            return className;
-        }
-
-        MethodType getMethodType() {
-            return methodType;
-        }
-
-        MethodHandle getMethodHandle() {
-            return MH.findStatic(LOOKUP, clazz, methodName, methodType);
+    /**
+     * Get the uppermost parent, the program, for this data
+     * @return program
+     */
+    public RecompilableScriptFunctionData getProgram() {
+        RecompilableScriptFunctionData program = this;
+        while (true) {
+            final RecompilableScriptFunctionData p = program.getParent();
+            if (p == null) {
+                return program;
+            }
+            program = p;
         }
     }
 
-}
+    /**
+     * Check whether a certain name is a global symbol, i.e. only exists as defined
+     * in outermost scope and not shadowed by being parameter or assignment in inner
+     * scopes
+     *
+     * @param functionNode function node to check
+     * @param symbolName symbol name
+     * @return true if global symbol
+     */
+    public boolean isGlobalSymbol(final FunctionNode functionNode, final String symbolName) {
+        RecompilableScriptFunctionData data = getScriptFunctionData(functionNode.getId());
+        assert data != null;
 
+        do {
+            if (data.hasInternalSymbol(symbolName)) {
+                return false;
+            }
+            data = data.getParent();
+        } while(data != null);
+
+        return true;
+    }
+
+    private void readObject(final java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        createLogger();
+    }
+
+    private void createLogger() {
+        log = initLogger(Context.getContextTrusted());
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/RewriteException.java b/nashorn/src/jdk/nashorn/internal/runtime/RewriteException.java
new file mode 100644
index 0000000..37d65f2
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/RewriteException.java
@@ -0,0 +1,419 @@
+/*
+ * 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.
+ */
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.codegen.types.Type;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.objects.Global;
+
+/**
+ * Used to signal to the linker to relink the callee
+ */
+@SuppressWarnings("serial")
+public final class RewriteException extends Exception {
+    private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+
+    // Runtime scope in effect at the time of the compilation. Used to evaluate types of expressions and prevent overly
+    // optimistic assumptions (which will lead to unnecessary deoptimizing recompilations).
+    private ScriptObject runtimeScope;
+
+    // Contents of bytecode slots
+    private Object[] byteCodeSlots;
+
+    private final int[] previousContinuationEntryPoints;
+
+    /** Call for getting the contents of the bytecode slots in the exception */
+    public static final Call GET_BYTECODE_SLOTS       = virtualCallNoLookup(RewriteException.class, "getByteCodeSlots", Object[].class);
+    /** Call for getting the program point in the exception */
+    public static final Call GET_PROGRAM_POINT        = virtualCallNoLookup(RewriteException.class, "getProgramPoint", int.class);
+    /** Call for getting the return value for the exception */
+    public static final Call GET_RETURN_VALUE         = virtualCallNoLookup(RewriteException.class, "getReturnValueDestructive", Object.class);
+    /** Call for the populate array bootstrap */
+    public static final Call BOOTSTRAP                = staticCallNoLookup(RewriteException.class, "populateArrayBootstrap", CallSite.class, Lookup.class, String.class, MethodType.class, int.class);
+
+    /** Call for populating an array with local variable state */
+    private static final Call POPULATE_ARRAY           = staticCall(MethodHandles.lookup(), RewriteException.class, "populateArray", Object[].class, Object[].class, int.class, Object[].class);
+
+    /** Call for converting an array to a long array. */
+    public static final Call TO_LONG_ARRAY   = staticCallNoLookup(RewriteException.class, "toLongArray",   long[].class, Object.class, RewriteException.class);
+    /** Call for converting an array to a double array. */
+    public static final Call TO_DOUBLE_ARRAY = staticCallNoLookup(RewriteException.class, "toDoubleArray", double[].class, Object.class, RewriteException.class);
+    /** Call for converting an array to an object array. */
+    public static final Call TO_OBJECT_ARRAY = staticCallNoLookup(RewriteException.class, "toObjectArray", Object[].class, Object.class, RewriteException.class);
+    /** Call for converting an object to null if it can't be represented as an instance of a class. */
+    public static final Call INSTANCE_OR_NULL = staticCallNoLookup(RewriteException.class, "instanceOrNull", Object.class, Object.class, Class.class);
+    /** Call for asserting the length of an array. */
+    public static final Call ASSERT_ARRAY_LENGTH = staticCallNoLookup(RewriteException.class, "assertArrayLength", void.class, Object[].class, int.class);
+
+    private RewriteException(
+            final UnwarrantedOptimismException e,
+            final Object[] byteCodeSlots,
+            final String[] byteCodeSymbolNames,
+            final int[] previousContinuationEntryPoints) {
+        super("", e, false, Context.DEBUG);
+        this.byteCodeSlots = byteCodeSlots;
+        this.runtimeScope = mergeSlotsWithScope(byteCodeSlots, byteCodeSymbolNames);
+        this.previousContinuationEntryPoints = previousContinuationEntryPoints;
+    }
+
+    /**
+     * Constructor for a rewrite exception thrown from an optimistic function.
+     * @param e the {@link UnwarrantedOptimismException} that triggered this exception.
+     * @param byteCodeSlots contents of local variable slots at the time of rewrite at the program point
+     * @param byteCodeSymbolNames the names of the variables in the {@code byteCodeSlots} parameter. The array might
+     * have less elements, and some elements might be unnamed (the name can be null). The information is provided in an
+     * effort to assist evaluation of expressions for their types by the compiler doing the deoptimizing recompilation,
+     * and can thus be incomplete - the more complete it is, the more expressions can be evaluated by the compiler, and
+     * the more unnecessary deoptimizing compilations can be avoided.
+     * @return a new rewrite exception
+     */
+    public static RewriteException create(final UnwarrantedOptimismException e,
+            final Object[] byteCodeSlots,
+            final String[] byteCodeSymbolNames) {
+        return create(e, byteCodeSlots, byteCodeSymbolNames, null);
+    }
+
+    /**
+     * Constructor for a rewrite exception thrown from a rest-of method.
+     * @param e the {@link UnwarrantedOptimismException} that triggered this exception.
+     * @param byteCodeSlots contents of local variable slots at the time of rewrite at the program point
+     * @param byteCodeSymbolNames the names of the variables in the {@code byteCodeSlots} parameter. The array might
+     * have less elements, and some elements might be unnamed (the name can be null). The information is provided in an
+     * effort to assist evaluation of expressions for their types by the compiler doing the deoptimizing recompilation,
+     * and can thus be incomplete - the more complete it is, the more expressions can be evaluated by the compiler, and
+     * the more unnecessary deoptimizing compilations can be avoided.
+     * @param previousContinuationEntryPoints an array of continuation entry points that were already executed during
+     * one logical invocation of the function (a rest-of triggering a rest-of triggering a...)
+     * @return a new rewrite exception
+     */
+    public static RewriteException create(final UnwarrantedOptimismException e,
+            final Object[] byteCodeSlots,
+            final String[] byteCodeSymbolNames,
+            final int[] previousContinuationEntryPoints) {
+        return new RewriteException(e, byteCodeSlots, byteCodeSymbolNames, previousContinuationEntryPoints);
+    }
+
+    /**
+     * Bootstrap method for populate array
+     * @param lookup     lookup
+     * @param name       name (ignored)
+     * @param type       method type for signature
+     * @param startIndex start index to start writing to
+     * @return callsite to array populator (constant)
+     */
+    public static CallSite populateArrayBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int startIndex) {
+        MethodHandle mh = POPULATE_ARRAY.methodHandle();
+        mh = MH.insertArguments(mh, 1, startIndex);
+        mh = MH.asCollector(mh, Object[].class, type.parameterCount() - 1);
+        mh = MH.asType(mh, type);
+        return new ConstantCallSite(mh);
+    }
+
+    private static ScriptObject mergeSlotsWithScope(final Object[] byteCodeSlots, final String[] byteCodeSymbolNames) {
+        final ScriptObject locals = Global.newEmptyInstance();
+        final int l = Math.min(byteCodeSlots.length, byteCodeSymbolNames.length);
+        ScriptObject runtimeScope = null;
+        final String scopeName = CompilerConstants.SCOPE.symbolName();
+        for(int i = 0; i < l; ++i) {
+            final String name = byteCodeSymbolNames[i];
+            final Object value = byteCodeSlots[i];
+            if(scopeName.equals(name)) {
+                assert runtimeScope == null;
+                runtimeScope = (ScriptObject)value;
+            } else if(name != null) {
+                locals.set(name, value, true);
+            }
+        }
+        locals.setProto(runtimeScope);
+        return locals;
+    }
+
+    /**
+     * Array populator used for saving the local variable state into the array contained in the
+     * RewriteException
+     * @param arrayToBePopluated array to be populated
+     * @param startIndex start index to write to
+     * @param items items with which to populate the array
+     * @return the populated array - same array object
+     */
+    public static Object[] populateArray(final Object[] arrayToBePopluated, final int startIndex, final Object[] items) {
+        System.arraycopy(items, 0, arrayToBePopluated, startIndex, items.length);
+        return arrayToBePopluated;
+    }
+
+    /**
+     * Continuation handler calls this method when a local variable carried over into the continuation is expected to be
+     * a long array in the continued method. Normally, it will also be a long array in the original (interrupted by
+     * deoptimization) method, but it can actually be an int array that underwent widening in the new code version.
+     * @param obj the object that has to be converted into a long array
+     * @param e the exception being processed
+     * @return a long array
+     */
+    public static long[] toLongArray(final Object obj, final RewriteException e) {
+        if(obj instanceof long[]) {
+            return (long[])obj;
+        }
+
+        assert obj instanceof int[];
+
+        final int[] in = (int[])obj;
+        final long[] out = new long[in.length];
+        for(int i = 0; i < in.length; ++i) {
+            out[i] = in[i];
+        }
+        return e.replaceByteCodeValue(in, out);
+    }
+
+    /**
+     * Continuation handler calls this method when a local variable carried over into the continuation is expected to be
+     * a double array in the continued method. Normally, it will also be a double array in the original (interrupted by
+     * deoptimization) method, but it can actually be an int or long array that underwent widening in the new code version.
+     * @param obj the object that has to be converted into a double array
+     * @param e the exception being processed
+     * @return a double array
+     */
+    public static double[] toDoubleArray(final Object obj, final RewriteException e) {
+        if(obj instanceof double[]) {
+            return (double[])obj;
+        }
+
+        assert obj instanceof int[] || obj instanceof long[];
+
+        final int l = Array.getLength(obj);
+        final double[] out = new double[l];
+        for(int i = 0; i < l; ++i) {
+            out[i] = Array.getDouble(obj, i);
+        }
+        return e.replaceByteCodeValue(obj, out);
+    }
+
+    /**
+     * Continuation handler calls this method when a local variable carried over into the continuation is expected to be
+     * an Object array in the continued method. Normally, it will also be an Object array in the original (interrupted by
+     * deoptimization) method, but it can actually be an int, long, or double array that underwent widening in the new
+     * code version.
+     * @param obj the object that has to be converted into an Object array
+     * @param e the exception being processed
+     * @return an Object array
+     */
+    public static Object[] toObjectArray(final Object obj, final RewriteException e) {
+        if(obj instanceof Object[]) {
+            return (Object[])obj;
+        }
+
+        assert obj instanceof int[] || obj instanceof long[] || obj instanceof double[] : obj + " is " + obj.getClass().getName();
+
+        final int l = Array.getLength(obj);
+        final Object[] out = new Object[l];
+        for(int i = 0; i < l; ++i) {
+            out[i] = Array.get(obj, i);
+        }
+        return e.replaceByteCodeValue(obj, out);
+    }
+
+    /**
+     * Continuation handler calls this method when a local variable carried over into the continuation is expected to
+     * have a certain type, but the value can have a different type coming from the deoptimized method as it was a dead
+     * store. If we had precise liveness analysis, we wouldn't need this.
+     * @param obj the object inspected for being of a particular type
+     * @param clazz the type the object must belong to
+     * @return the object if it belongs to the type, or null otherwise
+     */
+    public static Object instanceOrNull(final Object obj, final Class<?> clazz) {
+        return clazz.isInstance(obj) ? obj : null;
+    }
+
+    /**
+     * Asserts the length of an array. Invoked from continuation handler only when running with assertions enabled.
+     * The array can, in fact, have more elements than asserted, but they must all have Undefined as their value. The
+     * method does not test for the array having less elements than asserted, as those would already have caused an
+     * {@code ArrayIndexOutOfBoundsException} to be thrown as the continuation handler attempts to access the missing
+     * elements.
+     * @param arr the array
+     * @param length the asserted length
+     */
+    public static void assertArrayLength(final Object[] arr, final int length) {
+        for(int i = arr.length; i-- > length;) {
+            if(arr[i] != ScriptRuntime.UNDEFINED) {
+                throw new AssertionError(String.format("Expected array length %d, but it is %d", length, i + 1));
+            }
+        }
+    }
+
+    private <T> T replaceByteCodeValue(final Object in, final T out) {
+        for(int i = 0; i < byteCodeSlots.length; ++i) {
+            if(byteCodeSlots[i] == in) {
+                byteCodeSlots[i] = out;
+            }
+        }
+        return out;
+    }
+
+    private UnwarrantedOptimismException getUOE() {
+        return (UnwarrantedOptimismException)getCause();
+    }
+    /**
+     * Get return value. This method is destructive, after it is invoked subsequent invocation of either
+     * {@link #getByteCodeSlots()} or this method will return null. This method is invoked from the generated
+     * continuation code as the last step before continuing the execution, and we need to make sure we don't hang on to
+     * either the entry bytecode slot values or the return value and prevent them from being garbage collected.
+     * @return return value
+     */
+    public Object getReturnValueDestructive() {
+        assert byteCodeSlots != null;
+        byteCodeSlots = null;
+        runtimeScope = null;
+        return getUOE().getReturnValueDestructive();
+    }
+
+    Object getReturnValueNonDestructive() {
+        return getUOE().getReturnValueNonDestructive();
+    }
+
+    /**
+     * Get return type
+     * @return return type
+     */
+    public Type getReturnType() {
+        return getUOE().getReturnType();
+    }
+
+    /**
+     * Get the program point.
+     * @return program point.
+     */
+    public int getProgramPoint() {
+        return getUOE().getProgramPoint();
+    }
+
+    /**
+     * Get the bytecode slot contents.
+     * @return bytecode slot contents.
+     */
+    public Object[] getByteCodeSlots() {
+        return byteCodeSlots == null ? null : byteCodeSlots.clone();
+    }
+
+    /**
+     * @return an array of continuation entry points that were already executed during one logical invocation of the
+     * function (a rest-of triggering a rest-of triggering a...)
+     */
+    public int[] getPreviousContinuationEntryPoints() {
+        return previousContinuationEntryPoints == null ? null : previousContinuationEntryPoints.clone();
+    }
+
+    /**
+     * Returns the runtime scope that was in effect when the exception was thrown.
+     * @return the runtime scope.
+     */
+    public ScriptObject getRuntimeScope() {
+        return runtimeScope;
+    }
+
+    private static String stringify(final Object returnValue) {
+        if (returnValue == null) {
+            return "null";
+        }
+        String str = returnValue.toString();
+        if (returnValue instanceof String) {
+            str = '\'' + str + '\'';
+        } else if (returnValue instanceof Double) {
+            str = str + 'd';
+        } else if (returnValue instanceof Long) {
+            str = str + 'l';
+        }
+        return str;
+    }
+
+    @Override
+    public String getMessage() {
+        return getMessage(false);
+    }
+
+    /**
+     * Short toString function for message
+     * @return short message
+     */
+    public String getMessageShort() {
+        return getMessage(true);
+    }
+
+    private String getMessage(final boolean isShort) {
+        final StringBuilder sb = new StringBuilder();
+
+        //program point
+        sb.append("[pp=").
+            append(getProgramPoint()).
+            append(", ");
+
+        //slot contents
+        if (!isShort) {
+            final Object[] slots = byteCodeSlots;
+            if (slots != null) {
+                sb.append("slots=").
+                    append(Arrays.asList(slots)).
+                    append(", ");
+            }
+        }
+
+        //return type
+        sb.append("type=").
+            append(getReturnType()).
+            append(", ");
+
+        //return value
+        sb.append("value=").
+            append(stringify(getReturnValueNonDestructive())).
+            append(")]");
+
+        return sb.toString();
+    }
+
+    private void writeObject(final ObjectOutputStream out) throws NotSerializableException {
+        throw new NotSerializableException(getClass().getName());
+    }
+
+    private void readObject(final ObjectInputStream in) throws NotSerializableException {
+        throw new NotSerializableException(getClass().getName());
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
index 445106d..8f56ddf 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptEnvironment.java
@@ -26,16 +26,18 @@
 package jdk.nashorn.internal.runtime;
 
 import java.io.PrintWriter;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
-import java.util.Set;
+import java.util.Map;
 import java.util.StringTokenizer;
 import java.util.TimeZone;
-
+import java.util.logging.Level;
 import jdk.nashorn.internal.codegen.Namespace;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.options.KeyValueOption;
+import jdk.nashorn.internal.runtime.options.LoggingOption;
+import jdk.nashorn.internal.runtime.options.LoggingOption.LoggerInfo;
 import jdk.nashorn.internal.runtime.options.Option;
 import jdk.nashorn.internal.runtime.options.Options;
 
@@ -92,8 +94,11 @@
     /** Use single Global instance per jsr223 engine instance. */
     public final boolean _global_per_engine;
 
+    /** Argument passed to compile only if optimistic compilation should take place */
+    public static final String COMPILE_ONLY_OPTIMISTIC_ARG = "optimistic";
+
     /**
-     * Behavior when encountering a function declaration in a lexical context where only statements are acceptable
+     *  Behavior when encountering a function declaration in a lexical context where only statements are acceptable
      * (function declarations are source elements, but not statements).
      */
     public enum FunctionStatementBehavior {
@@ -122,6 +127,9 @@
     /** Should lazy compilation take place */
     public final boolean _lazy_compilation;
 
+    /** Should optimistic types be used */
+    public final boolean _optimistic_types;
+
     /** Create a new class loaded for each compilation */
     public final boolean _loader_per_compile;
 
@@ -149,6 +157,12 @@
     /** Print resulting bytecode for script */
     public final boolean _print_code;
 
+    /** Directory (optional) to print files to */
+    public final String _print_code_dir;
+
+    /** List of functions to write to the print code dir, optional */
+    public final String _print_code_func;
+
     /** Print memory usage for IR after each phase */
     public final boolean _print_mem_usage;
 
@@ -170,9 +184,6 @@
     /** is this environment in scripting mode? */
     public final boolean _scripting;
 
-    /** is the JIT allowed to specializ calls based on callsite types? */
-    public final Set<String> _specialize_calls;
-
     /** is this environment in strict mode? */
     public final boolean _strict;
 
@@ -188,6 +199,12 @@
     /** Local for error messages */
     public final Locale _locale;
 
+    /** Logging */
+    public final Map<String, LoggerInfo> _loggers;
+
+    /** Timing */
+    public final Timing _timing;
+
     /**
      * Constructor
      *
@@ -210,9 +227,9 @@
         _early_lvalue_error   = options.getBoolean("early.lvalue.error");
         _empty_statements     = options.getBoolean("empty.statements");
         _fullversion          = options.getBoolean("fullversion");
-        if(options.getBoolean("function.statement.error")) {
+        if (options.getBoolean("function.statement.error")) {
             _function_statement = FunctionStatementBehavior.ERROR;
-        } else if(options.getBoolean("function.statement.warning")) {
+        } else if (options.getBoolean("function.statement.warning")) {
             _function_statement = FunctionStatementBehavior.WARNING;
         } else {
             _function_statement = FunctionStatementBehavior.ACCEPT;
@@ -220,6 +237,7 @@
         _fx                   = options.getBoolean("fx");
         _global_per_engine    = options.getBoolean("global.per.engine");
         _lazy_compilation     = options.getBoolean("lazy.compilation");
+        _optimistic_types     = options.getBoolean("optimistic.types");
         _loader_per_compile   = options.getBoolean("loader.per.compile");
         _no_java              = options.getBoolean("no.java");
         _no_syntax_extensions = options.getBoolean("no.syntax.extensions");
@@ -228,7 +246,7 @@
         _persistent_cache     = options.getBoolean("persistent.code.cache");
         _print_ast            = options.getBoolean("print.ast");
         _print_lower_ast      = options.getBoolean("print.lower.ast");
-        _print_code           = options.getBoolean("print.code");
+        _print_code           = options.getString("print.code") != null;
         _print_mem_usage      = options.getBoolean("print.mem.usage");
         _print_no_newline     = options.getBoolean("print.no.newline");
         _print_parse          = options.getBoolean("print.parse");
@@ -240,16 +258,25 @@
         _version              = options.getBoolean("version");
         _verify_code          = options.getBoolean("verify.code");
 
-        final String specialize = options.getString("specialize.calls");
-        if (specialize == null) {
-            _specialize_calls = null;
-        } else {
-            _specialize_calls = new HashSet<>();
-            final StringTokenizer st = new StringTokenizer(specialize, ",");
-            while (st.hasMoreElements()) {
-                _specialize_calls.add(st.nextToken());
+        String dir = null;
+        String func = null;
+        final String pc = options.getString("print.code");
+        if (pc != null) {
+            final StringTokenizer st = new StringTokenizer(pc, ",");
+            while (st.hasMoreTokens()) {
+                final StringTokenizer st2 = new StringTokenizer(st.nextToken(), ":");
+                while (st2.hasMoreTokens()) {
+                    final String cmd = st2.nextToken();
+                    if ("dir".equals(cmd)) {
+                        dir = st2.nextToken();
+                    } else if ("function".equals(cmd)) {
+                        func = st2.nextToken();
+                    }
+                }
             }
         }
+        _print_code_dir = dir;
+        _print_code_func = func;
 
         int callSiteFlags = 0;
         if (options.getBoolean("profile.callsites")) {
@@ -268,9 +295,6 @@
             if (kv.hasValue("objects")) {
                 callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_VALUES;
             }
-            if (kv.hasValue("scope")) {
-                callSiteFlags |= NashornCallSiteDescriptor.CALLSITE_TRACE_SCOPE;
-            }
         }
         this._callsite_flags = callSiteFlags;
 
@@ -287,18 +311,12 @@
         } else {
             this._locale = Locale.getDefault();
         }
-    }
 
-    /**
-     * Can we specialize a particular method name?
-     * @param functionName method name
-     * @return true if we are allowed to generate versions of this method
-     */
-    public boolean canSpecialize(final String functionName) {
-        if (_specialize_calls == null) {
-            return false;
-        }
-        return _specialize_calls.isEmpty() || _specialize_calls.contains(functionName);
+        final LoggingOption loggingOption = (LoggingOption)options.get("log");
+        this._loggers = loggingOption == null ? new HashMap<String, LoggerInfo>() : loggingOption.getLoggers();
+
+        final LoggerInfo timeLoggerInfo = _loggers.get(Timing.getLoggerName());
+        this._timing = new Timing(timeLoggerInfo != null && timeLoggerInfo.getLevel() != Level.OFF);
     }
 
     /**
@@ -343,4 +361,24 @@
     public List<String> getArguments() {
         return options.getArguments();
     }
+
+    /**
+     * Check if there is a logger registered for a particular name: typically
+     * the "name" attribute of a Loggable annotation on a class
+     *
+     * @param name logger name
+     * @return true, if a logger exists for that name, false otherwise
+     */
+    public boolean hasLogger(final String name) {
+        return _loggers.get(name) != null;
+    }
+
+    /**
+     * Check if compilation/runtime timings are enabled
+     * @return true if enabled
+     */
+    public boolean isTimingEnabled() {
+        return _timing != null ? _timing.isEnabled() : false;
+    }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
index 3d8b4ff..81863bd 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunction.java
@@ -29,18 +29,23 @@
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import java.util.Collections;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.codegen.ApplySpecialization;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeFunction;
+import jdk.nashorn.internal.runtime.linker.Bootstrap;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
-import jdk.nashorn.internal.runtime.linker.NashornGuards;
 
 /**
  * Runtime representation of a JavaScript function.
@@ -48,35 +53,39 @@
 public abstract class ScriptFunction extends ScriptObject {
 
     /** Method handle for prototype getter for this ScriptFunction */
-    public static final MethodHandle G$PROTOTYPE = findOwnMH("G$prototype", Object.class, Object.class);
+    public static final MethodHandle G$PROTOTYPE = findOwnMH_S("G$prototype", Object.class, Object.class);
 
     /** Method handle for prototype setter for this ScriptFunction */
-    public static final MethodHandle S$PROTOTYPE = findOwnMH("S$prototype", void.class, Object.class, Object.class);
+    public static final MethodHandle S$PROTOTYPE = findOwnMH_S("S$prototype", void.class, Object.class, Object.class);
 
     /** Method handle for length getter for this ScriptFunction */
-    public static final MethodHandle G$LENGTH = findOwnMH("G$length", int.class, Object.class);
+    public static final MethodHandle G$LENGTH = findOwnMH_S("G$length", int.class, Object.class);
 
     /** Method handle for name getter for this ScriptFunction */
-    public static final MethodHandle G$NAME = findOwnMH("G$name", Object.class, Object.class);
+    public static final MethodHandle G$NAME = findOwnMH_S("G$name", Object.class, Object.class);
 
     /** Method handle used for implementing sync() in mozilla_compat */
-    public static final MethodHandle INVOKE_SYNC = findOwnMH("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
+    public static final MethodHandle INVOKE_SYNC = findOwnMH_S("invokeSync", Object.class, ScriptFunction.class, Object.class, Object.class, Object[].class);
 
     /** Method handle for allocate function for this ScriptFunction */
-    static final MethodHandle ALLOCATE = findOwnMH("allocate", Object.class);
+    static final MethodHandle ALLOCATE = findOwnMH_V("allocate", Object.class);
 
-    private static final MethodHandle WRAPFILTER = findOwnMH("wrapFilter", Object.class, Object.class);
+    private static final MethodHandle WRAPFILTER = findOwnMH_S("wrapFilter", Object.class, Object.class);
 
-    private static final MethodHandle GLOBALFILTER = findOwnMH("globalFilter", Object.class, Object.class);
+    private static final MethodHandle SCRIPTFUNCTION_GLOBALFILTER = findOwnMH_S("globalFilter", Object.class, Object.class);
 
     /** method handle to scope getter for this ScriptFunction */
     public static final Call GET_SCOPE = virtualCallNoLookup(ScriptFunction.class, "getScope", ScriptObject.class);
 
-    private static final MethodHandle IS_FUNCTION_MH  = findOwnMH("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
+    private static final MethodHandle IS_FUNCTION_MH  = findOwnMH_S("isFunctionMH", boolean.class, Object.class, ScriptFunctionData.class);
 
-    private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
+    private static final MethodHandle IS_APPLY_FUNCTION  = findOwnMH_S("isApplyFunction", boolean.class, boolean.class, Object.class, Object.class);
 
-    private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH("addZerothElement", Object[].class, Object[].class, Object.class);
+    private static final MethodHandle IS_NONSTRICT_FUNCTION = findOwnMH_S("isNonStrictFunction", boolean.class, Object.class, Object.class, ScriptFunctionData.class);
+
+    private static final MethodHandle ADD_ZEROTH_ELEMENT = findOwnMH_S("addZerothElement", Object[].class, Object[].class, Object.class);
+
+    private static final MethodHandle WRAP_THIS = MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, "wrapThis", MH.type(Object.class, Object.class));
 
     /** The parent scope. */
     private final ScriptObject scope;
@@ -195,6 +204,10 @@
         return data.needsWrappedThis();
     }
 
+    private static boolean needsWrappedThis(final Object fn) {
+        return fn instanceof ScriptFunction ? ((ScriptFunction)fn).needsWrappedThis() : false;
+    }
+
     /**
      * Execute this script function.
      * @param self  Target object.
@@ -230,12 +243,13 @@
         if (Context.DEBUG) {
             allocations++;
         }
+
         assert !isBoundFunction(); // allocate never invoked on bound functions
 
         final ScriptObject object = data.allocate(allocatorMap);
 
         if (object != null) {
-            Object prototype = getPrototype();
+            final Object prototype = getPrototype();
             if (prototype instanceof ScriptObject) {
                 object.setInitialProto((ScriptObject)prototype);
             }
@@ -311,26 +325,7 @@
      * @param sync the Object to synchronize on, or undefined
      * @return synchronized function
      */
-    public abstract ScriptFunction makeSynchronizedFunction(Object sync);
-
-    /**
-     * Return the most appropriate invoke handle if there are specializations
-     * @param type most specific method type to look for invocation with
-     * @param args args for trampoline invocation
-     * @return invoke method handle
-     */
-    private MethodHandle getBestInvoker(final MethodType type, final Object[] args) {
-        return data.getBestInvoker(type, args);
-    }
-
-    /**
-     * Return the most appropriate invoke handle if there are specializations
-     * @param type most specific method type to look for invocation with
-     * @return invoke method handle
-     */
-    public MethodHandle getBestInvoker(final MethodType type) {
-        return getBestInvoker(type, null);
-    }
+   public abstract ScriptFunction makeSynchronizedFunction(Object sync);
 
     /**
      * Return the invoke handle bound to a given ScriptObject self reference.
@@ -340,7 +335,7 @@
      * @return bound invoke handle
      */
     public final MethodHandle getBoundInvokeHandle(final Object self) {
-        return MH.bindTo(bindToCalleeIfNeeded(data.getGenericInvoker()), self);
+        return MH.bindTo(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), self);
     }
 
     /**
@@ -379,7 +374,7 @@
      * @return self's prototype
      */
     public static Object G$prototype(final Object self) {
-        return (self instanceof ScriptFunction) ?
+        return self instanceof ScriptFunction ?
             ((ScriptFunction)self).getPrototype() :
             UNDEFINED;
     }
@@ -428,9 +423,9 @@
      * @param constructor constructor
      * @return prototype, or null if given constructor is not a ScriptFunction
      */
-    public static ScriptObject getPrototype(final Object constructor) {
-        if (constructor instanceof ScriptFunction) {
-            final Object proto = ((ScriptFunction)constructor).getPrototype();
+    public static ScriptObject getPrototype(final ScriptFunction constructor) {
+        if (constructor != null) {
+            final Object proto = constructor.getPrototype();
             if (proto instanceof ScriptObject) {
                 return (ScriptObject)proto;
             }
@@ -466,9 +461,13 @@
     }
 
     @Override
-    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final MethodType type = desc.getMethodType();
-        return new GuardedInvocation(pairArguments(data.getBestConstructor(type.changeParameterType(0, ScriptFunction.class), null), type), null, getFunctionGuard(this));
+        assert desc.getMethodType().returnType() == Object.class && !NashornCallSiteDescriptor.isOptimistic(desc);
+        final CompiledFunction cf = data.getBestConstructor(type, scope);
+        final GuardedInvocation bestCtorInv = cf.createConstructorInvocation();
+        //TODO - ClassCastException
+        return new GuardedInvocation(pairArguments(bestCtorInv.getInvocation(), type), getFunctionGuard(this, cf.getFlags()), bestCtorInv.getSwitchPoints(), null);
     }
 
     @SuppressWarnings("unused")
@@ -497,51 +496,79 @@
      * (b) method doesn't have callee parameter (builtin functions)
      *   (3) for local/scope calls, bind thiz and drop both callee and thiz.
      *   (4) for normal this-calls, drop callee.
+     *
+     * @return guarded invocation for call
      */
     @Override
     protected GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final MethodType type = desc.getMethodType();
-        final boolean scopeCall = NashornCallSiteDescriptor.isScope(desc);
 
-        if (request.isCallSiteUnstable()) {
-            // (callee, this, args...) => (callee, this, args[])
-            final MethodHandle collector = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
+        final String  name       = getName();
+        final boolean isUnstable = request.isCallSiteUnstable();
+        final boolean scopeCall  = NashornCallSiteDescriptor.isScope(desc);
+        final boolean isCall     = !scopeCall && data.isBuiltin() && "call".equals(name);
+        final boolean isApply    = !scopeCall && data.isBuiltin() && "apply".equals(name);
+
+        final boolean isApplyOrCall = isCall | isApply;
+
+        if (isUnstable && !isApplyOrCall) {
+            //megamorphic - replace call with apply
+            final MethodHandle handle;
+            //ensure that the callsite is vararg so apply can consume it
+            if (type.parameterCount() == 3 && type.parameterType(2) == Object[].class) {
+                // Vararg call site
+                handle = ScriptRuntime.APPLY.methodHandle();
+            } else {
+                // (callee, this, args...) => (callee, this, args[])
+                handle = MH.asCollector(ScriptRuntime.APPLY.methodHandle(), Object[].class, type.parameterCount() - 2);
+            }
 
             // If call site is statically typed to take a ScriptFunction, we don't need a guard, otherwise we need a
             // generic "is this a ScriptFunction?" guard.
-            return new GuardedInvocation(collector, ScriptFunction.class.isAssignableFrom(desc.getMethodType().parameterType(0))
-                    ? null : NashornGuards.getScriptFunctionGuard());
+            return new GuardedInvocation(
+                    handle,
+                    null,
+                    (SwitchPoint)null,
+                    ClassCastException.class);
         }
 
         MethodHandle boundHandle;
         MethodHandle guard = null;
 
+        // Special handling of Function.apply and Function.call. Note we must be invoking
+        if (isApplyOrCall && !isUnstable) {
+            final Object[] args = request.getArguments();
+            if (Bootstrap.isCallable(args[1])) {
+                return createApplyOrCallCall(isApply, desc, request, args);
+            }
+        } //else just fall through and link as ordinary function or unstable apply
+
+        final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT;
+        final CompiledFunction cf = data.getBestInvoker(type, scope);
+        final GuardedInvocation bestInvoker = cf.createFunctionInvocation(type.returnType(), programPoint);
+        final MethodHandle callHandle = bestInvoker.getInvocation();
+
         if (data.needsCallee()) {
-            final MethodHandle callHandle = getBestInvoker(type, request.getArguments());
             if (scopeCall && needsWrappedThis()) {
-                // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
                 // (callee, this, args...) => (callee, [this], args...)
-                boundHandle = MH.filterArguments(callHandle, 1, GLOBALFILTER);
+                boundHandle = MH.filterArguments(callHandle, 1, SCRIPTFUNCTION_GLOBALFILTER);
             } else {
                 // It's already (callee, this, args...), just what we need
                 boundHandle = callHandle;
             }
+        } else if (data.isBuiltin() && "extend".equals(data.getName())) {
+            // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
+            // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
+            boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, type.parameterType(0), type.parameterType(1));
+        } else if (scopeCall && needsWrappedThis()) {
+            // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
+            // (this, args...) => ([this], args...)
+            boundHandle = MH.filterArguments(callHandle, 0, SCRIPTFUNCTION_GLOBALFILTER);
+            // ([this], args...) => ([callee], [this], args...)
+            boundHandle = MH.dropArguments(boundHandle, 0, type.parameterType(0));
         } else {
-            final MethodHandle callHandle = getBestInvoker(type.dropParameterTypes(0, 1), request.getArguments());
-            if (data.isBuiltin() && "extend".equals(data.getName())) {
-                // NOTE: the only built-in named "extend" is NativeJava.extend. As a special-case we're binding the
-                // current lookup as its "this" so it can do security-sensitive creation of adapter classes.
-                boundHandle = MH.dropArguments(MH.bindTo(callHandle, desc.getLookup()), 0, Object.class, Object.class);
-            } else if (scopeCall && needsWrappedThis()) {
-                // Make a handle that drops the passed "this" argument and substitutes either Global or Undefined
-                // (this, args...) => ([this], args...)
-                boundHandle = MH.filterArguments(callHandle, 0, GLOBALFILTER);
-                // ([this], args...) => ([callee], [this], args...)
-                boundHandle = MH.dropArguments(boundHandle, 0, Object.class);
-            } else {
-                // (this, args...) => ([callee], this, args...)
-                boundHandle = MH.dropArguments(callHandle, 0, Object.class);
-            }
+            // (this, args...) => ([callee], this, args...)
+            boundHandle = MH.dropArguments(callHandle, 0, type.parameterType(0));
         }
 
         // For non-strict functions, check whether this-object is primitive type.
@@ -557,8 +584,217 @@
 
         boundHandle = pairArguments(boundHandle, type);
 
-        return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this) : guard);
-   }
+        return new GuardedInvocation(boundHandle, guard == null ? getFunctionGuard(this, cf.getFlags()) : guard, bestInvoker.getSwitchPoints(), null);
+    }
+
+    private GuardedInvocation createApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc, final LinkRequest request, final Object[] args) {
+        final MethodType descType = desc.getMethodType();
+        final int paramCount = descType.parameterCount();
+        if(descType.parameterType(paramCount - 1).isArray()) {
+            // This is vararg invocation of apply or call. This can normally only happen when we do a recursive
+            // invocation of createApplyOrCallCall (because we're doing apply-of-apply). In this case, create delegate
+            // linkage by unpacking the vararg invocation and use pairArguments to introduce the necessary spreader.
+            return createVarArgApplyOrCallCall(isApply, desc, request, args);
+        }
+
+        final boolean passesThis = paramCount > 2;
+        final boolean passesArgs = paramCount > 3;
+        final int realArgCount = passesArgs ? paramCount - 3 : 0;
+
+        final Object appliedFn = args[1];
+        final boolean appliedFnNeedsWrappedThis = needsWrappedThis(appliedFn);
+
+        //box call back to apply
+        CallSiteDescriptor appliedDesc = desc;
+        final SwitchPoint applyToCallSwitchPoint = Global.instance().getChangeCallback("apply");
+        //enough to change the proto switchPoint here
+
+        final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc);
+        final boolean isFailedApplyToCall = isApplyToCall && applyToCallSwitchPoint.hasBeenInvalidated();
+
+        // R(apply|call, ...) => R(...)
+        MethodType appliedType = descType.dropParameterTypes(0, 1);
+        if (!passesThis) {
+            // R() => R(this)
+            appliedType = appliedType.insertParameterTypes(1, Object.class);
+        } else if (appliedFnNeedsWrappedThis) {
+            appliedType = appliedType.changeParameterType(1, Object.class);
+        }
+
+        if (isApply || isFailedApplyToCall) {
+            if (passesArgs) {
+                // R(this, args) => R(this, Object[])
+                appliedType = appliedType.changeParameterType(2, Object[].class);
+                // drop any extraneous arguments for the apply fail case
+                if (isFailedApplyToCall) {
+                    appliedType = appliedType.dropParameterTypes(3, paramCount - 1);
+                }
+            } else {
+                // R(this) => R(this, Object[])
+                appliedType = appliedType.insertParameterTypes(2, Object[].class);
+            }
+        }
+
+        appliedDesc = appliedDesc.changeMethodType(appliedType);
+
+        // Create the same arguments for the delegate linking request that would be passed in an actual apply'd invocation
+        final Object[] appliedArgs = new Object[isApply ? 3 : appliedType.parameterCount()];
+        appliedArgs[0] = appliedFn;
+        appliedArgs[1] = passesThis ? appliedFnNeedsWrappedThis ? ScriptFunctionData.wrapThis(args[2]) : args[2] : ScriptRuntime.UNDEFINED;
+        if (isApply && !isFailedApplyToCall) {
+            appliedArgs[2] = passesArgs ? NativeFunction.toApplyArgs(args[3]) : ScriptRuntime.EMPTY_ARRAY;
+        } else {
+            if (passesArgs) {
+                if (isFailedApplyToCall) {
+                    final Object[] tmp = new Object[args.length - 3];
+                    System.arraycopy(args, 3, tmp, 0, tmp.length);
+                    appliedArgs[2] = NativeFunction.toApplyArgs(tmp);
+                } else {
+                    assert !isApply;
+                    System.arraycopy(args, 3, appliedArgs, 2, args.length - 3);
+                }
+            } else if (isFailedApplyToCall) {
+                appliedArgs[2] = ScriptRuntime.EMPTY_ARRAY;
+            }
+        }
+
+        // Ask the linker machinery for an invocation of the target function
+        final LinkRequest appliedRequest = request.replaceArguments(appliedDesc, appliedArgs);
+        GuardedInvocation appliedInvocation;
+        try {
+            appliedInvocation = Bootstrap.getLinkerServices().getGuardedInvocation(appliedRequest);
+        } catch (final RuntimeException | Error e) {
+            throw e;
+        } catch (final Exception e) {
+            throw new RuntimeException(e);
+        }
+        assert appliedRequest != null; // Bootstrap.isCallable() returned true for args[1], so it must produce a linkage.
+
+        final Class<?> applyFnType = descType.parameterType(0);
+        MethodHandle inv = appliedInvocation.getInvocation(); //method handle from apply invocation. the applied function invocation
+
+        if (isApply && !isFailedApplyToCall) {
+            if (passesArgs) {
+                // Make sure that the passed argArray is converted to Object[] the same way NativeFunction.apply() would do it.
+                inv = MH.filterArguments(inv, 2, NativeFunction.TO_APPLY_ARGS);
+            } else {
+                // If the original call site doesn't pass argArray, pass in an empty array
+                inv = MH.insertArguments(inv, 2, (Object)ScriptRuntime.EMPTY_ARRAY);
+            }
+        }
+
+        if (isApplyToCall) {
+            if (isFailedApplyToCall) {
+                //take the real arguments that were passed to a call and force them into the apply instead
+                Context.getContextTrusted().getLogger(ApplySpecialization.class).info("Collection arguments to revert call to apply in " + appliedFn);
+                inv = MH.asCollector(inv, Object[].class, realArgCount);
+            } else {
+                appliedInvocation = appliedInvocation.addSwitchPoint(applyToCallSwitchPoint);
+            }
+        }
+
+        if (!passesThis) {
+            // If the original call site doesn't pass in a thisArg, pass in Global/undefined as needed
+            inv = bindImplicitThis(appliedFn, inv);
+        } else if (appliedFnNeedsWrappedThis) {
+            // target function needs a wrapped this, so make sure we filter for that
+            inv = MH.filterArguments(inv, 1, WRAP_THIS);
+        }
+        inv = MH.dropArguments(inv, 0, applyFnType);
+
+        MethodHandle guard = appliedInvocation.getGuard();
+        // If the guard checks the value of "this" but we aren't passing thisArg, insert the default one
+        if (!passesThis && guard.type().parameterCount() > 1) {
+            guard = bindImplicitThis(appliedFn, guard);
+        }
+        final MethodType guardType = guard.type();
+
+        // We need to account for the dropped (apply|call) function argument.
+        guard = MH.dropArguments(guard, 0, descType.parameterType(0));
+        // Take the "isApplyFunction" guard, and bind it to this function.
+        MethodHandle applyFnGuard = MH.insertArguments(IS_APPLY_FUNCTION, 2, this);
+        // Adapt the guard to receive all the arguments that the original guard does.
+        applyFnGuard = MH.dropArguments(applyFnGuard, 2, guardType.parameterArray());
+        // Fold the original function guard into our apply guard.
+        guard = MH.foldArguments(applyFnGuard, guard);
+
+        return appliedInvocation.replaceMethods(inv, guard);
+    }
+
+    /*
+     * This method is used for linking nested apply. Specialized apply and call linking will create a variable arity
+     * call site for an apply call; when createApplyOrCallCall sees a linking request for apply or call with
+     * Nashorn-style variable arity call site (last argument type is Object[]) it'll delegate to this method.
+     * This method converts the link request from a vararg to a non-vararg one (unpacks the array), then delegates back
+     * to createApplyOrCallCall (with which it is thus mutually recursive), and adds appropriate argument spreaders to
+     * invocation and the guard of whatever createApplyOrCallCall returned to adapt it back into a variable arity
+     * invocation. It basically reduces the problem of vararg call site linking of apply and call back to the (already
+     * solved by createApplyOrCallCall) non-vararg call site linking.
+     */
+    private GuardedInvocation createVarArgApplyOrCallCall(final boolean isApply, final CallSiteDescriptor desc,
+            final LinkRequest request, final Object[] args) {
+        final MethodType descType = desc.getMethodType();
+        final int paramCount = descType.parameterCount();
+        final Object[] varArgs = (Object[])args[paramCount - 1];
+        // -1 'cause we're not passing the vararg array itself
+        final int copiedArgCount = args.length - 1;
+        final int varArgCount = varArgs.length;
+
+        // Spread arguments for the delegate createApplyOrCallCall invocation.
+        final Object[] spreadArgs = new Object[copiedArgCount + varArgCount];
+        System.arraycopy(args, 0, spreadArgs, 0, copiedArgCount);
+        System.arraycopy(varArgs, 0, spreadArgs, copiedArgCount, varArgCount);
+
+        // Spread call site descriptor for the delegate createApplyOrCallCall invocation. We drop vararg array and
+        // replace it with a list of Object.class.
+        final MethodType spreadType = descType.dropParameterTypes(paramCount - 1, paramCount).appendParameterTypes(
+                Collections.<Class<?>>nCopies(varArgCount, Object.class));
+        final CallSiteDescriptor spreadDesc = desc.changeMethodType(spreadType);
+
+        // Delegate back to createApplyOrCallCall with the spread (that is, reverted to non-vararg) request/
+        final LinkRequest spreadRequest = request.replaceArguments(spreadDesc, spreadArgs);
+        final GuardedInvocation spreadInvocation = createApplyOrCallCall(isApply, spreadDesc, spreadRequest, spreadArgs);
+
+        // Add spreader combinators to returned invocation and guard.
+        return spreadInvocation.replaceMethods(
+                // Use standard ScriptObject.pairArguments on the invocation
+                pairArguments(spreadInvocation.getInvocation(), descType),
+                // Use our specialized spreadGuardArguments on the guard (see below).
+                spreadGuardArguments(spreadInvocation.getGuard(), descType));
+    }
+
+    private static MethodHandle spreadGuardArguments(final MethodHandle guard, final MethodType descType) {
+        final MethodType guardType = guard.type();
+        final int guardParamCount = guardType.parameterCount();
+        final int descParamCount = descType.parameterCount();
+        final int spreadCount = guardParamCount - descParamCount + 1;
+        if (spreadCount <= 0) {
+            // Guard doesn't dip into the varargs
+            return guard;
+        }
+
+        final MethodHandle arrayConvertingGuard;
+        // If the last parameter type of the guard is an array, then it is already itself a guard for a vararg apply
+        // invocation. We must filter the last argument with toApplyArgs otherwise deeper levels of nesting will fail
+        // with ClassCastException of NativeArray to Object[].
+        if(guardType.parameterType(guardParamCount - 1).isArray()) {
+            arrayConvertingGuard = MH.filterArguments(guard, guardParamCount - 1, NativeFunction.TO_APPLY_ARGS);
+        } else {
+            arrayConvertingGuard = guard;
+        }
+
+        return ScriptObject.adaptHandleToVarArgCallSite(arrayConvertingGuard, descParamCount);
+    }
+
+    private static MethodHandle bindImplicitThis(final Object fn, final MethodHandle mh) {
+         final MethodHandle bound;
+         if(fn instanceof ScriptFunction && ((ScriptFunction)fn).needsWrappedThis()) {
+             bound = MH.filterArguments(mh, 1, SCRIPTFUNCTION_GLOBALFILTER);
+         } else {
+             bound = mh;
+         }
+         return MH.insertArguments(bound, 1, ScriptRuntime.UNDEFINED);
+     }
 
     /**
      * Used for noSuchMethod/noSuchProperty and JSAdapter hooks.
@@ -566,7 +802,7 @@
      * These don't want a callee parameter, so bind that. Name binding is optional.
      */
     MethodHandle getCallMethodHandle(final MethodType type, final String bindName) {
-        return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(getBestInvoker(type, null)), bindName), type);
+        return pairArguments(bindToNameIfNeeded(bindToCalleeIfNeeded(data.getGenericInvoker(scope)), bindName), type);
     }
 
     private static MethodHandle bindToNameIfNeeded(final MethodHandle methodHandle, final String bindName) {
@@ -594,8 +830,13 @@
      *
      * @return method handle for guard
      */
-    private static MethodHandle getFunctionGuard(final ScriptFunction function) {
+    private static MethodHandle getFunctionGuard(final ScriptFunction function, final int flags) {
         assert function.data != null;
+        // Built-in functions have a 1-1 correspondence to their ScriptFunctionData, so we can use a cheaper identity
+        // comparison for them.
+        if (function.data.isBuiltin()) {
+            return Guards.getIdentityGuard(function);
+        }
         return MH.insertArguments(IS_FUNCTION_MH, 1, function.data);
     }
 
@@ -624,9 +865,15 @@
     }
 
     @SuppressWarnings("unused")
+    private static boolean isApplyFunction(final boolean appliedFnCondition, final Object self, final Object expectedSelf) {
+        // NOTE: we're using self == expectedSelf as we're only using this with built-in functions apply() and call()
+        return appliedFnCondition && self == expectedSelf;
+    }
+
+    @SuppressWarnings("unused")
     private static Object[] addZerothElement(final Object[] args, final Object value) {
         // extends input array with by adding new zeroth element
-        final Object[] src = (args == null)? ScriptRuntime.EMPTY_ARRAY : args;
+        final Object[] src = args == null? ScriptRuntime.EMPTY_ARRAY : args;
         final Object[] result = new Object[src.length + 1];
         System.arraycopy(src, 0, result, 1, src.length);
         result[0] = value;
@@ -642,14 +889,12 @@
         }
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        final Class<?>   own = ScriptFunction.class;
-        final MethodType mt  = MH.type(rtype, types);
-        try {
-            return MH.findStatic(MethodHandles.lookup(), own, name, mt);
-        } catch (final MethodHandleFactory.LookupException e) {
-            return MH.findVirtual(MethodHandles.lookup(), own, name, mt);
-        }
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types));
+    }
+
+    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findVirtual(MethodHandles.lookup(), ScriptFunction.class, name, MH.type(rtype, types));
     }
 }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
index 001996b..3cd292a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptFunctionData.java
@@ -29,11 +29,16 @@
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
+import java.io.IOException;
+import java.io.ObjectInputStream;
 import java.io.Serializable;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodType;
-import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory;
+import java.util.LinkedList;
+import java.util.List;
+import jdk.nashorn.internal.runtime.linker.LinkerCallSite;
+
 
 /**
  * A container for data needed to instantiate a specific {@link ScriptFunction} at runtime.
@@ -41,19 +46,36 @@
  * constants array to reduce function instantiation overhead during runtime.
  */
 public abstract class ScriptFunctionData implements Serializable {
+    static final int MAX_ARITY = LinkerCallSite.ARGLIMIT;
+    static {
+        // Assert it fits in a byte, as that's what we store it in. It's just a size optimization though, so if needed
+        // "byte arity" field can be widened.
+        assert MAX_ARITY < 256;
+    }
 
-    /** Name of the function or "" for anonynous functions */
+    /** Name of the function or "" for anonymous functions */
     protected final String name;
 
-    /** All versions of this function that have been generated to code */
-    protected final CompiledFunctions code;
+    /**
+     * A list of code versions of a function sorted in ascending order of generic descriptors.
+     */
+    protected transient LinkedList<CompiledFunction> code = new LinkedList<>();
 
     /** Function flags */
     protected int flags;
 
+    // Parameter arity of the function, corresponding to "f.length". E.g. "function f(a, b, c) { ... }" arity is 3, and
+    // some built-in ECMAScript functions have their arity declared by the specification. Note that regardless of this
+    // value, the function might still be capable of receiving variable number of arguments, see isVariableArity.
     private int arity;
 
-    private static final MethodHandle NEWFILTER     = findOwnMH("newFilter", Object.class, Object.class, Object.class);
+    /**
+     * A pair of method handles used for generic invoker and constructor. Field is volatile as it can be initialized by
+     * multiple threads concurrently, but we still tolerate a race condition in it as all values stored into it are
+     * idempotent.
+     */
+    private volatile transient GenericInvokers genericInvokers;
+
     private static final MethodHandle BIND_VAR_ARGS = findOwnMH("bindVarArgs", Object[].class, Object[].class, Object[].class);
 
     /** Is this a strict mode function? */
@@ -66,6 +88,10 @@
     public static final int NEEDS_CALLEE   = 1 << 3;
     /** Does this function make use of the this-object argument? */
     public static final int USES_THIS      = 1 << 4;
+    /** Is this a variable arity function? */
+    public static final int IS_VARIABLE_ARITY = 1 << 5;
+    /** Is this declared in a dynamic context */
+    public static final int IN_DYNAMIC_CONTEXT = 1 << 6;
 
     /** Flag for strict or built-in functions */
     public static final int IS_STRICT_OR_BUILTIN = IS_STRICT | IS_BUILTIN;
@@ -79,39 +105,43 @@
     /**
      * Constructor
      *
-     * @param name          script function name
-     * @param arity         arity
-     * @param flags         the function flags
+     * @param name  script function name
+     * @param arity arity
+     * @param flags the function flags
      */
     ScriptFunctionData(final String name, final int arity, final int flags) {
         this.name  = name;
-        this.arity = arity;
-        this.code  = new CompiledFunctions();
         this.flags = flags;
+        setArity(arity);
     }
 
     final int getArity() {
         return arity;
     }
 
+    final boolean isVariableArity() {
+        return (flags & IS_VARIABLE_ARITY) != 0;
+    }
+
     /**
      * Used from e.g. Native*$Constructors as an explicit call. TODO - make arity immutable and final
      * @param arity new arity
      */
     void setArity(final int arity) {
+        if(arity < 0 || arity > MAX_ARITY) {
+            throw new IllegalArgumentException(String.valueOf(arity));
+        }
         this.arity = arity;
     }
 
     CompiledFunction bind(final CompiledFunction originalInv, final ScriptFunction fn, final Object self, final Object[] args) {
-        final MethodHandle boundInvoker = bindInvokeHandle(originalInv.getInvoker(), fn, self, args);
+        final MethodHandle boundInvoker = bindInvokeHandle(originalInv.createComposableInvoker(), fn, self, args);
 
-        //TODO the boundinvoker.type() could actually be more specific here
         if (isConstructor()) {
-            ensureConstructor(originalInv);
-            return new CompiledFunction(boundInvoker.type(), boundInvoker, bindConstructHandle(originalInv.getConstructor(), fn, args));
+            return new CompiledFunction(boundInvoker, bindConstructHandle(originalInv.createComposableConstructor(), fn, args));
         }
 
-        return new CompiledFunction(boundInvoker.type(), boundInvoker);
+        return new CompiledFunction(boundInvoker);
     }
 
     /**
@@ -122,6 +152,15 @@
         return (flags & IS_STRICT) != 0;
     }
 
+    /**
+     * Return the complete internal function name for this
+     * data, not anonymous or similar. May be identical
+     * @return internal function name
+     */
+    protected String getFunctionName() {
+        return getName();
+    }
+
     boolean isBuiltin() {
         return (flags & IS_BUILTIN) != 0;
     }
@@ -130,11 +169,7 @@
         return (flags & IS_CONSTRUCTOR) != 0;
     }
 
-    boolean needsCallee() {
-        // we don't know if we need a callee or not unless code has been compiled
-        ensureCompiled();
-        return (flags & NEEDS_CALLEE) != 0;
-    }
+    abstract boolean needsCallee();
 
     /**
      * Returns true if this is a non-strict, non-built-in function that requires non-primitive this argument
@@ -161,6 +196,14 @@
      */
     @Override
     public String toString() {
+        return name.isEmpty() ? "<anonymous>" : name;
+    }
+
+    /**
+     * Verbose description of data
+     * @return verbose description
+     */
+    public String toStringVerbose() {
         final StringBuilder sb = new StringBuilder();
 
         sb.append("name='").
@@ -181,44 +224,26 @@
      * and not suddenly a "real" object
      *
      * @param callSiteType callsite type
-     * @param args         arguments at callsite on first trampoline invocation
-     * @return method handle to best invoker
+     * @return compiled function object representing the best invoker.
      */
-    MethodHandle getBestInvoker(final MethodType callSiteType, final Object[] args) {
-        return getBest(callSiteType).getInvoker();
+     final CompiledFunction getBestInvoker(final MethodType callSiteType, final ScriptObject runtimeScope) {
+        final CompiledFunction cf = getBest(callSiteType, runtimeScope);
+        assert cf != null;
+        return cf;
     }
 
-    MethodHandle getBestInvoker(final MethodType callSiteType) {
-        return getBestInvoker(callSiteType, null);
-    }
-
-    MethodHandle getBestConstructor(final MethodType callSiteType, final Object[] args) {
+    final CompiledFunction getBestConstructor(final MethodType callSiteType, final ScriptObject runtimeScope) {
         if (!isConstructor()) {
             throw typeError("not.a.constructor", toSource());
         }
-        ensureCodeGenerated();
-
-        final CompiledFunction best = getBest(callSiteType);
-        ensureConstructor(best);
-        return best.getConstructor();
-    }
-
-    MethodHandle getBestConstructor(final MethodType callSiteType) {
-        return getBestConstructor(callSiteType, null);
-    }
-
-    /**
-     * Subclass responsibility. If we can have lazy code generation, this is a hook to ensure that
-     * code exists before performing an operation.
-     */
-    protected void ensureCodeGenerated() {
-        //empty
+        // Constructor call sites don't have a "this", but getBest is meant to operate on "callee, this, ..." style
+        final CompiledFunction cf = getBest(callSiteType.insertParameterTypes(1, Object.class), runtimeScope);
+        return cf;
     }
 
     /**
      * If we can have lazy code generation, this is a hook to ensure that the code has been compiled.
-     * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance;
-     * use {@link #ensureCodeGenerated()} to install the actual method handles.
+     * This does not guarantee the code been installed in this {@code ScriptFunctionData} instance
      */
     protected void ensureCompiled() {
         //empty
@@ -229,27 +254,139 @@
      * is generated, get the most generic of all versions of this function and adapt it
      * to Objects.
      *
-     * TODO this is only public because {@link JavaAdapterFactory} can't supply us with
-     * a MethodType that we can use for lookup due to boostrapping problems. Can be fixed
-     *
+     * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
+     * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
+     * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
      * @return generic invoker of this script function
      */
-    public final MethodHandle getGenericInvoker() {
-        ensureCodeGenerated();
-        return code.generic().getInvoker();
+    final MethodHandle getGenericInvoker(final ScriptObject runtimeScope) {
+        // This method has race conditions both on genericsInvoker and genericsInvoker.invoker, but even if invoked
+        // concurrently, they'll create idempotent results, so it doesn't matter. We could alternatively implement this
+        // using java.util.concurrent.AtomicReferenceFieldUpdater, but it's hardly worth it.
+        final GenericInvokers lgenericInvokers = ensureGenericInvokers();
+        MethodHandle invoker = lgenericInvokers.invoker;
+        if(invoker == null) {
+            lgenericInvokers.invoker = invoker = createGenericInvoker(runtimeScope);
+        }
+        return invoker;
     }
 
-    final MethodHandle getGenericConstructor() {
-        ensureCodeGenerated();
-        ensureConstructor(code.generic());
-        return code.generic().getConstructor();
+    private MethodHandle createGenericInvoker(final ScriptObject runtimeScope) {
+        return makeGenericMethod(getGeneric(runtimeScope).createComposableInvoker());
     }
 
-    private CompiledFunction getBest(final MethodType callSiteType) {
-        ensureCodeGenerated();
-        return code.best(callSiteType);
+    final MethodHandle getGenericConstructor(final ScriptObject runtimeScope) {
+        // This method has race conditions both on genericsInvoker and genericsInvoker.constructor, but even if invoked
+        // concurrently, they'll create idempotent results, so it doesn't matter. We could alternatively implement this
+        // using java.util.concurrent.AtomicReferenceFieldUpdater, but it's hardly worth it.
+        final GenericInvokers lgenericInvokers = ensureGenericInvokers();
+        MethodHandle constructor = lgenericInvokers.constructor;
+        if(constructor == null) {
+            lgenericInvokers.constructor = constructor = createGenericConstructor(runtimeScope);
+        }
+        return constructor;
     }
 
+    private MethodHandle createGenericConstructor(final ScriptObject runtimeScope) {
+        return makeGenericMethod(getGeneric(runtimeScope).createComposableConstructor());
+    }
+
+    private GenericInvokers ensureGenericInvokers() {
+        GenericInvokers lgenericInvokers = genericInvokers;
+        if(lgenericInvokers == null) {
+            genericInvokers = lgenericInvokers = new GenericInvokers();
+        }
+        return lgenericInvokers;
+    }
+
+    private static MethodType widen(final MethodType cftype) {
+        final Class<?>[] paramTypes = new Class<?>[cftype.parameterCount()];
+        for (int i = 0; i < cftype.parameterCount(); i++) {
+            paramTypes[i] = cftype.parameterType(i).isPrimitive() ? cftype.parameterType(i) : Object.class;
+        }
+        return MH.type(cftype.returnType(), paramTypes);
+    }
+
+    /**
+     * Used to find an apply to call version that fits this callsite.
+     * We cannot just, as in the normal matcher case, return e.g. (Object, Object, int)
+     * for (Object, Object, int, int, int) or we will destroy the semantics and get
+     * a function that, when padded with undefineds, behaves differently
+     * @param type actual call site type
+     * @return apply to call that perfectly fits this callsite or null if none found
+     */
+    CompiledFunction lookupExactApplyToCall(final MethodType type) {
+        for (final CompiledFunction cf : code) {
+            if (!cf.isApplyToCall()) {
+                continue;
+            }
+
+            final MethodType cftype = cf.type();
+            if (cftype.parameterCount() != type.parameterCount()) {
+                continue;
+            }
+
+            if (widen(cftype).equals(widen(type))) {
+                return cf;
+            }
+        }
+
+        return null;
+    }
+
+    CompiledFunction pickFunction(final MethodType callSiteType, final boolean canPickVarArg) {
+        for (final CompiledFunction candidate : code) {
+            if (candidate.matchesCallSite(callSiteType, canPickVarArg)) {
+                return candidate;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns the best function for the specified call site type.
+     * @param callSiteType The call site type. Call site types are expected to have the form
+     * {@code (callee, this[, args...])}.
+     * @param runtimeScope the runtime scope. It can be used to evaluate types of scoped variables to guide the
+     * optimistic compilation, should the call to this method trigger code compilation. Can be null if current runtime
+     * scope is not known, but that might cause compilation of code that will need more deoptimization passes.
+     * @return the best function for the specified call site type.
+     */
+    CompiledFunction getBest(final MethodType callSiteType, final ScriptObject runtimeScope) {
+        assert callSiteType.parameterCount() >= 2 : callSiteType; // Must have at least (callee, this)
+        assert callSiteType.parameterType(0).isAssignableFrom(ScriptFunction.class) : callSiteType; // Callee must be assignable from script function
+
+        if (isRecompilable()) {
+            final CompiledFunction candidate = pickFunction(callSiteType, false);
+            if (candidate != null) {
+                return candidate;
+            }
+            return pickFunction(callSiteType, true); //try vararg last
+        }
+
+        CompiledFunction best = null;
+        for(final CompiledFunction candidate: code) {
+            if(candidate.betterThanFinal(best, callSiteType)) {
+                best = candidate;
+            }
+        }
+
+        return best;
+    }
+
+
+    abstract boolean isRecompilable();
+
+    CompiledFunction getGeneric(final ScriptObject runtimeScope) {
+        return getBest(getGenericType(), runtimeScope);
+    }
+
+    /**
+     * Get a method type for a generic invoker.
+     * @return the method type for the generic invoker
+     */
+    abstract MethodType getGenericType();
+
     /**
      * Allocates an object using this function's allocator.
      *
@@ -278,91 +415,17 @@
      * @param args additional arguments to bind. Can be null.
      */
     ScriptFunctionData makeBoundFunctionData(final ScriptFunction fn, final Object self, final Object[] args) {
-        ensureCodeGenerated();
-
         final Object[] allArgs = args == null ? ScriptRuntime.EMPTY_ARRAY : args;
         final int length = args == null ? 0 : args.length;
         // Clear the callee and this flags
         final int boundFlags = flags & ~NEEDS_CALLEE & ~USES_THIS;
 
-        CompiledFunctions boundList = new CompiledFunctions();
-        if (code.size() == 1) {
-            // only one variant - bind that
-            boundList.add(bind(code.first(), fn, self, allArgs));
-        } else {
-            // There are specialized versions. Get the most generic one.
-            // This is to avoid ambiguous overloaded versions of bound and
-            // specialized variants and choosing wrong overload.
-            final MethodHandle genInvoker = getGenericInvoker();
-            final CompiledFunction inv = new CompiledFunction(genInvoker.type(), genInvoker, getGenericConstructor());
-            boundList.add(bind(inv, fn, self, allArgs));
-        }
+        final List<CompiledFunction> boundList = new LinkedList<>();
+        final ScriptObject runtimeScope = fn.getScope();
+        final CompiledFunction bindTarget = new CompiledFunction(getGenericInvoker(runtimeScope), getGenericConstructor(runtimeScope));
+        boundList.add(bind(bindTarget, fn, self, allArgs));
 
-        return new FinalScriptFunctionData(name, arity == -1 ? -1 : Math.max(0, arity - length), boundList, boundFlags);
-    }
-
-    /**
-     * Compose a constructor given a primordial constructor handle.
-     *
-     * @param ctor primordial constructor handle
-     * @return the composed constructor
-     */
-    protected MethodHandle composeConstructor(final MethodHandle ctor) {
-        // If it was (callee, this, args...), permute it to (this, callee, args...). We're doing this because having
-        // "this" in the first argument position is what allows the elegant folded composition of
-        // (newFilter x constructor x allocator) further down below in the code. Also, ensure the composite constructor
-        // always returns Object.
-        final boolean needsCallee = needsCallee(ctor);
-        MethodHandle composedCtor = needsCallee ? swapCalleeAndThis(ctor) : ctor;
-
-        composedCtor = changeReturnTypeToObject(composedCtor);
-
-        final MethodType ctorType = composedCtor.type();
-
-        // Construct a dropping type list for NEWFILTER, but don't include constructor "this" into it, so it's actually
-        // captured as "allocation" parameter of NEWFILTER after we fold the constructor into it.
-        // (this, [callee, ]args...) => ([callee, ]args...)
-        final Class<?>[] ctorArgs = ctorType.dropParameterTypes(0, 1).parameterArray();
-
-        // Fold constructor into newFilter that replaces the return value from the constructor with the originally
-        // allocated value when the originally allocated value is a primitive.
-        // (result, this, [callee, ]args...) x (this, [callee, ]args...) => (this, [callee, ]args...)
-        composedCtor = MH.foldArguments(MH.dropArguments(NEWFILTER, 2, ctorArgs), composedCtor);
-
-        // allocate() takes a ScriptFunction and returns a newly allocated ScriptObject...
-        if (needsCallee) {
-            // ...we either fold it into the previous composition, if we need both the ScriptFunction callee object and
-            // the newly allocated object in the arguments, so (this, callee, args...) x (callee) => (callee, args...),
-            // or...
-            return MH.foldArguments(composedCtor, ScriptFunction.ALLOCATE);
-        }
-
-        // ...replace the ScriptFunction argument with the newly allocated object, if it doesn't need the callee
-        // (this, args...) filter (callee) => (callee, args...)
-        return MH.filterArguments(composedCtor, 0, ScriptFunction.ALLOCATE);
-    }
-
-    /**
-     * If this function's method handles need a callee parameter, swap the order of first two arguments for the passed
-     * method handle. If this function's method handles don't need a callee parameter, returns the original method
-     * handle unchanged.
-     *
-     * @param mh a method handle with order of arguments {@code (callee, this, args...)}
-     *
-     * @return a method handle with order of arguments {@code (this, callee, args...)}
-     */
-    private static MethodHandle swapCalleeAndThis(final MethodHandle mh) {
-        final MethodType type = mh.type();
-        assert type.parameterType(0) == ScriptFunction.class : type;
-        assert type.parameterType(1) == Object.class : type;
-        final MethodType newType = type.changeParameterType(0, Object.class).changeParameterType(1, ScriptFunction.class);
-        final int[] reorder = new int[type.parameterCount()];
-        reorder[0] = 1;
-        assert reorder[1] == 0;
-        for (int i = 2; i < reorder.length; ++i) {
-            reorder[i] = i;
-        }
-        return MethodHandles.permuteArguments(mh, newType, reorder);
+        return new FinalScriptFunctionData(name, Math.max(0, getArity() - length), boundList, boundFlags);
     }
 
     /**
@@ -373,7 +436,11 @@
      * @return the converted this object
      */
     private Object convertThisObject(final Object thiz) {
-        if (!(thiz instanceof ScriptObject) && needsWrappedThis()) {
+        return needsWrappedThis() ? wrapThis(thiz) : thiz;
+    }
+
+    static Object wrapThis(final Object thiz) {
+        if (!(thiz instanceof ScriptObject)) {
             if (JSType.nullOrUndefined(thiz)) {
                 return Context.getGlobal();
             }
@@ -440,7 +507,7 @@
         } else {
             // If target is already bound, insert additional bound arguments after "this" argument, at position 1.
             final int argInsertPos = isTargetBound ? 1 : 0;
-            final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount() - argInsertPos, args.length + (isTargetBound ? 0 : (needsCallee  ? 2 : 1)))];
+            final Object[] boundArgs = new Object[Math.min(originalInvoker.type().parameterCount() - argInsertPos, args.length + (isTargetBound ? 0 : needsCallee  ? 2 : 1))];
             int next = 0;
             if (!isTargetBound) {
                 if (needsCallee) {
@@ -506,6 +573,38 @@
     }
 
     /**
+     * Takes a method handle, and returns a potentially different method handle that can be used in
+     * {@code ScriptFunction#invoke(Object, Object...)} or {code ScriptFunction#construct(Object, Object...)}.
+     * The returned method handle will be sure to return {@code Object}, and will have all its parameters turned into
+     * {@code Object} as well, except for the following ones:
+     * <ul>
+     *   <li>a last parameter of type {@code Object[]} which is used for vararg functions,</li>
+     *   <li>the first argument, which is forced to be {@link ScriptFunction}, in case the function receives itself
+     *   (callee) as an argument.</li>
+     * </ul>
+     *
+     * @param mh the original method handle
+     *
+     * @return the new handle, conforming to the rules above.
+     */
+    private static MethodHandle makeGenericMethod(final MethodHandle mh) {
+        final MethodType type = mh.type();
+        final MethodType newType = makeGenericType(type);
+        return type.equals(newType) ? mh : mh.asType(newType);
+    }
+
+    private static MethodType makeGenericType(final MethodType type) {
+        MethodType newType = type.generic();
+        if (isVarArg(type)) {
+            newType = newType.changeParameterType(type.parameterCount() - 1, Object[].class);
+        }
+        if (needsCallee(type)) {
+            newType = newType.changeParameterType(0, ScriptFunction.class);
+        }
+        return newType;
+    }
+
+    /**
      * Execute this script function.
      *
      * @param self  Target object.
@@ -515,9 +614,9 @@
      * @throws Throwable if there is an exception/error with the invocation or thrown from it
      */
     Object invoke(final ScriptFunction fn, final Object self, final Object... arguments) throws Throwable {
-        final MethodHandle mh  = getGenericInvoker();
-        final Object   selfObj = convertThisObject(self);
-        final Object[] args    = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
+        final MethodHandle mh      = getGenericInvoker(fn.getScope());
+        final Object       selfObj = convertThisObject(self);
+        final Object[]     args    = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
 
         DebuggerSupport.notifyInvoke(mh);
 
@@ -571,7 +670,7 @@
     }
 
     Object construct(final ScriptFunction fn, final Object... arguments) throws Throwable {
-        final MethodHandle mh   = getGenericConstructor();
+        final MethodHandle mh   = getGenericConstructor(fn.getScope());
         final Object[]     args = arguments == null ? ScriptRuntime.EMPTY_ARRAY : arguments;
 
         DebuggerSupport.notifyInvoke(mh);
@@ -690,24 +789,6 @@
     }
 
     /**
-     * Adapts the method handle so its return type is {@code Object}. If the handle's return type is already
-     * {@code Object}, the handle is returned unchanged.
-     *
-     * @param mh the handle to adapt
-     * @return the adapted handle
-     */
-    private static MethodHandle changeReturnTypeToObject(final MethodHandle mh) {
-        final MethodType type = mh.type();
-        return (type.returnType() == Object.class) ? mh : MH.asType(mh, type.changeReturnType(Object.class));
-    }
-
-    private void ensureConstructor(final CompiledFunction inv) {
-        if (!inv.hasConstructor()) {
-            inv.setConstructor(composeConstructor(inv.getInvoker()));
-        }
-    }
-
-    /**
      * Heuristic to figure out if the method handle has a callee argument. If it's type is
      * {@code (ScriptFunction, ...)}, then we'll assume it has a callee argument. We need this as
      * the constructor above is not passed this information, and can't just blindly assume it's false
@@ -719,8 +800,18 @@
      * @return true if the method handle expects a callee, false otherwise
      */
     protected static boolean needsCallee(final MethodHandle mh) {
-        final MethodType type = mh.type();
-        return (type.parameterCount() > 0 && type.parameterType(0) == ScriptFunction.class);
+        return needsCallee(mh.type());
+    }
+
+    static boolean needsCallee(final MethodType type) {
+        final int length = type.parameterCount();
+
+        if (length == 0) {
+            return false;
+        }
+
+        final Class<?> param0 = type.parameterType(0);
+        return param0 == ScriptFunction.class || param0 == boolean.class && length > 1 && type.parameterType(1) == ScriptFunction.class;
     }
 
     /**
@@ -731,10 +822,21 @@
      * @return true if vararg
      */
     protected static boolean isVarArg(final MethodHandle mh) {
-        final MethodType type = mh.type();
+        return isVarArg(mh.type());
+    }
+
+    static boolean isVarArg(final MethodType type) {
         return type.parameterType(type.parameterCount() - 1).isArray();
     }
 
+    /**
+     * Is this ScriptFunction declared in a dynamic context
+     * @return true if in dynamic context, false if not or irrelevant
+     */
+    public boolean inDynamicContext() {
+        return false;
+    }
+
     @SuppressWarnings("unused")
     private static Object[] bindVarArgs(final Object[] array1, final Object[] array2) {
         if (array2 == null) {
@@ -755,12 +857,22 @@
         return concat;
     }
 
-    @SuppressWarnings("unused")
-    private static Object newFilter(final Object result, final Object allocation) {
-        return (result instanceof ScriptObject || !JSType.isPrimitive(result))? result : allocation;
-    }
-
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), ScriptFunctionData.class, name, MH.type(rtype, types));
     }
+
+    /**
+     * This class is used to hold the generic invoker and generic constructor pair. It is structured in this way since
+     * most functions will never use them, so this way ScriptFunctionData only pays storage cost for one null reference
+     * to the GenericInvokers object, instead of two null references for the two method handles.
+     */
+    private static final class GenericInvokers {
+        volatile MethodHandle invoker;
+        volatile MethodHandle constructor;
+    }
+
+    private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException {
+        in.defaultReadObject();
+        code = new LinkedList<>();
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java
index 52c98d4..b2a54be 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java
@@ -26,7 +26,6 @@
 package jdk.nashorn.internal.runtime;
 
 import java.security.CodeSource;
-import java.security.ProtectionDomain;
 
 /**
  * Responsible for loading script generated classes.
@@ -50,7 +49,7 @@
     }
 
     @Override
-    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+    protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
         checkPackageAccess(name);
         if (name.startsWith(NASHORN_PKG_PREFIX)) {
             return context.getSharedLoader().loadClass(name);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
index deae803..a8bf18c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java
@@ -25,11 +25,16 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCall;
 import static jdk.nashorn.internal.codegen.CompilerConstants.virtualCallNoLookup;
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_DOUBLE;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_INT;
+import static jdk.nashorn.internal.runtime.JSType.UNDEFINED_LONG;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.CONFIGURABLE;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.ENUMERABLE;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.GET;
@@ -37,8 +42,11 @@
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.VALUE;
 import static jdk.nashorn.internal.runtime.PropertyDescriptor.WRITABLE;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
 import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
+import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
@@ -55,18 +63,18 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.lookup.Lookup;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.objects.AccessorPropertyDescriptor;
 import jdk.nashorn.internal.objects.DataPropertyDescriptor;
 import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeArray;
 import jdk.nashorn.internal.runtime.arrays.ArrayData;
 import jdk.nashorn.internal.runtime.arrays.ArrayIndex;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -95,24 +103,30 @@
     public static final String PROTO_PROPERTY_NAME   = "__proto__";
 
     /** Search fall back routine name for "no such method" */
-    static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";
+    public static final String NO_SUCH_METHOD_NAME   = "__noSuchMethod__";
 
     /** Search fall back routine name for "no such property" */
-    static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
+    public static final String NO_SUCH_PROPERTY_NAME = "__noSuchProperty__";
 
     /** Per ScriptObject flag - is this a scope object? */
-    public static final int IS_SCOPE       = 0b0000_0001;
+    public static final int IS_SCOPE       = 1 << 0;
 
     /** Per ScriptObject flag - is this an array object? */
-    public static final int IS_ARRAY       = 0b0000_0010;
+    public static final int IS_ARRAY       = 1 << 1;
 
     /** Per ScriptObject flag - is this an arguments object? */
-    public static final int IS_ARGUMENTS   = 0b0000_0100;
+    public static final int IS_ARGUMENTS   = 1 << 2;
 
     /** Is length property not-writable? */
-    public static final int IS_LENGTH_NOT_WRITABLE = 0b0001_0000;
+    public static final int IS_LENGTH_NOT_WRITABLE = 1 << 3;
 
-    /** Spill growth rate - by how many elements does {@link ScriptObject#spill} when full */
+    /** Is this a builtin object? */
+    public static final int IS_BUILTIN = 1 << 4;
+
+    /**
+     * Spill growth rate - by how many elements does {@link ScriptObject#primitiveSpill} and
+     * {@link ScriptObject#objectSpill} when full
+     */
     public static final int SPILL_RATE = 8;
 
     /** Map to property information and accessor functions. Ordered by insertion. */
@@ -124,26 +138,41 @@
     /** Object flags. */
     private int flags;
 
-    /** Area for properties added to object after instantiation, see {@link AccessorProperty} */
-    public Object[] spill;
+    /** Area for primitive properties added to object after instantiation, see {@link AccessorProperty} */
+    protected long[]   primitiveSpill;
+
+    /** Area for reference properties added to object after instantiation, see {@link AccessorProperty} */
+    protected Object[] objectSpill;
+
+    /**
+     * Number of elements in the spill. This may be less than the spill array lengths, if not all of
+     * the allocated memory is in use
+     */
+    private int spillLength;
 
     /** Indexed array data. */
     private ArrayData arrayData;
 
-    /** Method handle to retrive prototype of this object */
-    public static final MethodHandle GETPROTO           = findOwnMH("getProto", ScriptObject.class);
-    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH("megamorphicGet", Object.class, String.class, boolean.class);
-    static final MethodHandle GLOBALFILTER       = findOwnMH("globalFilter", Object.class, Object.class);
+    /** Method handle to retrieve prototype of this object */
+    public static final MethodHandle GETPROTO      = findOwnMH_V("getProto", ScriptObject.class);
 
-    static final MethodHandle SETFIELD           = findOwnMH("setField",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class);
-    static final MethodHandle SETSPILL           = findOwnMH("setSpill",         void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
-    static final MethodHandle SETSPILLWITHNEW    = findOwnMH("setSpillWithNew",  void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class);
-    static final MethodHandle SETSPILLWITHGROW   = findOwnMH("setSpillWithGrow", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, int.class, Object.class, Object.class);
+    static final MethodHandle MEGAMORPHIC_GET    = findOwnMH_V("megamorphicGet", Object.class, String.class, boolean.class);
+    static final MethodHandle GLOBALFILTER       = findOwnMH_S("globalFilter", Object.class, Object.class);
 
-    private static final MethodHandle TRUNCATINGFILTER   = findOwnMH("truncatingFilter", Object[].class, int.class, Object[].class);
-    private static final MethodHandle KNOWNFUNCPROPGUARD = findOwnMH("knownFunctionPropertyGuard", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, Object.class, ScriptFunction.class);
+    private static final MethodHandle TRUNCATINGFILTER   = findOwnMH_S("truncatingFilter", Object[].class, int.class, Object[].class);
+    private static final MethodHandle KNOWNFUNCPROPGUARDSELF = findOwnMH_S("knownFunctionPropertyGuardSelf", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, ScriptFunction.class);
+    private static final MethodHandle KNOWNFUNCPROPGUARDPROTO = findOwnMH_S("knownFunctionPropertyGuardProto", boolean.class, Object.class, PropertyMap.class, MethodHandle.class, int.class, ScriptFunction.class);
 
-    private static final ArrayList<MethodHandle> protoFilters = new ArrayList<>();
+    private static final ArrayList<MethodHandle> PROTO_FILTERS = new ArrayList<>();
+
+    /** Method handle for getting the array data */
+    public static final Call GET_ARRAY          = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArray", ArrayData.class);
+
+    /** Method handle for getting the property map - debugging purposes */
+    public static final Call GET_MAP            = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getMap", PropertyMap.class);
+
+    /** Method handle for setting the array data */
+    public static final Call SET_ARRAY          = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setArray", void.class, ArrayData.class);
 
     /** Method handle for getting a function argument at a given index. Used from MapCreator */
     public static final Call GET_ARGUMENT       = virtualCall(MethodHandles.lookup(), ScriptObject.class, "getArgument", Object.class, int.class);
@@ -154,15 +183,33 @@
     /** Method handle for getting the proto of a ScriptObject */
     public static final Call GET_PROTO          = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class);
 
+    /** Method handle for getting the proto of a ScriptObject */
+    public static final Call GET_PROTO_DEPTH    = virtualCallNoLookup(ScriptObject.class, "getProto", ScriptObject.class, int.class);
+
     /** Method handle for setting the proto of a ScriptObject */
-    public static final Call SET_PROTO          = virtualCallNoLookup(ScriptObject.class, "setInitialProto", void.class, ScriptObject.class);
+    public static final Call SET_GLOBAL_OBJECT_PROTO = staticCallNoLookup(ScriptObject.class, "setGlobalObjectProto", void.class, ScriptObject.class);
 
     /** Method handle for setting the proto of a ScriptObject after checking argument */
     public static final Call SET_PROTO_FROM_LITERAL    = virtualCallNoLookup(ScriptObject.class, "setProtoFromLiteral", void.class, Object.class);
 
     /** Method handle for setting the user accessors of a ScriptObject */
+    //TODO fastpath this
     public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class);
 
+    static final MethodHandle[] SET_SLOW = new MethodHandle[] {
+        findOwnMH_V("set", void.class, Object.class, int.class, boolean.class),
+        findOwnMH_V("set", void.class, Object.class, long.class, boolean.class),
+        findOwnMH_V("set", void.class, Object.class, double.class, boolean.class),
+        findOwnMH_V("set", void.class, Object.class, Object.class, boolean.class)
+    };
+
+    /** Method handle to reset the map of this ScriptObject */
+    public static final Call SET_MAP = virtualCallNoLookup(ScriptObject.class, "setMap", void.class, PropertyMap.class);
+
+    static final MethodHandle CAS_MAP           = findOwnMH_V("compareAndSetMap", boolean.class, PropertyMap.class, PropertyMap.class);
+    static final MethodHandle EXTENSION_CHECK   = findOwnMH_V("extensionCheck", boolean.class, boolean.class, String.class);
+    static final MethodHandle ENSURE_SPILL_SIZE = findOwnMH_V("ensureSpillSize", Object.class, int.class);
+
     /**
      * Constructor
      */
@@ -179,7 +226,6 @@
         if (Context.DEBUG) {
             ScriptObject.count++;
         }
-
         this.arrayData = ArrayData.EMPTY_ARRAY;
         this.setMap(map == null ? PropertyMap.newMap() : map);
     }
@@ -194,16 +240,50 @@
      * @param map intial {@link PropertyMap}
      */
     protected ScriptObject(final ScriptObject proto, final PropertyMap map) {
-        if (Context.DEBUG) {
-            ScriptObject.count++;
-        }
-
-        this.arrayData = ArrayData.EMPTY_ARRAY;
-        this.setMap(map == null ? PropertyMap.newMap() : map);
+        this(map);
         this.proto = proto;
     }
 
     /**
+     * Constructor used to instantiate spill properties directly. Used from
+     * SpillObjectCreator.
+     *
+     * @param map            property maps
+     * @param primitiveSpill primitive spills
+     * @param objectSpill    reference spills
+     */
+    public ScriptObject(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+        this(map);
+        this.primitiveSpill = primitiveSpill;
+        this.objectSpill    = objectSpill;
+        assert primitiveSpill.length == objectSpill.length : " primitive spill pool size is not the same length as object spill pool size";
+        this.spillLength = spillAllocationLength(primitiveSpill.length);
+    }
+
+    /**
+     * Check whether this is a global object
+     * @return true if global
+     */
+    protected boolean isGlobal() {
+        return false;
+    }
+
+    private static int alignUp(final int size, final int alignment) {
+        return size + alignment - 1 & ~(alignment - 1);
+    }
+
+    /**
+     * Given a number of properties, return the aligned to SPILL_RATE
+     * buffer size required for the smallest spill pool needed to
+     * house them
+     * @param nProperties number of properties
+     * @return property buffer length, a multiple of SPILL_RATE
+     */
+    public static int spillAllocationLength(final int nProperties) {
+        return alignUp(nProperties, SPILL_RATE);
+    }
+
+    /**
      * Copy all properties from the source object with their receiver bound to the source.
      * This function was known as mergeMap
      *
@@ -386,10 +466,10 @@
 
             if (property instanceof UserAccessorProperty) {
                 return global.newAccessorDescriptor(
-                    (get != null) ?
+                    get != null ?
                         get :
                         UNDEFINED,
-                    (set != null) ?
+                    set != null ?
                         set :
                         UNDEFINED,
                     configurable,
@@ -456,12 +536,12 @@
             }
             return false;
         }
+
         // modifying an existing property
-        final PropertyDescriptor currentDesc = (PropertyDescriptor) current;
+        final PropertyDescriptor currentDesc = (PropertyDescriptor)current;
         final PropertyDescriptor newDesc     = desc;
 
-        if (newDesc.type() == PropertyDescriptor.GENERIC &&
-            ! newDesc.has(CONFIGURABLE) && ! newDesc.has(ENUMERABLE)) {
+        if (newDesc.type() == PropertyDescriptor.GENERIC && !newDesc.has(CONFIGURABLE) && !newDesc.has(ENUMERABLE)) {
             // every descriptor field is absent
             return true;
         }
@@ -471,7 +551,7 @@
             return true;
         }
 
-        if (! currentDesc.isConfigurable()) {
+        if (!currentDesc.isConfigurable()) {
             if (newDesc.has(CONFIGURABLE) && newDesc.isConfigurable()) {
                 // not configurable can not be made configurable
                 if (reject) {
@@ -494,10 +574,11 @@
         Property property = getMap().findProperty(key);
 
         if (currentDesc.type() == PropertyDescriptor.DATA &&
-            (newDesc.type() == PropertyDescriptor.DATA || newDesc.type() == PropertyDescriptor.GENERIC)) {
-            if (! currentDesc.isConfigurable() && ! currentDesc.isWritable()) {
+                (newDesc.type() == PropertyDescriptor.DATA ||
+                 newDesc.type() == PropertyDescriptor.GENERIC)) {
+            if (!currentDesc.isConfigurable() && !currentDesc.isWritable()) {
                 if (newDesc.has(WRITABLE) && newDesc.isWritable() ||
-                    newDesc.has(VALUE) && ! ScriptRuntime.sameValue(currentDesc.getValue(), newDesc.getValue())) {
+                    newDesc.has(VALUE) && !ScriptRuntime.sameValue(currentDesc.getValue(), newDesc.getValue())) {
                     if (reject) {
                         throw typeError(global, "cant.redefine.property", name, ScriptRuntime.safeToString(this));
                     }
@@ -506,11 +587,20 @@
             }
 
             final boolean newValue = newDesc.has(VALUE);
-            final Object value     = newValue? newDesc.getValue() : currentDesc.getValue();
+            final Object value     = newValue ? newDesc.getValue() : currentDesc.getValue();
+
             if (newValue && property != null) {
                 // Temporarily clear flags.
                 property = modifyOwnProperty(property, 0);
                 set(key, value, false);
+                //this might change the map if we change types of the property
+                //hence we need to read it again. note that we should probably
+                //have the setter return the new property throughout and in
+                //general respect Property return values from modify and add
+                //functions - which we don't seem to do at all here :-(
+                //There is already a bug filed to generify PropertyAccess so we
+                //can have the setter return e.g. a Property
+                property = getMap().findProperty(key);
             }
 
             if (property == null) {
@@ -524,23 +614,22 @@
         } else if (currentDesc.type() == PropertyDescriptor.ACCESSOR &&
                    (newDesc.type() == PropertyDescriptor.ACCESSOR ||
                     newDesc.type() == PropertyDescriptor.GENERIC)) {
-            if (! currentDesc.isConfigurable()) {
-                if (newDesc.has(PropertyDescriptor.GET) && ! ScriptRuntime.sameValue(currentDesc.getGetter(), newDesc.getGetter()) ||
-                    newDesc.has(PropertyDescriptor.SET) && ! ScriptRuntime.sameValue(currentDesc.getSetter(), newDesc.getSetter())) {
+            if (!currentDesc.isConfigurable()) {
+                if (newDesc.has(PropertyDescriptor.GET) && !ScriptRuntime.sameValue(currentDesc.getGetter(), newDesc.getGetter()) ||
+                    newDesc.has(PropertyDescriptor.SET) && !ScriptRuntime.sameValue(currentDesc.getSetter(), newDesc.getSetter())) {
                     if (reject) {
                         throw typeError(global, "cant.redefine.property", name, ScriptRuntime.safeToString(this));
                     }
                     return false;
                 }
             }
-
             // New set the new features.
             modifyOwnProperty(property, propFlags,
                                       newDesc.has(GET) ? newDesc.getGetter() : currentDesc.getGetter(),
                                       newDesc.has(SET) ? newDesc.getSetter() : currentDesc.getSetter());
         } else {
             // changing descriptor type
-            if (! currentDesc.isConfigurable()) {
+            if (!currentDesc.isConfigurable()) {
                 // not configurable can not be made configurable
                 if (reject) {
                     throw typeError(global, "cant.redefine.property", name, ScriptRuntime.safeToString(this));
@@ -552,7 +641,7 @@
 
             // Preserve only configurable and enumerable from current desc
             // if those are not overridden in the new property descriptor.
-            boolean value = newDesc.has(CONFIGURABLE)? newDesc.isConfigurable() : currentDesc.isConfigurable();
+            boolean value = newDesc.has(CONFIGURABLE) ? newDesc.isConfigurable() : currentDesc.isConfigurable();
             if (!value) {
                 propFlags |= Property.NOT_CONFIGURABLE;
             }
@@ -565,7 +654,7 @@
             if (type == PropertyDescriptor.DATA) {
                 // get writable from the new descriptor
                 value = newDesc.has(WRITABLE) && newDesc.isWritable();
-                if (! value) {
+                if (!value) {
                     propFlags |= Property.NOT_WRITABLE;
                 }
 
@@ -602,7 +691,9 @@
     public void defineOwnProperty(final int index, final Object value) {
         assert isValidArrayIndex(index) : "invalid array index";
         final long longIndex = ArrayIndex.toLongIndex(index);
-        setValueAtArrayIndex(longIndex, index, value, false);
+        doesNotHaveEnsureDelete(longIndex, getArray().length(), false);
+        setArray(getArray().ensure(longIndex));
+        setArray(getArray().set(index, value, false));
     }
 
     private void checkIntegerKey(final String key) {
@@ -761,9 +852,7 @@
      * @return New property.
      */
     public final Property addOwnProperty(final String key, final int propertyFlags, final Object value) {
-        final Property property = addSpillProperty(key, propertyFlags);
-        property.setObjectValue(this, this, value, false);
-        return property;
+        return addSpillProperty(key, propertyFlags, value, true);
     }
 
     /**
@@ -777,10 +866,8 @@
      */
     public final Property addOwnProperty(final Property newProperty) {
         PropertyMap oldMap = getMap();
-
         while (true) {
             final PropertyMap newMap = oldMap.addProperty(newProperty);
-
             if (!compareAndSetMap(oldMap, newMap)) {
                 oldMap = getMap();
                 final Property oldProperty = oldMap.findProperty(newProperty.getKey());
@@ -798,7 +885,8 @@
         // Erase the property field value with undefined. If the property is defined
         // by user-defined accessors, we don't want to call the setter!!
         if (!(property instanceof UserAccessorProperty)) {
-            property.setObjectValue(this, this, UNDEFINED, false);
+            assert property != null;
+            property.setValue(this, this, UNDEFINED, false);
         }
     }
 
@@ -825,13 +913,36 @@
             } else {
                 // delete getter and setter function references so that we don't leak
                 if (property instanceof UserAccessorProperty) {
-                    final UserAccessorProperty uc = (UserAccessorProperty) property;
-                    setSpill(uc.getGetterSlot(), null);
-                    setSpill(uc.getSetterSlot(), null);
+                    ((UserAccessorProperty)property).setAccessors(this, getMap(), null);
                 }
+                Global.getConstants().delete(property.getKey());
                 return true;
             }
         }
+
+    }
+
+    /**
+     * Fast initialization functions for ScriptFunctions that are strict, to avoid
+     * creating setters that probably aren't used. Inject directly into the spill pool
+     * the defaults for "arguments" and "caller"
+     *
+     * @param key
+     * @param propertyFlags
+     * @param getter
+     * @param setter
+     */
+    protected final void initUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
+        final int slot = spillLength;
+        ensureSpillSize(spillLength); //arguments=slot0, caller=slot0
+        objectSpill[slot] = new UserAccessorProperty.Accessors(getter, setter);
+        final PropertyMap oldMap = getMap();
+        Property    newProperty;
+        PropertyMap newMap;
+        do {
+            newProperty = new UserAccessorProperty(key, propertyFlags, slot);
+            newMap = oldMap.addProperty(newProperty);
+        } while (!compareAndSetMap(oldMap, newMap));
     }
 
     /**
@@ -846,19 +957,27 @@
      */
     public final Property modifyOwnProperty(final Property oldProperty, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
         Property newProperty;
+
         if (oldProperty instanceof UserAccessorProperty) {
-            final UserAccessorProperty uc = (UserAccessorProperty) oldProperty;
-            final int getterSlot = uc.getGetterSlot();
-            final int setterSlot = uc.getSetterSlot();
-            setSpill(getterSlot, getter);
-            setSpill(setterSlot, setter);
+            final UserAccessorProperty uc = (UserAccessorProperty)oldProperty;
+            final int slot = uc.getSlot();
 
-            // if just flipping getter and setter with new functions, no need to change property or map
-            if (uc.flags == propertyFlags) {
-                return oldProperty;
+            assert uc.getCurrentType() == Object.class;
+            if (slot >= spillLength) {
+                uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
+            } else {
+                final UserAccessorProperty.Accessors gs = uc.getAccessors(this); //this crashes
+                if (gs == null) {
+                    uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
+                } else {
+                    //reuse existing getter setter for speed
+                    gs.set(getter, setter);
+                    if (uc.getFlags() == propertyFlags) {
+                        return oldProperty;
+                    }
+                }
             }
-
-            newProperty = new UserAccessorProperty(oldProperty.getKey(), propertyFlags, getterSlot, setterSlot);
+            newProperty = new UserAccessorProperty(uc.getKey(), propertyFlags, slot);
         } else {
             // erase old property value and create new user accessor property
             erasePropertyValue(oldProperty);
@@ -889,6 +1008,10 @@
      * @return new property
      */
     private Property modifyOwnProperty(final Property oldProperty, final Property newProperty) {
+        if (oldProperty == newProperty) {
+            return newProperty; //nop
+        }
+
         assert newProperty.getKey().equals(oldProperty.getKey()) : "replacing property with different key";
 
         PropertyMap oldMap = getMap();
@@ -925,8 +1048,8 @@
         }
     }
 
-    private static int getIntValue(final FindProperty find) {
-        final MethodHandle getter = find.getGetter(int.class);
+    private static int getIntValue(final FindProperty find, final int programPoint) {
+        final MethodHandle getter = find.getGetter(int.class, programPoint);
         if (getter != null) {
             try {
                 return (int)getter.invokeExact((Object)find.getGetterReceiver());
@@ -937,11 +1060,11 @@
             }
         }
 
-        return ObjectClassGenerator.UNDEFINED_INT;
+        return UNDEFINED_INT;
     }
 
-    private static long getLongValue(final FindProperty find) {
-        final MethodHandle getter = find.getGetter(long.class);
+    private static long getLongValue(final FindProperty find, final int programPoint) {
+        final MethodHandle getter = find.getGetter(long.class, programPoint);
         if (getter != null) {
             try {
                 return (long)getter.invokeExact((Object)find.getGetterReceiver());
@@ -952,11 +1075,11 @@
             }
         }
 
-        return ObjectClassGenerator.UNDEFINED_LONG;
+        return UNDEFINED_LONG;
     }
 
-    private static double getDoubleValue(final FindProperty find) {
-        final MethodHandle getter = find.getGetter(double.class);
+    private static double getDoubleValue(final FindProperty find, final int programPoint) {
+        final MethodHandle getter = find.getGetter(double.class, programPoint);
         if (getter != null) {
             try {
                 return (double)getter.invokeExact((Object)find.getGetterReceiver());
@@ -967,7 +1090,7 @@
             }
         }
 
-        return ObjectClassGenerator.UNDEFINED_DOUBLE;
+        return UNDEFINED_DOUBLE;
     }
 
     /**
@@ -1073,14 +1196,12 @@
      * @param newMap Replacement map.
      * @return true if the operation succeeded.
      */
-    protected synchronized final boolean compareAndSetMap(final PropertyMap oldMap, final PropertyMap newMap) {
-        final boolean update = oldMap == this.map;
-
-        if (update) {
+    protected final boolean compareAndSetMap(final PropertyMap oldMap, final PropertyMap newMap) {
+        if (oldMap == this.map) {
             this.map = newMap;
+            return true;
         }
-
-        return update;
+        return false;
      }
 
     /**
@@ -1092,10 +1213,24 @@
     }
 
     /**
+     * Get the proto of a specific depth
+     * @param n depth
+     * @return proto at given depth
+     */
+    public final ScriptObject getProto(final int n) {
+        assert n > 0;
+        ScriptObject p = getProto();
+        for (int i = n; i-- > 0;) {
+            p = p.getProto();
+        }
+        return p;
+    }
+
+    /**
      * Set the __proto__ of an object.
      * @param newProto new __proto__ to set.
      */
-    public synchronized final void setProto(final ScriptObject newProto) {
+    public final void setProto(final ScriptObject newProto) {
         final ScriptObject oldProto = proto;
 
         if (oldProto != newProto) {
@@ -1124,6 +1259,14 @@
     }
 
     /**
+     * Invoked from generated bytecode to initialize the prototype of object literals to the global Object prototype.
+     * @param obj the object literal that needs to have its prototype initialized to the global Object prototype.
+     */
+    public static void setGlobalObjectProto(final ScriptObject obj) {
+        obj.setInitialProto(Global.objectPrototype());
+    }
+
+    /**
      * Set the __proto__ of an object with checks.
      * This is the built-in operation [[SetPrototypeOf]]
      * See ES6 draft spec: 9.1.2 [[SetPrototypeOf]] (V)
@@ -1132,8 +1275,9 @@
      */
     public final void setPrototypeOf(final Object newProto) {
         if (newProto == null || newProto instanceof ScriptObject) {
-            if (!isExtensible()) {
+            if (! isExtensible()) {
                 // okay to set same proto again - even if non-extensible
+
                 if (newProto == getProto()) {
                     return;
                 }
@@ -1180,7 +1324,19 @@
      * @param all True if to include non-enumerable keys.
      * @return Array of keys.
      */
-    public String[] getOwnKeys(final boolean all) {
+    public final String[] getOwnKeys(final boolean all) {
+        return getOwnKeys(all, null);
+    }
+
+    /**
+     * return an array of own property keys associated with the object.
+     *
+     * @param all True if to include non-enumerable keys.
+     * @param nonEnumerable set of non-enumerable properties seen already.Used
+       to filter out shadowed, but enumerable properties from proto children.
+     * @return Array of keys.
+     */
+    protected String[] getOwnKeys(final boolean all, final Set<String> nonEnumerable) {
         final List<Object> keys    = new ArrayList<>();
         final PropertyMap  selfMap = this.getMap();
 
@@ -1194,8 +1350,21 @@
         }
 
         for (final Property property : selfMap.getProperties()) {
-            if (all || property.isEnumerable()) {
-                keys.add(property.getKey());
+            final boolean enumerable = property.isEnumerable();
+            final String key = property.getKey();
+            if (all) {
+                keys.add(key);
+            } else if (enumerable) {
+                // either we don't have non-enumerable filter set or filter set
+                // does not contain the current property.
+                if (nonEnumerable == null || !nonEnumerable.contains(key)) {
+                    keys.add(key);
+                }
+            } else {
+                // store this non-enumerable property for later proto walk
+                if (nonEnumerable != null) {
+                    nonEnumerable.add(key);
+                }
             }
         }
 
@@ -1279,16 +1448,16 @@
      */
     public ScriptObject preventExtensions() {
         PropertyMap oldMap = getMap();
-
-        while (true) {
-            final PropertyMap newMap = getMap().preventExtensions();
-
-            if (!compareAndSetMap(oldMap, newMap)) {
-                oldMap = getMap();
-            } else {
-                return this;
-            }
+        while (!compareAndSetMap(oldMap,  getMap().preventExtensions())) {
+            oldMap = getMap();
         }
+
+        //invalidate any fast array setters
+        final ArrayData array = getArray();
+        if (array != null) {
+            array.invalidateSetters();
+        }
+        return this;
     }
 
     /**
@@ -1299,7 +1468,7 @@
      * @return true if array
      */
     public static boolean isArray(final Object obj) {
-        return (obj instanceof ScriptObject) && ((ScriptObject)obj).isArray();
+        return obj instanceof ScriptObject && ((ScriptObject)obj).isArray();
     }
 
     /**
@@ -1446,6 +1615,21 @@
     }
 
     /**
+     * Tag this script object as built in
+     */
+    public final void setIsBuiltin() {
+        flags |= IS_BUILTIN;
+    }
+
+    /**
+     * Check if this script object is built in
+     * @return true if build in
+     */
+    public final boolean isBuiltin() {
+        return (flags & IS_BUILTIN) != 0;
+    }
+
+    /**
      * Clears the properties from a ScriptObject
      * (java.util.Map-like method to help ScriptObjectMirror implementation)
      *
@@ -1629,11 +1813,11 @@
             return c > 2 ? findGetMethod(desc, request, operator) : findGetIndexMethod(desc, request);
         case "setProp":
         case "setElem":
-            return c > 2 ? findSetMethod(desc, request) : findSetIndexMethod(desc);
+            return c > 2 ? findSetMethod(desc, request) : findSetIndexMethod(desc, request);
         case "call":
             return findCallMethod(desc, request);
         case "new":
-            return findNewMethod(desc);
+            return findNewMethod(desc, request);
         case "callMethod":
             return findCallMethodMethod(desc, request);
         default:
@@ -1645,10 +1829,11 @@
      * Find the appropriate New method for an invoke dynamic call.
      *
      * @param desc The invoke dynamic call site descriptor.
+     * @param request The link request
      *
      * @return GuardedInvocation to be invoked at call site.
      */
-    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
+    protected GuardedInvocation findNewMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         return notAFunction();
     }
 
@@ -1722,17 +1907,28 @@
             return methodHandle;
         }
         final int listIndex = depth - 1; // We don't need 0-deep walker
-        MethodHandle filter = listIndex < protoFilters.size() ? protoFilters.get(listIndex) : null;
+        MethodHandle filter = listIndex < PROTO_FILTERS.size() ? PROTO_FILTERS.get(listIndex) : null;
 
-        if(filter == null) {
+        if (filter == null) {
             filter = addProtoFilter(GETPROTO, depth - 1);
-            protoFilters.add(null);
-            protoFilters.set(listIndex, filter);
+            PROTO_FILTERS.add(null);
+            PROTO_FILTERS.set(listIndex, filter);
         }
 
         return MH.filterArguments(methodHandle, 0, filter.asType(filter.type().changeReturnType(methodHandle.type().parameterType(0))));
     }
 
+    //this will only return true if apply is still builtin
+    private static SwitchPoint checkReservedName(final CallSiteDescriptor desc, final LinkRequest request) {
+        final boolean isApplyToCall = NashornCallSiteDescriptor.isApplyToCall(desc);
+        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        if ("apply".equals(name) && isApplyToCall && Global.instance().isSpecialNameValid(name)) {
+            assert Global.instance().getChangeCallback("apply") == Global.instance().getChangeCallback("call");
+            return Global.instance().getChangeCallback("apply");
+        }
+        return null;
+    }
+
     /**
      * Find the appropriate GET method for an invoke dynamic call.
      *
@@ -1743,66 +1939,92 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findGetMethod(final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
-        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
+        final String name;
+        final SwitchPoint reservedNameSwitchPoint;
+
+        reservedNameSwitchPoint = checkReservedName(desc, request);
+        if (reservedNameSwitchPoint != null) {
+            name = "call"; //turn apply into call, it is the builtin apply and has been modified to explode args
+        } else {
+            name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        }
+
         if (request.isCallSiteUnstable() || hasWithScope()) {
             return findMegaMorphicGetMethod(desc, name, "getMethod".equals(operator));
         }
 
         final FindProperty find = findProperty(name, true);
-        MethodHandle methodHandle;
+        MethodHandle mh;
 
         if (find == null) {
-            if ("getProp".equals(operator)) {
+            switch (operator) {
+            case "getProp":
                 return noSuchProperty(desc, request);
-            } else if ("getMethod".equals(operator)) {
+            case "getMethod":
                 return noSuchMethod(desc, request);
-            } else if ("getElem".equals(operator)) {
-                return createEmptyGetter(desc, name);
+            case "getElem":
+                return createEmptyGetter(desc, explicitInstanceOfCheck, name);
+            default:
+                throw new AssertionError(operator); // never invoked with any other operation
             }
-            throw new AssertionError(); // never invoked with any other operation
+        }
+
+        final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc, request, operator);
+        if (cinv != null) {
+            return cinv;
         }
 
         final Class<?> returnType = desc.getMethodType().returnType();
-        final Property property = find.getProperty();
-        methodHandle = find.getGetter(returnType);
+        final Property property   = find.getProperty();
 
+        final int programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ?
+                NashornCallSiteDescriptor.getProgramPoint(desc) :
+                UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+
+        mh = find.getGetter(returnType, programPoint);
         // Get the appropriate guard for this callsite and property.
-        final MethodHandle guard = NashornGuards.getGuard(this, property, desc);
+        final MethodHandle guard = NashornGuards.getGuard(this, property, desc, explicitInstanceOfCheck);
         final ScriptObject owner = find.getOwner();
+        final Class<ClassCastException> exception = explicitInstanceOfCheck ? null : ClassCastException.class;
 
-        if (methodHandle != null) {
-            assert methodHandle.type().returnType().equals(returnType);
-            if (find.isSelf()) {
-                return new GuardedInvocation(methodHandle, guard);
-            }
+        final SwitchPoint protoSwitchPoint;
 
+        if (mh == null) {
+            mh = Lookup.emptyGetter(returnType);
+            protoSwitchPoint = getProtoSwitchPoint(name, owner);
+        } else if (!find.isSelf()) {
+            assert mh.type().returnType().equals(returnType) : "returntype mismatch for getter " + mh.type().returnType() + " != " + returnType;
             if (!property.hasGetterFunction(owner)) {
                 // Add a filter that replaces the self object with the prototype owning the property.
-                methodHandle = addProtoFilter(methodHandle, find.getProtoChainLength());
+                mh = addProtoFilter(mh, find.getProtoChainLength());
             }
-            return new GuardedInvocation(methodHandle, guard == null ? null : getProtoSwitchPoint(name, owner), guard);
+            protoSwitchPoint = getProtoSwitchPoint(name, owner);
+        } else {
+            protoSwitchPoint = null;
         }
 
-        assert !NashornCallSiteDescriptor.isFastScope(desc);
-        return new GuardedInvocation(Lookup.emptyGetter(returnType), getProtoSwitchPoint(name, owner), guard);
+        assert OBJECT_FIELDS_ONLY || guard != null : "we always need a map guard here";
+
+        final GuardedInvocation inv = new GuardedInvocation(mh, guard, protoSwitchPoint, exception);
+        return inv.addSwitchPoint(reservedNameSwitchPoint);
     }
 
-    private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name,
-                                                              final boolean isMethod) {
+    private static GuardedInvocation findMegaMorphicGetMethod(final CallSiteDescriptor desc, final String name, final boolean isMethod) {
+        Context.getContextTrusted().getLogger(ObjectClassGenerator.class).warning("Megamorphic getter: " + desc + " " + name + " " +isMethod);
         final MethodHandle invoker = MH.insertArguments(MEGAMORPHIC_GET, 1, name, isMethod);
-        final MethodHandle guard = getScriptObjectGuard(desc.getMethodType());
+        final MethodHandle guard   = getScriptObjectGuard(desc.getMethodType(), true);
         return new GuardedInvocation(invoker, guard);
     }
 
     @SuppressWarnings("unused")
     private Object megamorphicGet(final String key, final boolean isMethod) {
         final FindProperty find = findProperty(key, true);
-
         if (find != null) {
             return find.getObjectValue();
         }
 
-        return isMethod ? getNoSuchMethod(key) : invokeNoSuchProperty(key);
+        return isMethod ? getNoSuchMethod(key, INVALID_PROGRAM_POINT) : invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
     }
 
     /**
@@ -1814,31 +2036,48 @@
      * @return GuardedInvocation to be invoked at call site.
      */
     protected GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) {
-        return findGetIndexMethod(desc.getMethodType());
-    }
+        final MethodType callType                = desc.getMethodType();
+        final Class<?>   returnType              = callType.returnType();
+        final Class<?>   returnClass             = returnType.isPrimitive() ? returnType : Object.class;
+        final Class<?>   keyClass                = callType.parameterType(1);
+        final boolean    explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
 
-    /**
-     * Find the appropriate GETINDEX method for an invoke dynamic call.
-     *
-     * @param callType the call site method type
-     * @return GuardedInvocation to be invoked at call site.
-     */
-    private static GuardedInvocation findGetIndexMethod(final MethodType callType) {
-        final Class<?> returnClass = callType.returnType();
-        final Class<?> keyClass    = callType.parameterType(1);
-
-        String name = "get";
+        final String name;
         if (returnClass.isPrimitive()) {
             //turn e.g. get with a double into getDouble
             final String returnTypeName = returnClass.getName();
-            name += Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
+            name = "get" + Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
+        } else {
+            name = "get";
         }
 
-        return new GuardedInvocation(findOwnMH(name, returnClass, keyClass), getScriptObjectGuard(callType));
+        final MethodHandle mh = findGetIndexMethodHandle(returnClass, name, keyClass, desc);
+        return new GuardedInvocation(mh, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
-    private static MethodHandle getScriptObjectGuard(final MethodType type) {
-        return ScriptObject.class.isAssignableFrom(type.parameterType(0)) ? null : NashornGuards.getScriptObjectGuard();
+    private static MethodHandle getScriptObjectGuard(final MethodType type, final boolean explicitInstanceOfCheck) {
+        return ScriptObject.class.isAssignableFrom(type.parameterType(0)) ? null : NashornGuards.getScriptObjectGuard(explicitInstanceOfCheck);
+    }
+
+    /**
+     * Find a handle for a getIndex method
+     * @param returnType     return type for getter
+     * @param name           name
+     * @param elementType    index type for getter
+     * @param desc           call site descriptor
+     * @return method handle for getter
+     */
+    protected MethodHandle findGetIndexMethodHandle(final Class<?> returnType, final String name, final Class<?> elementType, final CallSiteDescriptor desc) {
+        if (!returnType.isPrimitive()) {
+            return findOwnMH_V(getClass(), name, returnType, elementType);
+        }
+
+        return MH.insertArguments(
+                findOwnMH_V(getClass(), name, returnType, elementType, int.class),
+                2,
+                NashornCallSiteDescriptor.isOptimistic(desc) ?
+                        NashornCallSiteDescriptor.getProgramPoint(desc) :
+                        INVALID_PROGRAM_POINT);
     }
 
     /**
@@ -1856,7 +2095,7 @@
         }
 
         for (ScriptObject obj = this; obj != owner && obj.getProto() != null; obj = obj.getProto()) {
-            ScriptObject parent = obj.getProto();
+            final ScriptObject parent = obj.getProto();
             parent.getMap().addListener(name, obj.getMap());
         }
 
@@ -1873,11 +2112,14 @@
      */
     protected GuardedInvocation findSetMethod(final CallSiteDescriptor desc, final LinkRequest request) {
         final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+
         if (request.isCallSiteUnstable() || hasWithScope()) {
             return findMegaMorphicSetMethod(desc, name);
         }
 
-        final boolean scope = isScope();
+        final boolean scope                   = isScope();
+        final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
+
         /*
          * If doing property set on a scope object, we should stop proto search on the first
          * non-scope object. Without this, for example, when assigning "toString" on global scope,
@@ -1891,105 +2133,64 @@
         if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) {
             // We should still check if inherited data property is not writable
             if (isExtensible() && !find.getProperty().isWritable()) {
-                return createEmptySetMethod(desc, "property.not.writable", false);
+                return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", false);
             }
             // Otherwise, forget the found property
             find = null;
         }
 
         if (find != null) {
-            if(!find.getProperty().isWritable()) {
+            if (!find.getProperty().isWritable()) {
                 // Existing, non-writable property
-                return createEmptySetMethod(desc, "property.not.writable", true);
+                return createEmptySetMethod(desc, explicitInstanceOfCheck, "property.not.writable", true);
             }
         } else {
-            if (! isExtensible()) {
-                return createEmptySetMethod(desc, "object.non.extensible", false);
+            if (!isExtensible()) {
+                return createEmptySetMethod(desc, explicitInstanceOfCheck, "object.non.extensible", false);
             }
         }
 
-        return new SetMethodCreator(this, find, desc).createGuardedInvocation();
+        final GuardedInvocation inv = new SetMethodCreator(this, find, desc, explicitInstanceOfCheck).createGuardedInvocation();
+
+        final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request);
+        if (cinv != null) {
+            return cinv;
+        }
+
+        return inv;
     }
 
-    private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, String strictErrorMessage, boolean canBeFastScope) {
-        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
-        if (NashornCallSiteDescriptor.isStrict(desc)) {
-               throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString((this)));
-           }
-           assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
-           return new GuardedInvocation(Lookup.EMPTY_SETTER, getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
+    private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String strictErrorMessage, final boolean canBeFastScope) {
+        final String  name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+         if (NashornCallSiteDescriptor.isStrict(desc)) {
+           throw typeError(strictErrorMessage, name, ScriptRuntime.safeToString(this));
+        }
+        assert canBeFastScope || !NashornCallSiteDescriptor.isFastScope(desc);
+        return new GuardedInvocation(
+                Lookup.EMPTY_SETTER,
+                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
+                getProtoSwitchPoint(name, null),
+                explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
     @SuppressWarnings("unused")
-    private static void setField(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final MethodHandle setter, final Object self, final Object value) throws Throwable {
-        final ScriptObject obj = (ScriptObject)self;
-        final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
-        if (!obj.isExtensible()) {
-            if (isStrict) {
-                throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
-            }
-        } else if (obj.compareAndSetMap(oldMap, newMap)) {
-            setter.invokeExact(self, value);
+    private boolean extensionCheck(final boolean isStrict, final String name) {
+        if (isExtensible()) {
+            return true; //go on and do the set. this is our guard
+        } else if (isStrict) {
+            //throw an error for attempting to do the set in strict mode
+            throw typeError("object.non.extensible", name, ScriptRuntime.safeToString(this));
         } else {
-            obj.set(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND), value, isStrict);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private static void setSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final Object self, final Object value) {
-        final ScriptObject obj = (ScriptObject)self;
-        if (obj.trySetSpill(desc, oldMap, newMap, value)) {
-            obj.spill[index] = value;
-        }
-    }
-
-    private boolean trySetSpill(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final Object value) {
-        final boolean isStrict = NashornCallSiteDescriptor.isStrict(desc);
-        if (!isExtensible() && isStrict) {
-            throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(this));
-        } else if (compareAndSetMap(oldMap, newMap)) {
-            return true;
-        } else {
-            set(desc.getNameToken(CallSiteDescriptor.NAME_OPERAND), value, isStrict);
+            //not extensible, non strict - this is a nop
             return false;
         }
     }
 
-    @SuppressWarnings("unused")
-    private static void setSpillWithNew(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final Object self, final Object value) {
-        final ScriptObject obj      = (ScriptObject)self;
-        final boolean      isStrict = NashornCallSiteDescriptor.isStrict(desc);
-
-        if (!obj.isExtensible()) {
-            if (isStrict) {
-                throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
-            }
-        } else if (obj.compareAndSetMap(oldMap, newMap)) {
-            obj.spill = new Object[SPILL_RATE];
-            obj.spill[index] = value;
-        } else {
-            obj.set(desc.getNameToken(2), value, isStrict);
-        }
-    }
-
-    @SuppressWarnings("unused")
-    private static void setSpillWithGrow(final CallSiteDescriptor desc, final PropertyMap oldMap, final PropertyMap newMap, final int index, final int newLength, final Object self, final Object value) {
-        final ScriptObject obj      = (ScriptObject)self;
-        final boolean      isStrict = NashornCallSiteDescriptor.isStrict(desc);
-
-        if (!obj.isExtensible()) {
-            if (isStrict) {
-                throw typeError("object.non.extensible", desc.getNameToken(2), ScriptRuntime.safeToString(obj));
-            }
-        } else if (obj.compareAndSetMap(oldMap, newMap)) {
-            final int oldLength = obj.spill.length;
-            final Object[] newSpill = new Object[newLength];
-            System.arraycopy(obj.spill, 0, newSpill, 0, oldLength);
-            obj.spill = newSpill;
-            obj.spill[index] = value;
-        } else {
-            obj.set(desc.getNameToken(2), value, isStrict);
-        }
+    private GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
+        final MethodType        type = desc.getMethodType().insertParameterTypes(1, Object.class);
+        //never bother with ClassCastExceptionGuard for megamorphic callsites
+        final GuardedInvocation inv = findSetIndexMethod(getClass(), false, type, NashornCallSiteDescriptor.isStrict(desc));
+        return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
     }
 
     @SuppressWarnings("unused")
@@ -2001,14 +2202,17 @@
         return sobj;
     }
 
-    private static GuardedInvocation findMegaMorphicSetMethod(final CallSiteDescriptor desc, final String name) {
-        final MethodType type = desc.getMethodType().insertParameterTypes(1, Object.class);
-        final GuardedInvocation inv = findSetIndexMethod(type, NashornCallSiteDescriptor.isStrict(desc));
-        return inv.replaceMethods(MH.insertArguments(inv.getInvocation(), 1, name), inv.getGuard());
-    }
-
-    private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) { // array, index, value
-        return findSetIndexMethod(desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
+    /**
+     * Lookup function for the set index method, available for subclasses as well, e.g. {@link NativeArray}
+     * provides special quick accessor linkage for continuous arrays that are represented as Java arrays
+     *
+     * @param desc    call site descriptor
+     * @param request link request
+     *
+     * @return GuardedInvocation to be invoked at call site.
+     */
+    protected GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+        return findSetIndexMethod(getClass(), explicitInstanceOfCheck(desc, request), desc.getMethodType(), NashornCallSiteDescriptor.isStrict(desc));
     }
 
     /**
@@ -2019,16 +2223,15 @@
      *
      * @return GuardedInvocation to be invoked at call site.
      */
-    private static GuardedInvocation findSetIndexMethod(final MethodType callType, final boolean isStrict) {
+    private static GuardedInvocation findSetIndexMethod(final Class<? extends ScriptObject> clazz, final boolean explicitInstanceOfCheck, final MethodType callType, final boolean isStrict) {
         assert callType.parameterCount() == 3;
+        final Class<?> keyClass   = callType.parameterType(1);
+        final Class<?> valueClass = callType.parameterType(2);
 
-        final Class<?>   keyClass   = callType.parameterType(1);
-        final Class<?>   valueClass = callType.parameterType(2);
-
-        MethodHandle methodHandle = findOwnMH("set", void.class, keyClass, valueClass, boolean.class);
+        MethodHandle methodHandle = findOwnMH_V(clazz, "set", void.class, keyClass, valueClass, boolean.class);
         methodHandle = MH.insertArguments(methodHandle, 3, isStrict);
 
-        return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType));
+        return new GuardedInvocation(methodHandle, getScriptObjectGuard(callType, explicitInstanceOfCheck), (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
     /**
@@ -2046,17 +2249,26 @@
             return noSuchProperty(desc, request);
         }
 
+        final boolean explicitInstanceOfCheck = explicitInstanceOfCheck(desc, request);
+
         final Object value = find.getObjectValue();
-        if (! (value instanceof ScriptFunction)) {
-            return createEmptyGetter(desc, name);
+        if (!(value instanceof ScriptFunction)) {
+            return createEmptyGetter(desc, explicitInstanceOfCheck, name);
         }
 
         final ScriptFunction func = (ScriptFunction)value;
-        final Object thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
+        final Object         thiz = scopeCall && func.isStrict() ? ScriptRuntime.UNDEFINED : this;
         // TODO: It'd be awesome if we could bind "name" without binding "this".
-        return new GuardedInvocation(MH.dropArguments(MH.constant(ScriptFunction.class,
-                func.makeBoundFunction(thiz, new Object[] { name })), 0, Object.class),
-                null, NashornGuards.getMapGuard(getMap()));
+        return new GuardedInvocation(
+                MH.dropArguments(
+                        MH.constant(
+                                ScriptFunction.class,
+                                func.makeBoundFunction(thiz, new Object[] { name })),
+                        0,
+                        Object.class),
+                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck),
+                (SwitchPoint)null,
+                explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
     /**
@@ -2065,29 +2277,44 @@
      * @param request the link request
      * @return GuardedInvocation to be invoked at call site.
      */
-    @SuppressWarnings("null")
     public GuardedInvocation noSuchProperty(final CallSiteDescriptor desc, final LinkRequest request) {
-        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
-        final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
-        final boolean scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
+        final String       name        = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final FindProperty find        = findProperty(NO_SUCH_PROPERTY_NAME, true);
+        final boolean      scopeAccess = isScope() && NashornCallSiteDescriptor.isScope(desc);
 
         if (find != null) {
-            final Object   value        = find.getObjectValue();
-            ScriptFunction func         = null;
-            MethodHandle   methodHandle = null;
+            final Object   value = find.getObjectValue();
+            ScriptFunction func  = null;
+            MethodHandle   mh    = null;
 
             if (value instanceof ScriptFunction) {
                 func = (ScriptFunction)value;
-                methodHandle = getCallMethodHandle(func, desc.getMethodType(), name);
+                mh   = getCallMethodHandle(func, desc.getMethodType(), name);
             }
 
-            if (methodHandle != null) {
+            if (mh != null) {
+                assert func != null;
                 if (scopeAccess && func.isStrict()) {
-                    methodHandle = bindTo(methodHandle, UNDEFINED);
+                    mh = bindTo(mh, UNDEFINED);
                 }
-                return new GuardedInvocation(methodHandle,
+
+                return new GuardedInvocation(
+                        mh,
+                        find.isSelf()?
+                            getKnownFunctionPropertyGuardSelf(
+                                getMap(),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                func)
+                            :
+                            //TODO this always does a scriptobject check
+                            getKnownFunctionPropertyGuardProto(
+                                getMap(),
+                                find.getGetter(Object.class, INVALID_PROGRAM_POINT),
+                                find.getProtoChainLength(),
+                                func),
                         getProtoSwitchPoint(NO_SUCH_PROPERTY_NAME, find.getOwner()),
-                        getKnownFunctionPropertyGuard(getMap(), find.getGetter(Object.class), find.getOwner(), func));
+                        //TODO this doesn't need a ClassCastException as guard always checks script object
+                        null);
             }
         }
 
@@ -2095,51 +2322,64 @@
             throw referenceError("not.defined", name);
         }
 
-        return createEmptyGetter(desc, name);
+        return createEmptyGetter(desc, explicitInstanceOfCheck(desc, request), name);
     }
 
     /**
      * Invoke fall back if a property is not found.
      * @param name Name of property.
+     * @param programPoint program point
      * @return Result from call.
      */
-    protected Object invokeNoSuchProperty(final String name) {
+    protected Object invokeNoSuchProperty(final String name, final int programPoint) {
         final FindProperty find = findProperty(NO_SUCH_PROPERTY_NAME, true);
 
+        Object ret = UNDEFINED;
+
         if (find != null) {
             final Object func = find.getObjectValue();
 
             if (func instanceof ScriptFunction) {
-                return ScriptRuntime.apply((ScriptFunction)func, this, name);
+                ret = ScriptRuntime.apply((ScriptFunction)func, this, name);
             }
         }
 
-        return UNDEFINED;
+        if (isValid(programPoint)) {
+            throw new UnwarrantedOptimismException(ret, programPoint);
+        }
+
+        return ret;
     }
 
+
     /**
      * Get __noSuchMethod__ as a function bound to this object and {@code name} if it is defined.
      * @param name the method name
      * @return the bound function, or undefined
      */
-    private Object getNoSuchMethod(final String name) {
+    private Object getNoSuchMethod(final String name, final int programPoint) {
         final FindProperty find = findProperty(NO_SUCH_METHOD_NAME, true);
 
         if (find == null) {
-            return invokeNoSuchProperty(name);
+            return invokeNoSuchProperty(name, programPoint);
         }
 
         final Object value = find.getObjectValue();
-        if (! (value instanceof ScriptFunction)) {
+        if (!(value instanceof ScriptFunction)) {
             return UNDEFINED;
         }
 
         return ((ScriptFunction)value).makeBoundFunction(this, new Object[] {name});
     }
 
-    private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final String name) {
+    private GuardedInvocation createEmptyGetter(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String name) {
+        if (NashornCallSiteDescriptor.isOptimistic(desc)) {
+            throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
+        }
+
         return new GuardedInvocation(Lookup.emptyGetter(desc.getMethodType().returnType()),
-                getProtoSwitchPoint(name, null), NashornGuards.getMapGuard(getMap()));
+                NashornGuards.getMapGuard(getMap(), explicitInstanceOfCheck), getProtoSwitchPoint(name, null),
+                explicitInstanceOfCheck ? null : ClassCastException.class);
     }
 
     private abstract static class ScriptObjectIterator <T extends Object> implements Iterator<T> {
@@ -2183,8 +2423,9 @@
         @Override
         protected void init() {
             final Set<String> keys = new LinkedHashSet<>();
+            final Set<String> nonEnumerable = new HashSet<>();
             for (ScriptObject self = object; self != null; self = self.getProto()) {
-                keys.addAll(Arrays.asList(self.getOwnKeys(false)));
+                keys.addAll(Arrays.asList(self.getOwnKeys(false, nonEnumerable)));
             }
             this.values = keys.toArray(new String[keys.size()]);
         }
@@ -2198,8 +2439,9 @@
         @Override
         protected void init() {
             final ArrayList<Object> valueList = new ArrayList<>();
+            final Set<String> nonEnumerable = new HashSet<>();
             for (ScriptObject self = object; self != null; self = self.getProto()) {
-                for (final String key : self.getOwnKeys(false)) {
+                for (final String key : self.getOwnKeys(false, nonEnumerable)) {
                     valueList.add(self.get(key));
                 }
             }
@@ -2213,46 +2455,34 @@
      * @param propertyFlags Property flags.
      * @return Added property.
      */
-    private Property addSpillProperty(final String key, final int propertyFlags) {
-        int fieldCount   = getMap().getFieldCount();
-        int fieldMaximum = getMap().getFieldMaximum();
-        Property property;
+    private Property addSpillProperty(final String key, final int propertyFlags, final Object value, final boolean hasInitialValue) {
+        final PropertyMap propertyMap = getMap();
+        final int fieldSlot  = propertyMap.getFreeFieldSlot();
 
-        if (fieldCount < fieldMaximum) {
-            property = new AccessorProperty(key, propertyFlags & ~Property.IS_SPILL, getClass(), fieldCount);
+        Property property;
+        if (fieldSlot > -1) {
+            property = hasInitialValue ?
+                new AccessorProperty(key, propertyFlags, fieldSlot, this, value) :
+                new AccessorProperty(key, propertyFlags, getClass(), fieldSlot);
             property = addOwnProperty(property);
         } else {
-            int i = getMap().getSpillLength();
-            property = new AccessorProperty(key, propertyFlags | Property.IS_SPILL, i);
+            final int spillSlot = propertyMap.getFreeSpillSlot();
+            property = hasInitialValue ?
+                new SpillProperty(key, propertyFlags, spillSlot, this, value) :
+                new SpillProperty(key, propertyFlags, spillSlot);
             property = addOwnProperty(property);
-            i = property.getSlot();
-
-            final int newLength = (i + SPILL_RATE) / SPILL_RATE * SPILL_RATE;
-
-            if (spill == null || newLength > spill.length) {
-                final Object[] newSpill = new Object[newLength];
-
-                if (spill != null) {
-                    System.arraycopy(spill, 0, newSpill, 0, spill.length);
-                }
-
-                spill = newSpill;
-            }
+            ensureSpillSize(property.getSlot());
         }
-
         return property;
     }
 
-
     /**
      * Add a spill entry for the given key.
      * @param key Property key.
      * @return Setter method handle.
      */
-    MethodHandle addSpill(final String key) {
-        final Property spillProperty = addSpillProperty(key, 0);
-        final Class<?> type = Object.class;
-        return spillProperty.getSetter(type, getMap()); //TODO specfields
+    MethodHandle addSpill(final Class<?> type, final String key) {
+        return addSpillProperty(key, 0, null, false).getSetter(OBJECT_FIELDS_ONLY ? Object.class : type, getMap());
     }
 
     /**
@@ -2285,9 +2515,8 @@
      * @return method handle with adjusted arguments
      */
     public static MethodHandle pairArguments(final MethodHandle methodHandle, final MethodType callType, final Boolean callerVarArg) {
-
         final MethodType methodType = methodHandle.type();
-        if (methodType.equals(callType)) {
+        if (methodType.equals(callType.changeReturnType(methodType.returnType()))) {
             return methodHandle;
         }
 
@@ -2295,24 +2524,8 @@
         final int callCount      = callType.parameterCount();
 
         final boolean isCalleeVarArg = parameterCount > 0 && methodType.parameterType(parameterCount - 1).isArray();
-        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : (callCount > 0 &&
-                callType.parameterType(callCount - 1).isArray());
-
-        if (callCount < parameterCount) {
-            final int      missingArgs = parameterCount - callCount;
-            final Object[] fillers     = new Object[missingArgs];
-
-            Arrays.fill(fillers, UNDEFINED);
-
-            if (isCalleeVarArg) {
-                fillers[missingArgs - 1] = new Object[0];
-            }
-
-            return MH.insertArguments(
-                methodHandle,
-                parameterCount - missingArgs,
-                fillers);
-        }
+        final boolean isCallerVarArg = callerVarArg != null ? callerVarArg.booleanValue() : callCount > 0 &&
+                callType.parameterType(callCount - 1).isArray();
 
         if (isCalleeVarArg) {
             return isCallerVarArg ?
@@ -2321,18 +2534,23 @@
         }
 
         if (isCallerVarArg) {
-            final int spreadArgs = parameterCount - callCount + 1;
-            return MH.filterArguments(
-                MH.asSpreader(
-                    methodHandle,
-                    Object[].class,
-                    spreadArgs),
-                callCount - 1,
-                MH.insertArguments(
-                    TRUNCATINGFILTER,
-                    0,
-                    spreadArgs)
-                );
+            return adaptHandleToVarArgCallSite(methodHandle, callCount);
+        }
+
+        if (callCount < parameterCount) {
+            final int      missingArgs = parameterCount - callCount;
+            final Object[] fillers     = new Object[missingArgs];
+
+            Arrays.fill(fillers, UNDEFINED);
+
+            if (isCalleeVarArg) {
+                fillers[missingArgs - 1] = ScriptRuntime.EMPTY_ARRAY;
+            }
+
+            return MH.insertArguments(
+                methodHandle,
+                parameterCount - missingArgs,
+                fillers);
         }
 
         if (callCount > parameterCount) {
@@ -2347,19 +2565,32 @@
         return methodHandle;
     }
 
+    static MethodHandle adaptHandleToVarArgCallSite(final MethodHandle mh, final int callSiteParamCount) {
+        final int spreadArgs = mh.type().parameterCount() - callSiteParamCount + 1;
+        return MH.filterArguments(
+            MH.asSpreader(
+            mh,
+            Object[].class,
+            spreadArgs),
+            callSiteParamCount - 1,
+            MH.insertArguments(
+                TRUNCATINGFILTER,
+                0,
+                spreadArgs)
+            );
+    }
+
     @SuppressWarnings("unused")
     private static Object[] truncatingFilter(final int n, final Object[] array) {
         final int length = array == null ? 0 : array.length;
         if (n == length) {
-            return array == null ? new Object[0] : array;
+            return array == null ? ScriptRuntime.EMPTY_ARRAY : array;
         }
 
         final Object[] newArray = new Object[n];
 
         if (array != null) {
-            for (int i = 0; i < n && i < length; i++) {
-                newArray[i] = array[i];
-            }
+            System.arraycopy(array, 0, newArray, 0, Math.min(n, length));
         }
 
         if (length < n) {
@@ -2386,8 +2617,8 @@
 
        if (newLength > arrayLength) {
            setArray(getArray().ensure(newLength - 1));
-            if (getArray().canDelete(arrayLength, (newLength - 1), false)) {
-               setArray(getArray().delete(arrayLength, (newLength - 1)));
+            if (getArray().canDelete(arrayLength, newLength - 1, false)) {
+               setArray(getArray().delete(arrayLength, newLength - 1));
            }
            return;
        }
@@ -2419,14 +2650,14 @@
        }
     }
 
-    private int getInt(final int index, final String key) {
+    private int getInt(final int index, final String key, final int programPoint) {
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
                     final FindProperty find = object.findProperty(key, false, false, this);
 
                     if (find != null) {
-                        return getIntValue(find);
+                        return getIntValue(find, programPoint);
                     }
                 }
 
@@ -2437,77 +2668,78 @@
                 final ArrayData array = object.getArray();
 
                 if (array.has(index)) {
-                    return array.getInt(index);
+                    return isValid(programPoint) ?
+                        array.getIntOptimistic(index, programPoint) :
+                        array.getInt(index);
                 }
             }
         } else {
             final FindProperty find = findProperty(key, true);
 
             if (find != null) {
-                return getIntValue(find);
+                return getIntValue(find, programPoint);
             }
         }
 
-        return JSType.toInt32(invokeNoSuchProperty(key));
+        return JSType.toInt32(invokeNoSuchProperty(key, programPoint));
     }
 
     @Override
-    public int getInt(final Object key) {
-        final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
-        final ArrayData array = getArray();
+    public int getInt(final Object key, final int programPoint) {
+        final Object    primitiveKey = JSType.toPrimitive(key, String.class);
+        final int       index        = getArrayIndex(primitiveKey);
+        final ArrayData array        = getArray();
 
         if (array.has(index)) {
-            return array.getInt(index);
+            return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
         }
 
-        return getInt(index, JSType.toString(primitiveKey));
+        return getInt(index, JSType.toString(primitiveKey), programPoint);
     }
 
     @Override
-    public int getInt(final double key) {
-        final int index = getArrayIndex(key);
+    public int getInt(final double key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getInt(index);
+            return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
         }
 
-        return getInt(index, JSType.toString(key));
+        return getInt(index, JSType.toString(key), programPoint);
     }
 
     @Override
-    public int getInt(final long key) {
-        final int index = getArrayIndex(key);
+    public int getInt(final long key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getInt(index);
+            return isValid(programPoint) ? array.getIntOptimistic(index, programPoint) : array.getInt(index);
         }
 
-        return getInt(index, JSType.toString(key));
+        return getInt(index, JSType.toString(key), programPoint);
     }
 
     @Override
-    public int getInt(final int key) {
-        final int index = getArrayIndex(key);
+    public int getInt(final int key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getInt(index);
+            return isValid(programPoint) ? array.getIntOptimistic(key, programPoint) : array.getInt(key);
         }
 
-        return getInt(index, JSType.toString(key));
+        return getInt(index, JSType.toString(key), programPoint);
     }
 
-    private long getLong(final int index, final String key) {
+    private long getLong(final int index, final String key, final int programPoint) {
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
                     final FindProperty find = object.findProperty(key, false, false, this);
-
                     if (find != null) {
-                        return getLongValue(find);
+                        return getLongValue(find, programPoint);
                     }
                 }
 
@@ -2518,77 +2750,78 @@
                 final ArrayData array = object.getArray();
 
                 if (array.has(index)) {
-                    return array.getLong(index);
+                    return isValid(programPoint) ?
+                        array.getLongOptimistic(index, programPoint) :
+                        array.getLong(index);
                 }
             }
         } else {
             final FindProperty find = findProperty(key, true);
 
             if (find != null) {
-                return getLongValue(find);
+                return getLongValue(find, programPoint);
             }
         }
 
-        return JSType.toLong(invokeNoSuchProperty(key));
+        return JSType.toLong(invokeNoSuchProperty(key, programPoint));
     }
 
     @Override
-    public long getLong(final Object key) {
-        final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
-        final ArrayData array = getArray();
+    public long getLong(final Object key, final int programPoint) {
+        final Object    primitiveKey = JSType.toPrimitive(key, String.class);
+        final int       index        = getArrayIndex(primitiveKey);
+        final ArrayData array        = getArray();
 
         if (array.has(index)) {
-            return array.getLong(index);
+            return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
         }
 
-        return getLong(index, JSType.toString(primitiveKey));
+        return getLong(index, JSType.toString(primitiveKey), programPoint);
     }
 
     @Override
-    public long getLong(final double key) {
-        final int index = getArrayIndex(key);
+    public long getLong(final double key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getLong(index);
+            return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
         }
 
-        return getLong(index, JSType.toString(key));
+        return getLong(index, JSType.toString(key), programPoint);
     }
 
     @Override
-    public long getLong(final long key) {
-        final int index = getArrayIndex(key);
+    public long getLong(final long key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getLong(index);
+            return isValid(programPoint) ? array.getLongOptimistic(index, programPoint) : array.getLong(index);
         }
 
-        return getLong(index, JSType.toString(key));
+        return getLong(index, JSType.toString(key), programPoint);
     }
 
     @Override
-    public long getLong(final int key) {
-        final int index = getArrayIndex(key);
+    public long getLong(final int key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getLong(index);
+            return isValid(programPoint) ? array.getLongOptimistic(key, programPoint) : array.getLong(key);
         }
 
-        return getLong(index, JSType.toString(key));
+        return getLong(index, JSType.toString(key), programPoint);
     }
 
-    private double getDouble(final int index, final String key) {
+    private double getDouble(final int index, final String key, final int programPoint) {
         if (isValidArrayIndex(index)) {
             for (ScriptObject object = this; ; ) {
                 if (object.getMap().containsArrayKeys()) {
                     final FindProperty find = object.findProperty(key, false, false, this);
-
                     if (find != null) {
-                        return getDoubleValue(find);
+                        return getDoubleValue(find, programPoint);
                     }
                 }
 
@@ -2599,67 +2832,69 @@
                 final ArrayData array = object.getArray();
 
                 if (array.has(index)) {
-                    return array.getDouble(index);
+                    return isValid(programPoint) ?
+                        array.getDoubleOptimistic(index, programPoint) :
+                        array.getDouble(index);
                 }
             }
         } else {
             final FindProperty find = findProperty(key, true);
 
             if (find != null) {
-                return getDoubleValue(find);
+                return getDoubleValue(find, programPoint);
             }
         }
 
-        return JSType.toNumber(invokeNoSuchProperty(key));
+        return JSType.toNumber(invokeNoSuchProperty(key, INVALID_PROGRAM_POINT));
     }
 
     @Override
-    public double getDouble(final Object key) {
-        final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
-        final ArrayData array = getArray();
+    public double getDouble(final Object key, final int programPoint) {
+        final Object    primitiveKey = JSType.toPrimitive(key, String.class);
+        final int       index        = getArrayIndex(primitiveKey);
+        final ArrayData array        = getArray();
 
         if (array.has(index)) {
-            return array.getDouble(index);
+            return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
         }
 
-        return getDouble(index, JSType.toString(primitiveKey));
+        return getDouble(index, JSType.toString(primitiveKey), programPoint);
     }
 
     @Override
-    public double getDouble(final double key) {
-        final int index = getArrayIndex(key);
+    public double getDouble(final double key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getDouble(index);
+            return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
         }
 
-        return getDouble(index, JSType.toString(key));
+        return getDouble(index, JSType.toString(key), programPoint);
     }
 
     @Override
-    public double getDouble(final long key) {
-        final int index = getArrayIndex(key);
+    public double getDouble(final long key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getDouble(index);
+            return isValid(programPoint) ? array.getDoubleOptimistic(index, programPoint) : array.getDouble(index);
         }
 
-        return getDouble(index, JSType.toString(key));
+        return getDouble(index, JSType.toString(key), programPoint);
     }
 
     @Override
-    public double getDouble(final int key) {
-        final int index = getArrayIndex(key);
+    public double getDouble(final int key, final int programPoint) {
+        final int       index = getArrayIndex(key);
         final ArrayData array = getArray();
 
         if (array.has(index)) {
-            return array.getDouble(index);
+            return isValid(programPoint) ? array.getDoubleOptimistic(key, programPoint) : array.getDouble(key);
         }
 
-        return getDouble(index, JSType.toString(key));
+        return getDouble(index, JSType.toString(key), programPoint);
     }
 
     private Object get(final int index, final String key) {
@@ -2691,14 +2926,14 @@
             }
         }
 
-        return invokeNoSuchProperty(key);
+        return invokeNoSuchProperty(key, INVALID_PROGRAM_POINT);
     }
 
     @Override
     public Object get(final Object key) {
-        final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
-        final ArrayData array = getArray();
+        final Object    primitiveKey = JSType.toPrimitive(key, String.class);
+        final int       index        = getArrayIndex(primitiveKey);
+        final ArrayData array        = getArray();
 
         if (array.has(index)) {
             return array.getObject(index);
@@ -2743,68 +2978,114 @@
         return get(index, JSType.toString(key));
     }
 
-    /**
-     * Handle when an array doesn't have a slot - possibly grow and/or convert array.
-     *
-     * @param index  key as index
-     * @param value  element value
-     * @param strict are we in strict mode
-     */
-    private void doesNotHave(final int index, final Object value, final boolean strict) {
-        final long longIndex = ArrayIndex.toLongIndex(index);
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final int value, final boolean strict) {
         if (getMap().containsArrayKeys()) {
-            final String key = JSType.toString(longIndex);
+            final String       key  = JSType.toString(longIndex);
             final FindProperty find = findProperty(key, true);
-
             if (find != null) {
                 setObject(find, strict, key, value);
-                return;
+                return true;
             }
         }
-
-        setValueAtArrayIndex(longIndex, index, value, strict);
+        return false;
     }
 
-    /**
-     * Handle when an array doesn't have a slot - possibly grow and/or convert array.
-     *
-     * @param index  key as index
-     * @param value  element value
-     * @param strict are we in strict mode
-     */
-    private void setValueAtArrayIndex(final long longIndex, final int index, final Object value, final boolean strict) {
-        final long oldLength = getArray().length();
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final long value, final boolean strict) {
+        if (getMap().containsArrayKeys()) {
+            final String       key  = JSType.toString(longIndex);
+            final FindProperty find = findProperty(key, true);
+            if (find != null) {
+                setObject(find, strict, key, value);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final double value, final boolean strict) {
+         if (getMap().containsArrayKeys()) {
+            final String       key  = JSType.toString(longIndex);
+            final FindProperty find = findProperty(key, true);
+            if (find != null) {
+                setObject(find, strict, key, value);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean doesNotHaveCheckArrayKeys(final long longIndex, final Object value, final boolean strict) {
+        if (getMap().containsArrayKeys()) {
+            final String       key  = JSType.toString(longIndex);
+            final FindProperty find = findProperty(key, true);
+            if (find != null) {
+                setObject(find, strict, key, value);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    //value agnostic
+    private boolean doesNotHaveEnsureLength(final long longIndex, final long oldLength, final boolean strict) {
         if (longIndex >= oldLength) {
             if (!isExtensible()) {
                 if (strict) {
-                    throw typeError("object.non.extensible", JSType.toString(index), ScriptRuntime.safeToString(this));
+                    throw typeError("object.non.extensible", JSType.toString(longIndex), ScriptRuntime.safeToString(this));
                 }
-                return;
+                return true;
             }
             setArray(getArray().ensure(longIndex));
         }
+        return false;
+    }
 
-        if (value instanceof Integer) {
-            setArray(getArray().set(index, (int)value, strict));
-        } else if (value instanceof Long) {
-            setArray(getArray().set(index, (long)value, strict));
-        } else if (value instanceof Double) {
-            setArray(getArray().set(index, (double)value, strict));
-        } else {
-            setArray(getArray().set(index, value, strict));
-        }
-
+    private void doesNotHaveEnsureDelete(final long longIndex, final long oldLength, final boolean strict) {
         if (longIndex > oldLength) {
             ArrayData array = getArray();
-
-            if (array.canDelete(oldLength, (longIndex - 1), strict)) {
-                array = array.delete(oldLength, (longIndex - 1));
+            if (array.canDelete(oldLength, longIndex - 1, strict)) {
+                array = array.delete(oldLength, longIndex - 1);
             }
-
             setArray(array);
         }
     }
 
+    private void doesNotHave(final int index, final int value, final boolean strict) {
+        final long oldLength = getArray().length();
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+            setArray(getArray().set(index, value, strict));
+            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+        }
+    }
+
+    private void doesNotHave(final int index, final long value, final boolean strict) {
+        final long oldLength = getArray().length();
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+            setArray(getArray().set(index, value, strict));
+            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+        }
+    }
+
+    private void doesNotHave(final int index, final double value, final boolean strict) {
+        final long oldLength = getArray().length();
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+            setArray(getArray().set(index, value, strict));
+            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+        }
+    }
+
+    private void doesNotHave(final int index, final Object value, final boolean strict) {
+        final long oldLength = getArray().length();
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        if (!doesNotHaveCheckArrayKeys(longIndex, value, strict) && !doesNotHaveEnsureLength(longIndex, oldLength, strict)) {
+            setArray(getArray().set(index, value, strict));
+            doesNotHaveEnsureDelete(longIndex, oldLength, strict);
+        }
+    }
+
     /**
      * This is the most generic of all Object setters. Most of the others use this in some form.
      * TODO: should be further specialized
@@ -2831,7 +3112,7 @@
                 return;
             }
 
-            f.setObjectValue(value, strict);
+            f.setValue(value, strict);
 
         } else if (!isExtensible()) {
             if (strict) {
@@ -2846,19 +3127,17 @@
                 }
                 assert sobj != null : "no parent global object in scope";
             }
-            sobj.spill(key, value);
+            //this will unbox any Number object to its primitive type in case the
+            //property supports primitive types, so it doesn't matter that it comes
+            //in as an Object.
+            sobj.addSpillProperty(key, 0, value, true);
         }
     }
 
-    private void spill(final String key, final Object value) {
-        addSpillProperty(key, 0).setObjectValue(this, this, value, false);
-    }
-
-
     @Override
     public void set(final Object key, final int value, final boolean strict) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
+        final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
@@ -2877,7 +3156,7 @@
     @Override
     public void set(final Object key, final long value, final boolean strict) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
+        final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
@@ -2896,7 +3175,7 @@
     @Override
     public void set(final Object key, final double value, final boolean strict) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
+        final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
@@ -2915,7 +3194,7 @@
     @Override
     public void set(final Object key, final Object value, final boolean strict) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
+        final int    index        = getArrayIndex(primitiveKey);
 
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
@@ -3078,14 +3357,12 @@
     @Override
     public void set(final int key, final int value, final boolean strict) {
         final int index = getArrayIndex(key);
-
         if (isValidArrayIndex(index)) {
             if (getArray().has(index)) {
                 setArray(getArray().set(index, value, strict));
             } else {
                 doesNotHave(index, value, strict);
             }
-
             return;
         }
 
@@ -3150,7 +3427,7 @@
     @Override
     public boolean has(final Object key) {
         final Object primitiveKey = JSType.toPrimitive(key);
-        final int index = getArrayIndex(primitiveKey);
+        final int    index        = getArrayIndex(primitiveKey);
         return isValidArrayIndex(index) ? hasArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), true);
     }
 
@@ -3188,7 +3465,7 @@
     @Override
     public boolean hasOwnProperty(final Object key) {
         final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
+        final int    index        = getArrayIndex(primitiveKey);
         return isValidArrayIndex(index) ? hasOwnArrayProperty(index) : hasProperty(JSType.toString(primitiveKey), false);
     }
 
@@ -3211,7 +3488,7 @@
     }
 
     private boolean hasOwnArrayProperty(final int index) {
-        return getArray().has(index) || (getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false));
+        return getArray().has(index) || getMap().containsArrayKeys() && hasProperty(ArrayIndex.toKey(index), false);
     }
 
     @Override
@@ -3264,9 +3541,9 @@
 
     @Override
     public boolean delete(final Object key, final boolean strict) {
-        final Object primitiveKey = JSType.toPrimitive(key, String.class);
-        final int index = getArrayIndex(primitiveKey);
-        final ArrayData array = getArray();
+        final Object    primitiveKey = JSType.toPrimitive(key, String.class);
+        final int       index        = getArrayIndex(primitiveKey);
+        final ArrayData array        = getArray();
 
         if (array.has(index)) {
             if (array.canDelete(index, strict)) {
@@ -3311,60 +3588,91 @@
      * @return the newly created UserAccessorProperty
      */
     protected final UserAccessorProperty newUserAccessors(final String key, final int propertyFlags, final ScriptFunction getter, final ScriptFunction setter) {
-        final UserAccessorProperty property = getMap().newUserAccessors(key, propertyFlags);
-        setSpill(property.getGetterSlot(), getter);
-        setSpill(property.getSetterSlot(), setter);
-
-        return property;
+        final UserAccessorProperty uc = getMap().newUserAccessors(key, propertyFlags);
+        //property.getSetter(Object.class, getMap());
+        uc.setAccessors(this, getMap(), new UserAccessorProperty.Accessors(getter, setter));
+        return uc;
     }
 
-    /**
-     * Write a value to a spill slot
-     * @param slot  the slot index
-     * @param value the value
-     */
-    protected final void setSpill(final int slot, final Object value) {
-        if (spill == null) {
-            // create new spill.
-            spill = new Object[Math.max(slot + 1, SPILL_RATE)];
-        } else if (slot >= spill.length) {
-            // grow spill as needed
-            final Object[] newSpill = new Object[slot + 1];
-            System.arraycopy(spill, 0, newSpill, 0, spill.length);
-            spill = newSpill;
+    Object ensureSpillSize(final int slot) {
+        if (slot < spillLength) {
+            return this;
+        }
+        final int newLength = alignUp(slot + 1, SPILL_RATE);
+        final Object[] newObjectSpill    = new Object[newLength];
+        final long[]   newPrimitiveSpill = OBJECT_FIELDS_ONLY ? null : new long[newLength];
+
+        if (objectSpill != null) {
+            System.arraycopy(objectSpill, 0, newObjectSpill, 0, spillLength);
+            if (!OBJECT_FIELDS_ONLY) {
+                System.arraycopy(primitiveSpill, 0, newPrimitiveSpill, 0, spillLength);
+            }
         }
 
-        spill[slot] = value;
+        this.primitiveSpill = newPrimitiveSpill;
+        this.objectSpill    = newObjectSpill;
+        this.spillLength = newLength;
+
+        return this;
     }
 
-    /**
-     * Get a value from a spill slot
-     * @param slot the slot index
-     * @return the value in the spill slot with the given index
-     */
-    protected Object getSpill(final int slot) {
-        return spill != null && slot < spill.length ? spill[slot] : null;
+    private static MethodHandle findOwnMH_V(final Class<? extends ScriptObject> clazz, final String name, final Class<?> rtype, final Class<?>... types) {
+        // TODO: figure out how can it work for NativeArray$Prototype etc.
+        return MH.findVirtual(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        final Class<?>   own = ScriptObject.class;
-        final MethodType mt  = MH.type(rtype, types);
-        try {
-            return MH.findStatic(MethodHandles.lookup(), own, name, mt);
-        } catch (final MethodHandleFactory.LookupException e) {
-            return MH.findVirtual(MethodHandles.lookup(), own, name, mt);
-        }
+    private static MethodHandle findOwnMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+        return findOwnMH_V(ScriptObject.class, name, rtype, types);
     }
 
-    private static MethodHandle getKnownFunctionPropertyGuard(final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
-        return MH.insertArguments(KNOWNFUNCPROPGUARD, 1, map, getter, where, func);
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), ScriptObject.class, name, MH.type(rtype, types));
+    }
+
+    private static MethodHandle getKnownFunctionPropertyGuardSelf(final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
+        return MH.insertArguments(KNOWNFUNCPROPGUARDSELF, 1, map, getter, func);
     }
 
     @SuppressWarnings("unused")
-    private static boolean knownFunctionPropertyGuard(final Object self, final PropertyMap map, final MethodHandle getter, final Object where, final ScriptFunction func) {
+    private static boolean knownFunctionPropertyGuardSelf(final Object self, final PropertyMap map, final MethodHandle getter, final ScriptFunction func) {
         if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
             try {
-                return getter.invokeExact(where) == func;
+                return getter.invokeExact(self) == func;
+            } catch (final RuntimeException | Error e) {
+                throw e;
+            } catch (final Throwable t) {
+                throw new RuntimeException(t);
+            }
+        }
+
+        return false;
+    }
+
+    private static MethodHandle getKnownFunctionPropertyGuardProto(final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
+        return MH.insertArguments(KNOWNFUNCPROPGUARDPROTO, 1, map, getter, depth, func);
+    }
+
+    private static ScriptObject getProto(final ScriptObject self, final int depth) {
+        ScriptObject proto = self;
+        for (int d = 0; d < depth; d++) {
+            proto = proto.getProto();
+            if (proto == null) {
+                return null;
+            }
+        }
+
+        return proto;
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean knownFunctionPropertyGuardProto(final Object self, final PropertyMap map, final MethodHandle getter, final int depth, final ScriptFunction func) {
+        if (self instanceof ScriptObject && ((ScriptObject)self).getMap() == map) {
+            final ScriptObject proto = getProto((ScriptObject)self, depth);
+            if (proto == null) {
+                return false;
+            }
+            try {
+                return getter.invokeExact((Object)proto) == func;
             } catch (final RuntimeException | Error e) {
                 throw e;
             } catch (final Throwable t) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
index 6df047d..6c5758c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java
@@ -27,6 +27,7 @@
 
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
+import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.syntaxError;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
@@ -45,9 +46,11 @@
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.api.scripting.ScriptObjectMirror;
+import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
 import jdk.nashorn.internal.ir.debug.JSONWriter;
 import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.objects.NativeObject;
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
@@ -81,9 +84,6 @@
     /** Method handle used to enter a {@code with} scope at runtime. */
     public static final Call OPEN_WITH = staticCallNoLookup(ScriptRuntime.class, "openWith", ScriptObject.class, ScriptObject.class, Object.class);
 
-    /** Method handle used to exit a {@code with} scope at runtime. */
-    public static final Call CLOSE_WITH = staticCallNoLookup(ScriptRuntime.class, "closeWith", ScriptObject.class, ScriptObject.class);
-
     /**
      * Method used to place a scope's variable into the Global scope, which has to be done for the
      * properties declared at outermost script level.
@@ -121,7 +121,6 @@
                 return (int)d;
             }
         }
-
         return deflt;
     }
 
@@ -169,7 +168,7 @@
         // But we don't need to -- all we need is the right class name
         // of the corresponding primitive wrapper type.
 
-        final JSType type = JSType.of(self);
+        final JSType type = JSType.ofNoFunction(self);
 
         switch (type) {
         case BOOLEAN:
@@ -189,7 +188,6 @@
             className = "Undefined";
             break;
         case OBJECT:
-        case FUNCTION:
             if (self instanceof ScriptObject) {
                 className = ((ScriptObject)self).getClassName();
             } else if (self instanceof JSObject) {
@@ -271,7 +269,7 @@
         private final int length;
         private int index;
 
-        RangeIterator(int length) {
+        RangeIterator(final int length) {
             this.length = length;
         }
 
@@ -409,8 +407,8 @@
      * @return true if both objects have the same value
      */
     public static boolean sameValue(final Object x, final Object y) {
-        final JSType xType = JSType.of(x);
-        final JSType yType = JSType.of(y);
+        final JSType xType = JSType.ofNoFunction(x);
+        final JSType yType = JSType.ofNoFunction(y);
 
         if (xType != yType) {
             return false;
@@ -429,7 +427,7 @@
             }
 
             // checking for xVal == -0.0 and yVal == +0.0 or vice versa
-            if (xVal == 0.0 && (Double.doubleToLongBits(xVal) != Double.doubleToLongBits(yVal))) {
+            if (xVal == 0.0 && Double.doubleToLongBits(xVal) != Double.doubleToLongBits(yVal)) {
                 return false;
             }
 
@@ -440,7 +438,7 @@
             return x.equals(y);
         }
 
-        return (x == y);
+        return x == y;
     }
 
     /**
@@ -453,7 +451,7 @@
      * @return JSON string representation of AST of the supplied code
      */
     public static String parse(final String code, final String name, final boolean includeLoc) {
-        return JSONWriter.parse(Context.getContextTrusted().getEnv(), code, name, includeLoc);
+        return JSONWriter.parse(Context.getContextTrusted(), code, name, includeLoc);
     }
 
     /**
@@ -466,7 +464,8 @@
     }
 
     /**
-     * Entering a {@code with} node requires new scope. This is the implementation
+     * Entering a {@code with} node requires new scope. This is the implementation. When exiting the with statement,
+     * use {@link ScriptObject#getProto()} on the scope.
      *
      * @param scope      existing scope
      * @param expression expression in with
@@ -481,6 +480,17 @@
             throw typeError(global, "cant.apply.with.to.null");
         }
 
+        if (expression instanceof ScriptObjectMirror) {
+            final Object unwrapped = ScriptObjectMirror.unwrap(expression, global);
+            if (unwrapped instanceof ScriptObject) {
+                return new WithObject(scope, (ScriptObject)unwrapped);
+            }
+            // foreign ScriptObjectMirror
+            final ScriptObject exprObj = global.newObject();
+            NativeObject.bindAllProperties(exprObj, (ScriptObjectMirror)expression);
+            return new WithObject(scope, exprObj);
+        }
+
         final Object wrappedExpr = JSType.toScriptObject(global, expression);
         if (wrappedExpr instanceof ScriptObject) {
             return new WithObject(scope, (ScriptObject)wrappedExpr);
@@ -490,20 +500,6 @@
     }
 
     /**
-     * Exiting a {@code with} node requires restoring scope. This is the implementation
-     *
-     * @param scope existing scope
-     *
-     * @return restored scope
-     */
-    public static ScriptObject closeWith(final ScriptObject scope) {
-        if (scope instanceof WithObject) {
-            return ((WithObject)scope).getParentScope();
-        }
-        return scope;
-    }
-
-    /**
      * ECMA 11.6.1 - The addition operator (+) - generic implementation
      * Compiler specializes using {@link jdk.nashorn.internal.codegen.RuntimeCallSite}
      * if any type information is available for any of the operands
@@ -525,7 +521,7 @@
         final boolean xIsUndefined = x == UNDEFINED;
         final boolean yIsUndefined = y == UNDEFINED;
 
-        if ((xIsNumber && yIsUndefined) || (xIsUndefined && yIsNumber) || (xIsUndefined && yIsUndefined)) {
+        if (xIsNumber && yIsUndefined || xIsUndefined && yIsNumber || xIsUndefined && yIsUndefined) {
             return Double.NaN;
         }
 
@@ -535,7 +531,11 @@
 
         if (xPrim instanceof String || yPrim instanceof String
                 || xPrim instanceof ConsString || yPrim instanceof ConsString) {
-            return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim));
+            try {
+                return new ConsString(JSType.toCharSequence(xPrim), JSType.toCharSequence(yPrim));
+            } catch (final IllegalArgumentException iae) {
+                throw rangeError(iae, "concat.string.too.big");
+            }
         }
 
         return JSType.toNumber(xPrim) + JSType.toNumber(yPrim);
@@ -577,6 +577,13 @@
         if (property != null) {
             if (obj instanceof ScriptObject) {
                 obj = ((ScriptObject)obj).get(property);
+                if(Global.isLocationPropertyPlaceholder(obj)) {
+                    if(CompilerConstants.__LINE__.name().equals(property)) {
+                        obj = Integer.valueOf(0);
+                    } else {
+                        obj = "";
+                    }
+                }
             } else if (object instanceof Undefined) {
                 obj = ((Undefined)obj).get(property);
             } else if (object == null) {
@@ -689,67 +696,100 @@
 
     /** ECMA 11.9.3 The Abstract Equality Comparison Algorithm */
     private static boolean equals(final Object x, final Object y) {
-        final JSType xType = JSType.of(x);
-        final JSType yType = JSType.of(y);
-
-        if (xType == yType) {
-
-            if (xType == JSType.UNDEFINED || xType == JSType.NULL) {
-                return true;
-            }
-
-            if (xType == JSType.NUMBER) {
-                final double xVal = ((Number)x).doubleValue();
-                final double yVal = ((Number)y).doubleValue();
-                if (Double.isNaN(xVal) || Double.isNaN(yVal)) {
-                    return false;
-                }
-
-                return xVal == yVal;
-            }
-
-            if (xType == JSType.STRING) {
-                // String may be represented by ConsString
-                return x.toString().equals(y.toString());
-            }
-
-            if (xType == JSType.BOOLEAN) {
-                // Boolean comparison
-                return x.equals(y);
-            }
-
+        if (x == y) {
+            return true;
+        }
+        if (x instanceof ScriptObject && y instanceof ScriptObject) {
             return x == y;
         }
+        if (x instanceof ScriptObjectMirror || y instanceof ScriptObjectMirror) {
+            return ScriptObjectMirror.identical(x, y);
+        }
+        return equalValues(x, y);
+    }
 
-        if ((xType == JSType.UNDEFINED && yType == JSType.NULL) ||
-            (xType == JSType.NULL && yType == JSType.UNDEFINED)) {
+    /**
+     * Extracted portion of {@code equals()} that compares objects by value (or by reference, if no known value
+     * comparison applies).
+     * @param x one value
+     * @param y another value
+     * @return true if they're equal according to 11.9.3
+     */
+    private static boolean equalValues(final Object x, final Object y) {
+        final JSType xType = JSType.ofNoFunction(x);
+        final JSType yType = JSType.ofNoFunction(y);
+
+        if (xType == yType) {
+            return equalSameTypeValues(x, y, xType);
+        }
+
+        return equalDifferentTypeValues(x, y, xType, yType);
+    }
+
+    /**
+     * Extracted portion of {@link #equals(Object, Object)} and {@link #strictEquals(Object, Object)} that compares
+     * values belonging to the same JSType.
+     * @param x one value
+     * @param y another value
+     * @param type the common type for the values
+     * @return true if they're equal
+     */
+    private static boolean equalSameTypeValues(final Object x, final Object y, final JSType type) {
+        if (type == JSType.UNDEFINED || type == JSType.NULL) {
+            return true;
+        }
+
+        if (type == JSType.NUMBER) {
+            return ((Number)x).doubleValue() == ((Number)y).doubleValue();
+        }
+
+        if (type == JSType.STRING) {
+            // String may be represented by ConsString
+            return x.toString().equals(y.toString());
+        }
+
+        if (type == JSType.BOOLEAN) {
+            return ((Boolean)x).booleanValue() == ((Boolean)y).booleanValue();
+        }
+
+        return x == y;
+    }
+
+    /**
+     * Extracted portion of {@link #equals(Object, Object)} that compares values belonging to different JSTypes.
+     * @param x one value
+     * @param y another value
+     * @param xType the type for the value x
+     * @param yType the type for the value y
+     * @return true if they're equal
+     */
+    private static boolean equalDifferentTypeValues(final Object x, final Object y, final JSType xType, final JSType yType) {
+        if (xType == JSType.UNDEFINED && yType == JSType.NULL || xType == JSType.NULL && yType == JSType.UNDEFINED) {
             return true;
         }
 
         if (xType == JSType.NUMBER && yType == JSType.STRING) {
-            return EQ(x, JSType.toNumber(y));
+            return equals(x, JSType.toNumber(y));
         }
 
         if (xType == JSType.STRING && yType == JSType.NUMBER) {
-            return EQ(JSType.toNumber(x), y);
+            return equals(JSType.toNumber(x), y);
         }
 
         if (xType == JSType.BOOLEAN) {
-            return EQ(JSType.toNumber(x), y);
+            return equals(JSType.toNumber(x), y);
         }
 
         if (yType == JSType.BOOLEAN) {
-            return EQ(x, JSType.toNumber(y));
+            return equals(x, JSType.toNumber(y));
         }
 
-        if ((xType == JSType.STRING || xType == JSType.NUMBER) &&
-             (y instanceof ScriptObject))  {
-            return EQ(x, JSType.toPrimitive(y));
+        if ((xType == JSType.STRING || xType == JSType.NUMBER) && y instanceof ScriptObject)  {
+            return equals(x, JSType.toPrimitive(y));
         }
 
-        if ((x instanceof ScriptObject) &&
-            (yType == JSType.STRING || yType == JSType.NUMBER)) {
-            return EQ(JSType.toPrimitive(x), y);
+        if (x instanceof ScriptObject && (yType == JSType.STRING || yType == JSType.NUMBER)) {
+            return equals(JSType.toPrimitive(x), y);
         }
 
         return false;
@@ -781,39 +821,17 @@
 
     /** ECMA 11.9.6 The Strict Equality Comparison Algorithm */
     private static boolean strictEquals(final Object x, final Object y) {
-        final JSType xType = JSType.of(x);
-        final JSType yType = JSType.of(y);
+        // NOTE: you might be tempted to do a quick x == y comparison. Remember, though, that any Double object having
+        // NaN value is not equal to itself by value even though it is referentially.
+
+        final JSType xType = JSType.ofNoFunction(x);
+        final JSType yType = JSType.ofNoFunction(y);
 
         if (xType != yType) {
             return false;
         }
 
-        if (xType == JSType.UNDEFINED || xType == JSType.NULL) {
-            return true;
-        }
-
-        if (xType == JSType.NUMBER) {
-            final double xVal = ((Number)x).doubleValue();
-            final double yVal = ((Number)y).doubleValue();
-
-            if (Double.isNaN(xVal) || Double.isNaN(yVal)) {
-                return false;
-            }
-
-            return xVal == yVal;
-        }
-
-        if (xType == JSType.STRING) {
-            // String may be represented by ConsString
-            return x.toString().equals(y.toString());
-        }
-
-        if (xType == JSType.BOOLEAN) {
-            return x.equals(y);
-        }
-
-        // finally, the object identity comparison
-        return x == y;
+        return equalSameTypeValues(x, y, xType);
     }
 
     /**
@@ -825,9 +843,9 @@
      * @return true if objects are equal
      */
     public static boolean IN(final Object property, final Object obj) {
-        final JSType rvalType = JSType.of(obj);
+        final JSType rvalType = JSType.ofNoFunction(obj);
 
-        if (rvalType == JSType.OBJECT || rvalType == JSType.FUNCTION) {
+        if (rvalType == JSType.OBJECT) {
             if (obj instanceof ScriptObject) {
                 return ((ScriptObject)obj).has(property);
             }
@@ -884,7 +902,7 @@
      */
     public static boolean LT(final Object x, final Object y) {
         final Object value = lessThan(x, y, true);
-        return (value == UNDEFINED) ? false : (Boolean)value;
+        return value == UNDEFINED ? false : (Boolean)value;
     }
 
     /**
@@ -897,7 +915,7 @@
      */
     public static boolean GT(final Object x, final Object y) {
         final Object value = lessThan(y, x, false);
-        return (value == UNDEFINED) ? false : (Boolean)value;
+        return value == UNDEFINED ? false : (Boolean)value;
     }
 
     /**
@@ -910,7 +928,7 @@
      */
     public static boolean LE(final Object x, final Object y) {
         final Object value = lessThan(y, x, false);
-        return (!(Boolean.TRUE.equals(value) || value == UNDEFINED));
+        return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
     }
 
     /**
@@ -923,7 +941,7 @@
      */
     public static boolean GE(final Object x, final Object y) {
         final Object value = lessThan(x, y, true);
-        return (!(Boolean.TRUE.equals(value) || value == UNDEFINED));
+        return !(Boolean.TRUE.equals(value) || value == UNDEFINED);
     }
 
     /** ECMA 11.8.5 The Abstract Relational Comparison Algorithm */
@@ -939,9 +957,9 @@
             px = JSType.toPrimitive(x, Number.class);
         }
 
-        if (JSType.of(px) == JSType.STRING && JSType.of(py) == JSType.STRING) {
+        if (JSType.ofNoFunction(px) == JSType.STRING && JSType.ofNoFunction(py) == JSType.STRING) {
             // May be String or ConsString
-            return (px.toString()).compareTo(py.toString()) < 0;
+            return px.toString().compareTo(py.toString()) < 0;
         }
 
         final double nx = JSType.toNumber(px);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
index 8a03533..2113b79 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptingFunctions.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-import static jdk.nashorn.internal.lookup.Lookup.MH;
 
 import java.io.BufferedReader;
 import java.io.File;
@@ -107,8 +107,8 @@
 
         if (file instanceof File) {
             f = (File)file;
-        } else if (file instanceof String) {
-            f = new java.io.File((String)file);
+        } else if (file instanceof String || file instanceof ConsString) {
+            f = new java.io.File(((CharSequence)file).toString());
         }
 
         if (f == null || !f.isFile()) {
@@ -157,7 +157,7 @@
             // Set up ENV variables.
             final Map<String, String> environment = processBuilder.environment();
             environment.clear();
-            for (Map.Entry<Object, Object> entry : envProperties.entrySet()) {
+            for (final Map.Entry<Object, Object> entry : envProperties.entrySet()) {
                 environment.put(JSType.toString(entry.getKey()), JSType.toString(entry.getValue()));
             }
         }
@@ -168,15 +168,15 @@
 
         // Collect output.
         final StringBuilder outBuffer = new StringBuilder();
-        Thread outThread = new Thread(new Runnable() {
+        final Thread outThread = new Thread(new Runnable() {
             @Override
             public void run() {
-                char buffer[] = new char[1024];
+                final char buffer[] = new char[1024];
                 try (final InputStreamReader inputStream = new InputStreamReader(process.getInputStream())) {
                     for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) {
                         outBuffer.append(buffer, 0, length);
                     }
-                } catch (IOException ex) {
+                } catch (final IOException ex) {
                     exception[0] = ex;
                 }
             }
@@ -184,15 +184,15 @@
 
         // Collect errors.
         final StringBuilder errBuffer = new StringBuilder();
-        Thread errThread = new Thread(new Runnable() {
+        final Thread errThread = new Thread(new Runnable() {
             @Override
             public void run() {
-                char buffer[] = new char[1024];
+                final char buffer[] = new char[1024];
                 try (final InputStreamReader inputStream = new InputStreamReader(process.getErrorStream())) {
                     for (int length; (length = inputStream.read(buffer, 0, buffer.length)) != -1; ) {
                         errBuffer.append(buffer, 0, length);
                     }
-                } catch (IOException ex) {
+                } catch (final IOException ex) {
                     exception[1] = ex;
                 }
             }
@@ -205,10 +205,10 @@
         // If input is present, pass on to process.
         try (OutputStreamWriter outputStream = new OutputStreamWriter(process.getOutputStream())) {
             if (input != UNDEFINED) {
-                String in = JSType.toString(input);
+                final String in = JSType.toString(input);
                 outputStream.write(in, 0, in.length());
             }
-        } catch (IOException ex) {
+        } catch (final IOException ex) {
             // Process was not expecting input.  May be normal state of affairs.
         }
 
@@ -226,9 +226,9 @@
         global.set(EXIT_NAME, exit, false);
 
         // Propagate exception if present.
-        for (int i = 0; i < exception.length; i++) {
-            if (exception[i] != null) {
-                throw exception[i];
+        for (final IOException element : exception) {
+            if (element != null) {
+                throw element;
             }
         }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
index edee374..4b392ba 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SetMethodCreator.java
@@ -25,17 +25,17 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
 
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.SwitchPoint;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 
-
 /**
  * Instances of this class are quite ephemeral; they only exist for the duration of an invocation of
  * {@link ScriptObject#findSetMethod(CallSiteDescriptor, jdk.internal.dynalink.linker.LinkRequest)} and
@@ -43,10 +43,12 @@
  */
 final class SetMethodCreator {
     // See constructor parameters for description of fields
-    private final ScriptObject sobj;
-    private final PropertyMap map;
-    private final FindProperty find;
+    private final ScriptObject       sobj;
+    private final PropertyMap        map;
+    private final FindProperty       find;
     private final CallSiteDescriptor desc;
+    private final Class<?>           type;
+    private final boolean            explicitInstanceOfCheck;
 
     /**
      * Creates a new property setter method creator.
@@ -55,11 +57,14 @@
      * want to create a setter for. Can be null if the property does not yet exist on the object.
      * @param desc the descriptor of the call site that triggered the property setter lookup
      */
-    SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc) {
+    SetMethodCreator(final ScriptObject sobj, final FindProperty find, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) {
         this.sobj = sobj;
-        this.map = sobj.getMap();
+        this.map  = sobj.getMap();
         this.find = find;
         this.desc = desc;
+        this.type = desc.getMethodType().parameterType(1);
+        this.explicitInstanceOfCheck = explicitInstanceOfCheck;
+
     }
 
     private String getName() {
@@ -95,7 +100,7 @@
         SetMethod(final MethodHandle methodHandle, final Property property) {
             assert methodHandle != null;
             this.methodHandle = methodHandle;
-            this.property = property;
+            this.property     = property;
         }
 
         /**
@@ -103,9 +108,12 @@
          * @return the composed guarded invocation that represents the dynamic setter method for the property.
          */
         GuardedInvocation createGuardedInvocation() {
-            return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc));
+            // getGuard() and getException() either both return null, or neither does. The reason for that is that now
+            // getGuard returns a map guard that casts its argument to ScriptObject, and if that fails, we need to
+            // relink on ClassCastException.
+            return new GuardedInvocation(methodHandle, NashornGuards.getGuard(sobj, property, desc, explicitInstanceOfCheck),
+                    (SwitchPoint)null, explicitInstanceOfCheck ? null : ClassCastException.class);
         }
-
     }
 
     private SetMethod createSetMethod() {
@@ -132,7 +140,6 @@
 
     private SetMethod createExistingPropertySetter() {
         final Property property = find.getProperty();
-        final Class<?> type = desc.getMethodType().parameterType(1);
         final MethodHandle methodHandle = find.getSetter(type, NashornCallSiteDescriptor.isStrict(desc));
 
         assert methodHandle != null;
@@ -149,11 +156,11 @@
 
     private SetMethod createGlobalPropertySetter() {
         final ScriptObject global = Context.getGlobal();
-        return new SetMethod(MH.filterArguments(global.addSpill(getName()), 0, ScriptObject.GLOBALFILTER), null);
+        return new SetMethod(MH.filterArguments(global.addSpill(type, getName()), 0, ScriptObject.GLOBALFILTER), null);
     }
 
     private SetMethod createNewPropertySetter() {
-        final SetMethod sm = map.getFieldCount() < map.getFieldMaximum() ? createNewFieldSetter() : createNewSpillPropertySetter();
+        final SetMethod sm = map.getFreeFieldSlot() > -1 ? createNewFieldSetter() : createNewSpillPropertySetter();
         final PropertyListeners listeners = map.getListeners();
         if (listeners != null) {
             listeners.propertyAdded(sm.property);
@@ -161,38 +168,51 @@
         return sm;
     }
 
-    private SetMethod createNewFieldSetter() {
-        final PropertyMap oldMap = getMap();
-        final Property property = new AccessorProperty(getName(), 0, sobj.getClass(), oldMap.getFieldCount());
-        final PropertyMap newMap = oldMap.addProperty(property);
-        MethodHandle setter = MH.insertArguments(ScriptObject.SETFIELD, 0, desc, oldMap, newMap, property.getSetter(Object.class, newMap));
+    private SetMethod createNewSetter(final Property property) {
+        final PropertyMap oldMap   = getMap();
+        final PropertyMap newMap   = getNewMap(property);
+        final boolean     isStrict = NashornCallSiteDescriptor.isStrict(desc);
+        final String      name     = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
 
-        return new SetMethod(MH.asType(setter, Lookup.SET_OBJECT_TYPE), property);
+        //fast type specific setter
+        final MethodHandle fastSetter = property.getSetter(type, newMap); //0 sobj, 1 value, slot folded for spill property already
+
+        //slow setter, that calls ScriptObject.set with appropraite type and key name
+        MethodHandle slowSetter = ScriptObject.SET_SLOW[getAccessorTypeIndex(type)];
+        slowSetter = MH.insertArguments(slowSetter, 3, NashornCallSiteDescriptor.isStrict(desc));
+        slowSetter = MH.insertArguments(slowSetter, 1, name);
+        slowSetter = MH.asType(slowSetter, slowSetter.type().changeParameterType(0, Object.class));
+
+        assert slowSetter.type().equals(fastSetter.type()) : "slow=" + slowSetter + " != fast=" + fastSetter;
+
+        //cas map used as guard, if true that means we can do the set fast
+        MethodHandle casMap = MH.insertArguments(ScriptObject.CAS_MAP, 1, oldMap, newMap);
+        casMap = MH.dropArguments(casMap, 1, type);
+        casMap = MH.asType(casMap, casMap.type().changeParameterType(0, Object.class));
+        final MethodHandle casGuard = MH.guardWithTest(casMap, fastSetter, slowSetter);
+
+        //outermost level needs an extendable check. if object can be extended, guard is true and
+        //we can run the cas setter. The setter goes to "nop" VOID_RETURN if false or throws an
+        //exception if we are in strict mode and object is not extensible
+        MethodHandle extCheck = MH.insertArguments(ScriptObject.EXTENSION_CHECK, 1, isStrict, name);
+        extCheck = MH.asType(extCheck, extCheck.type().changeParameterType(0, Object.class));
+        extCheck = MH.dropArguments(extCheck, 1, type);
+
+        MethodHandle nop = JSType.VOID_RETURN.methodHandle();
+        nop = MH.dropArguments(nop, 0, Object.class, type);
+
+        return new SetMethod(MH.asType(MH.guardWithTest(extCheck, casGuard, nop), fastSetter.type()), property);
+    }
+
+    private SetMethod createNewFieldSetter() {
+        return createNewSetter(new AccessorProperty(getName(), 0, sobj.getClass(), getMap().getFreeFieldSlot(), type));
     }
 
     private SetMethod createNewSpillPropertySetter() {
-        final int nextSpill = getMap().getSpillLength();
-
-        final Property property = new AccessorProperty(getName(), Property.IS_SPILL, nextSpill);
-        return new SetMethod(createSpillMethodHandle(nextSpill, property), property);
+        return createNewSetter(new SpillProperty(getName(), 0, getMap().getFreeSpillSlot(), type));
     }
 
-    private MethodHandle createSpillMethodHandle(final int nextSpill, Property property) {
-        final PropertyMap oldMap = getMap();
-        final PropertyMap newMap = getNewMap(property);
-
-        final Object[] spill = sobj.spill;
-        if (spill == null) {
-            return MH.insertArguments(ScriptObject.SETSPILLWITHNEW,  0, desc, oldMap, newMap, nextSpill);
-        } else if (nextSpill < spill.length) {
-            return MH.insertArguments(ScriptObject.SETSPILL,         0, desc, oldMap, newMap, nextSpill);
-        } else {
-            final int newLength = (nextSpill + ScriptObject.SPILL_RATE) / ScriptObject.SPILL_RATE * ScriptObject.SPILL_RATE;
-            return MH.insertArguments(ScriptObject.SETSPILLWITHGROW, 0, desc, oldMap, newMap, nextSpill, newLength);
-        }
-    }
-
-    private PropertyMap getNewMap(Property property) {
+    private PropertyMap getNewMap(final Property property) {
         return getMap().addProperty(property);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Source.java b/nashorn/src/jdk/nashorn/internal/runtime/Source.java
index 1423c16..38d4b85 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Source.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Source.java
@@ -45,20 +45,25 @@
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
+import java.util.Base64;
 import java.util.Objects;
 import java.util.WeakHashMap;
 import jdk.nashorn.api.scripting.URLReader;
 import jdk.nashorn.internal.parser.Token;
-
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 /**
  * Source objects track the origin of JavaScript entities.
  */
-public final class Source {
-
-    private static final DebugLogger DEBUG = new DebugLogger("source");
+@Logger(name="source")
+public final class Source implements Loggable {
     private static final int BUF_SIZE = 8 * 1024;
     private static final Cache CACHE = new Cache();
 
+    // Message digest to file name encoder
+    private final static Base64.Encoder BASE64 = Base64.getUrlEncoder().withoutPadding();
+
     /**
      * Descriptive name of the source as supplied by the user. Used for error
      * reporting to the user. For example, SyntaxError will use this to print message.
@@ -79,8 +84,11 @@
     /** Cached hash code */
     private int hash;
 
-    /** Message digest */
-    private byte[] digest;
+    /** Base64-encoded SHA1 digest of this source object */
+    private volatile byte[] digest;
+
+    /** source URL set via //@ sourceURL or //# sourceURL directive */
+    private String explicitURL;
 
     // Do *not* make this public, ever! Trusts the URL and content.
     private Source(final String name, final String base, final Data data) {
@@ -97,13 +105,14 @@
                 // Force any access errors
                 data.checkPermissionAndClose();
                 return existingSource;
-            } else {
-                // All sources in cache must be fully loaded
-                data.load();
-                CACHE.put(newSource, newSource);
-                return newSource;
             }
-        } catch (RuntimeException e) {
+
+            // All sources in cache must be fully loaded
+            data.load();
+            CACHE.put(newSource, newSource);
+
+            return newSource;
+        } catch (final RuntimeException e) {
             final Throwable cause = e.getCause();
             if (cause instanceof IOException) {
                 throw (IOException) cause;
@@ -139,40 +148,46 @@
         long lastModified();
 
         char[] array();
+
+        boolean isEvalCode();
     }
 
     private static class RawData implements Data {
         private final char[] array;
+        private final boolean evalCode;
         private int hash;
 
-        private RawData(final char[] array) {
+        private RawData(final char[] array, final boolean evalCode) {
             this.array = Objects.requireNonNull(array);
+            this.evalCode = evalCode;
         }
 
-        private RawData(final String source) {
+        private RawData(final String source, final boolean evalCode) {
             this.array = Objects.requireNonNull(source).toCharArray();
+            this.evalCode = evalCode;
         }
 
         private RawData(final Reader reader) throws IOException {
-            this(readFully(reader));
+            this(readFully(reader), false);
         }
 
         @Override
         public int hashCode() {
             int h = hash;
             if (h == 0) {
-                h = hash = Arrays.hashCode(array);
+                h = hash = Arrays.hashCode(array) ^ (evalCode? 1 : 0);
             }
             return h;
         }
 
         @Override
-        public boolean equals(Object obj) {
+        public boolean equals(final Object obj) {
             if (this == obj) {
                 return true;
             }
             if (obj instanceof RawData) {
-                return Arrays.equals(array, ((RawData)obj).array);
+                final RawData other = (RawData)obj;
+                return Arrays.equals(array, other.array) && evalCode == other.evalCode;
             }
             return false;
         }
@@ -203,6 +218,10 @@
         }
 
 
+        @Override
+        public boolean isEvalCode() {
+            return evalCode;
+        }
     }
 
     private static class URLData implements Data {
@@ -228,7 +247,7 @@
         }
 
         @Override
-        public boolean equals(Object other) {
+        public boolean equals(final Object other) {
             if (this == other) {
                 return true;
             }
@@ -236,7 +255,7 @@
                 return false;
             }
 
-            URLData otherData = (URLData) other;
+            final URLData otherData = (URLData) other;
 
             if (url.equals(otherData.url)) {
                 // Make sure both have meta data loaded
@@ -248,7 +267,7 @@
                     } else if (otherData.isDeferred()) {
                         otherData.loadMeta();
                     }
-                } catch (IOException e) {
+                } catch (final IOException e) {
                     throw new RuntimeException(e);
                 }
 
@@ -284,12 +303,20 @@
             return array;
         }
 
+        @Override
+        public boolean isEvalCode() {
+            return false;
+        }
+
         boolean isDeferred() {
             return array == null;
         }
 
+        @SuppressWarnings("try")
         protected void checkPermissionAndClose() throws IOException {
-            try (InputStream in = url.openStream()) {}
+            try (InputStream in = url.openStream()) {
+                // empty
+            }
             debug("permission checked for ", url);
         }
 
@@ -353,7 +380,10 @@
     }
 
     private static void debug(final Object... msg) {
-        DEBUG.info(msg);
+        final DebugLogger logger = getLoggerStatic();
+        if (logger != null) {
+            logger.info(msg);
+        }
     }
 
     private char[] data() {
@@ -361,23 +391,50 @@
     }
 
     /**
-     * Returns an instance
+     * Returns a Source instance
      *
      * @param name    source name
      * @param content contents as char array
+     * @param isEval does this represent code from 'eval' call?
+     * @return source instance
      */
-    public static Source sourceFor(final String name, final char[] content) {
-        return new Source(name, baseName(name), new RawData(content));
+    public static Source sourceFor(final String name, final char[] content, final boolean isEval) {
+        return new Source(name, baseName(name), new RawData(content, isEval));
     }
 
     /**
-     * Returns an instance
+     * Returns a Source instance
+     *
+     * @param name    source name
+     * @param content contents as char array
+     *
+     * @return source instance
+     */
+    public static Source sourceFor(final String name, final char[] content) {
+        return sourceFor(name, content, false);
+    }
+
+    /**
+     * Returns a Source instance
      *
      * @param name    source name
      * @param content contents as string
+     * @param isEval does this represent code from 'eval' call?
+     * @return source instance
+     */
+    public static Source sourceFor(final String name, final String content, final boolean isEval) {
+        return new Source(name, baseName(name), new RawData(content, isEval));
+    }
+
+    /**
+     * Returns a Source instance
+     *
+     * @param name    source name
+     * @param content contents as string
+     * @return source instance
      */
     public static Source sourceFor(final String name, final String content) {
-        return new Source(name, baseName(name), new RawData(content));
+        return sourceFor(name, content, false);
     }
 
     /**
@@ -386,6 +443,8 @@
      * @param name  source name
      * @param url   url from which source can be loaded
      *
+     * @return source instance
+     *
      * @throws IOException if source cannot be loaded
      */
     public static Source sourceFor(final String name, final URL url) throws IOException {
@@ -399,6 +458,8 @@
      * @param url   url from which source can be loaded
      * @param cs    Charset used to convert bytes to chars
      *
+     * @return source instance
+     *
      * @throws IOException if source cannot be loaded
      */
     public static Source sourceFor(final String name, final URL url, final Charset cs) throws IOException {
@@ -411,6 +472,8 @@
      * @param name  source name
      * @param file  file from which source can be loaded
      *
+     * @return source instance
+     *
      * @throws IOException if source cannot be loaded
      */
     public static Source sourceFor(final String name, final File file) throws IOException {
@@ -424,6 +487,8 @@
      * @param file  file from which source can be loaded
      * @param cs    Charset used to convert bytes to chars
      *
+     * @return source instance
+     *
      * @throws IOException if source cannot be loaded
      */
     public static Source sourceFor(final String name, final File file, final Charset cs) throws IOException {
@@ -436,6 +501,9 @@
      *
      * @param name source name
      * @param reader reader from which source can be loaded
+     *
+     * @return source instance
+     *
      * @throws IOException if source cannot be loaded
      */
     public static Source sourceFor(final String name, final Reader reader) throws IOException {
@@ -532,14 +600,39 @@
     }
 
     /**
+     * Get explicit source URL.
+     * @return URL set vial sourceURL directive
+     */
+    public String getExplicitURL() {
+        return explicitURL;
+    }
+
+    /**
+     * Set explicit source URL.
+     * @param explicitURL URL set via sourceURL directive
+     */
+    public void setExplicitURL(final String explicitURL) {
+        this.explicitURL = explicitURL;
+    }
+
+    /**
+     * Returns whether this source was submitted via 'eval' call or not.
+     *
+     * @return true if this source represents code submitted via 'eval'
+     */
+    public boolean isEvalCode() {
+        return data.isEvalCode();
+    }
+
+    /**
      * Find the beginning of the line containing position.
      * @param position Index to offending token.
      * @return Index of first character of line.
      */
     private int findBOLN(final int position) {
-        final char[] data = data();
+        final char[] d = data();
         for (int i = position - 1; i > 0; i--) {
-            final char ch = data[i];
+            final char ch = d[i];
 
             if (ch == '\n' || ch == '\r') {
                 return i + 1;
@@ -555,10 +648,10 @@
      * @return Index of last character of line.
      */
     private int findEOLN(final int position) {
-        final char[] data = data();
-        final int length = data.length;
+        final char[] d = data();
+        final int length = d.length;
         for (int i = position; i < length; i++) {
-            final char ch = data[i];
+            final char ch = d[i];
 
             if (ch == '\n' || ch == '\r') {
                 return i - 1;
@@ -578,12 +671,12 @@
      * @return Line number.
      */
     public int getLine(final int position) {
-        final char[] data = data();
+        final char[] d = data();
         // Line count starts at 1.
         int line = 1;
 
         for (int i = 0; i < position; i++) {
-            final char ch = data[i];
+            final char ch = d[i];
             // Works for both \n and \r\n.
             if (ch == '\n') {
                 line++;
@@ -618,11 +711,16 @@
     }
 
     /**
-     * Get the content of this source as a char array
-     * @return content
+     * Get the content of this source as a char array. Note that the underlying array is returned instead of a
+     * clone; modifying the char array will cause modification to the source; this should not be done. While
+     * there is an apparent danger that we allow unfettered access to an underlying mutable array, the
+     * {@code Source} class is in a restricted {@code jdk.nashorn.internal.*} package and as such it is
+     * inaccessible by external actors in an environment with a security manager. Returning a clone would be
+     * detrimental to performance.
+     * @return content the content of this source as a char array
      */
     public char[] getContent() {
-        return data().clone();
+        return data();
     }
 
     /**
@@ -711,12 +809,17 @@
     }
 
     /**
-     * Get a message digest for this source.
+     * Get a Base64-encoded SHA1 digest for this source.
      *
-     * @return a message digest for this source
+     * @return a Base64-encoded SHA1 digest for this source
      */
-    public synchronized byte[] getDigest() {
-        if (digest == null) {
+    public String getDigest() {
+        return new String(getDigestBytes(), StandardCharsets.US_ASCII);
+    }
+
+    private byte[] getDigestBytes() {
+        byte[] ldigest = digest;
+        if (ldigest == null) {
             final char[] content = data();
             final byte[] bytes = new byte[content.length * 2];
 
@@ -736,12 +839,12 @@
                 if (getURL() != null) {
                     md.update(getURL().toString().getBytes(StandardCharsets.UTF_8));
                 }
-                digest = md.digest(bytes);
-            } catch (NoSuchAlgorithmException e) {
+                digest = ldigest = BASE64.encode(md.digest(bytes));
+            } catch (final NoSuchAlgorithmException e) {
                 throw new RuntimeException(e);
             }
         }
-        return digest;
+        return ldigest;
     }
 
     /**
@@ -847,4 +950,19 @@
             return null;
         }
     }
+
+    private static DebugLogger getLoggerStatic() {
+        final Context context = Context.getContextTrustedOrNull();
+        return context == null ? null : context.getLogger(Source.class);
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return initLogger(Context.getContextTrusted());
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java
new file mode 100644
index 0000000..8ff1b8e
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/SpillProperty.java
@@ -0,0 +1,217 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static jdk.nashorn.internal.codegen.ObjectClassGenerator.OBJECT_FIELDS_ONLY;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+
+/**
+ * Spill property
+ */
+public class SpillProperty extends AccessorProperty {
+    private static final long serialVersionUID = 3028496245198669460L;
+
+    private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+    private static final MethodHandle PARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "primitiveSpill",  long[].class), MH.type(long[].class, Object.class));
+    private static final MethodHandle OARRAY_GETTER = MH.asType(MH.getter(LOOKUP, ScriptObject.class, "objectSpill",  Object[].class), MH.type(Object[].class, Object.class));
+
+    private static final MethodHandle OBJECT_GETTER    = MH.filterArguments(MH.arrayElementGetter(Object[].class), 0, OARRAY_GETTER);
+    private static final MethodHandle PRIMITIVE_GETTER = MH.filterArguments(MH.arrayElementGetter(long[].class), 0, PARRAY_GETTER);
+    private static final MethodHandle OBJECT_SETTER    = MH.filterArguments(MH.arrayElementSetter(Object[].class), 0, OARRAY_GETTER);
+    private static final MethodHandle PRIMITIVE_SETTER = MH.filterArguments(MH.arrayElementSetter(long[].class), 0, PARRAY_GETTER);
+
+    private static class Accessors {
+        private MethodHandle objectGetter;
+        private MethodHandle objectSetter;
+        private MethodHandle primitiveGetter;
+        private MethodHandle primitiveSetter;
+
+        private final int slot;
+        private final MethodHandle ensureSpillSize;
+
+        private static Accessors ACCESSOR_CACHE[] = new Accessors[512];
+
+        //private static final Map<Integer, Reference<Accessors>> ACCESSOR_CACHE = Collections.synchronizedMap(new WeakHashMap<Integer, Reference<Accessors>>());
+
+        Accessors(final int slot) {
+            assert slot >= 0;
+            this.slot = slot;
+            this.ensureSpillSize = MH.asType(MH.insertArguments(ScriptObject.ENSURE_SPILL_SIZE, 1, slot), MH.type(Object.class, Object.class));
+        }
+
+        private static void ensure(final int slot) {
+            int len = ACCESSOR_CACHE.length;
+            if (slot >= len) {
+                do {
+                    len *= 2;
+                } while (slot >= len);
+                final Accessors newCache[] = new Accessors[len];
+                System.arraycopy(ACCESSOR_CACHE, 0, newCache, 0, ACCESSOR_CACHE.length);
+                ACCESSOR_CACHE = newCache;
+            }
+        }
+
+        static MethodHandle getCached(final int slot, final boolean isPrimitive, final boolean isGetter) {
+            //Reference<Accessors> ref = ACCESSOR_CACHE.get(slot);
+            ensure(slot);
+            Accessors acc = ACCESSOR_CACHE[slot];
+            if (acc == null) {
+                acc = new Accessors(slot);
+                ACCESSOR_CACHE[slot] = acc;
+            }
+
+            return acc.getOrCreate(isPrimitive, isGetter);
+        }
+
+        private static MethodHandle primordial(final boolean isPrimitive, final boolean isGetter) {
+            if (isPrimitive) {
+                return isGetter ? PRIMITIVE_GETTER : PRIMITIVE_SETTER;
+            }
+            return isGetter ? OBJECT_GETTER : OBJECT_SETTER;
+        }
+
+        MethodHandle getOrCreate(final boolean isPrimitive, final boolean isGetter) {
+            MethodHandle accessor;
+
+            accessor = getInner(isPrimitive, isGetter);
+            if (accessor != null) {
+                return accessor;
+            }
+
+            accessor = primordial(isPrimitive, isGetter);
+            accessor = MH.insertArguments(accessor, 1, slot);
+            if (!isGetter) {
+                accessor = MH.filterArguments(accessor, 0, ensureSpillSize);
+            }
+            setInner(isPrimitive, isGetter, accessor);
+
+            return accessor;
+        }
+
+        void setInner(final boolean isPrimitive, final boolean isGetter, final MethodHandle mh) {
+            if (isPrimitive) {
+                if (isGetter) {
+                    primitiveGetter = mh;
+                } else {
+                    primitiveSetter = mh;
+                }
+            } else {
+                if (isGetter) {
+                    objectGetter = mh;
+                } else {
+                    objectSetter = mh;
+                }
+            }
+        }
+
+        MethodHandle getInner(final boolean isPrimitive, final boolean isGetter) {
+            if (isPrimitive) {
+                return isGetter ? primitiveGetter : primitiveSetter;
+            }
+            return isGetter ? objectGetter : objectSetter;
+        }
+    }
+
+    private static MethodHandle primitiveGetter(final int slot) {
+        return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, true);
+    }
+    private static MethodHandle primitiveSetter(final int slot) {
+        return OBJECT_FIELDS_ONLY ? null : Accessors.getCached(slot, true, false);
+    }
+    private static MethodHandle objectGetter(final int slot) {
+        return Accessors.getCached(slot, false, true);
+    }
+    private static MethodHandle objectSetter(final int slot) {
+        return Accessors.getCached(slot, false, false);
+    }
+
+    /**
+     * Constructor for spill properties. Array getters and setters will be created on demand.
+     *
+     * @param key    the property key
+     * @param flags  the property flags
+     * @param slot   spill slot
+     */
+    public SpillProperty(final String key, final int flags, final int slot) {
+        super(key, flags, slot, primitiveGetter(slot), primitiveSetter(slot), objectGetter(slot), objectSetter(slot));
+        assert !OBJECT_FIELDS_ONLY || getCurrentType() == Object.class;
+    }
+
+    SpillProperty(final String key, final int flags, final int slot, final Class<?> initialType) {
+        this(key, flags, slot);
+        setCurrentType(OBJECT_FIELDS_ONLY ? Object.class : initialType);
+    }
+
+    SpillProperty(final String key, final int flags, final int slot, final ScriptObject owner, final Object initialValue) {
+        this(key, flags, slot);
+        setInitialValue(owner, initialValue);
+    }
+
+    /**
+     * Copy constructor
+     * @param property other property
+     */
+    protected SpillProperty(final SpillProperty property) {
+        super(property);
+    }
+
+    /**
+     * Copy constructor
+     * @param newType new type
+     * @param property other property
+     */
+    protected SpillProperty(final SpillProperty property, final Class<?> newType) {
+        super(property, newType);
+    }
+
+    @Override
+    public Property copy() {
+        return new SpillProperty(this);
+    }
+
+    @Override
+    public Property copy(final Class<?> newType) {
+        return new SpillProperty(this, newType);
+    }
+
+    @Override
+    public boolean isSpill() {
+        return true;
+    }
+
+    @Override
+    void initMethodHandles(final Class<?> structure) {
+        final int slot  = getSlot();
+        primitiveGetter = primitiveGetter(slot);
+        primitiveSetter = primitiveSetter(slot);
+        objectGetter    = objectGetter(slot);
+        objectSetter    = objectSetter(slot);
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/CompiledScript.java b/nashorn/src/jdk/nashorn/internal/runtime/StoredScript.java
similarity index 77%
rename from nashorn/src/jdk/nashorn/internal/runtime/CompiledScript.java
rename to nashorn/src/jdk/nashorn/internal/runtime/StoredScript.java
index 6bb8e9a..7a76b98 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/CompiledScript.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/StoredScript.java
@@ -30,9 +30,12 @@
 import java.util.Map;
 
 /**
- * Class representing a compiled script.
+ * Class representing a persistent compiled script.
  */
-final class CompiledScript implements Serializable {
+public final class StoredScript implements Serializable {
+
+    /** Compilation id */
+    private final int compilationId;
 
     /** Main class name. */
     private final String mainClassName;
@@ -43,8 +46,8 @@
     /** Constants array. */
     private final Object[] constants;
 
-    /** The source */
-    private transient Source source;
+    /** Function initializers */
+    private final Map<Integer, FunctionInitializer> initializers;
 
     private static final long serialVersionUID = 2958227232195298340L;
 
@@ -55,11 +58,16 @@
      * @param classBytes map of class names to class bytes
      * @param constants constants array
      */
-    CompiledScript(final Source source, final String mainClassName, final Map<String, byte[]> classBytes, final Object[] constants) {
-        this.source = source;
+    public StoredScript(final int compilationId, final String mainClassName, final Map<String, byte[]> classBytes, final Map<Integer, FunctionInitializer> initializers, final Object[] constants) {
+        this.compilationId = compilationId;
         this.mainClassName = mainClassName;
         this.classBytes = classBytes;
         this.constants = constants;
+        this.initializers = initializers;
+    }
+
+    public int getCompilationId() {
+        return compilationId;
     }
 
     /**
@@ -86,20 +94,8 @@
         return constants;
     }
 
-    /**
-     * Returns the source of this cached script.
-     * @return the source
-     */
-    public Source getSource() {
-        return source;
-    }
-
-    /**
-     * Sets the source of this cached script.
-     * @param source the source
-     */
-    void setSource(final Source source) {
-        this.source = source;
+    Map<Integer, FunctionInitializer> getInitializers() {
+        return initializers;
     }
 
     @Override
@@ -111,15 +107,15 @@
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (obj == this) {
             return true;
         }
-        if (!(obj instanceof CompiledScript)) {
+        if (!(obj instanceof StoredScript)) {
             return false;
         }
 
-        final CompiledScript cs = (CompiledScript) obj;
+        final StoredScript cs = (StoredScript) obj;
         return mainClassName.equals(cs.mainClassName)
                 && classBytes.equals(cs.classBytes)
                 && Arrays.equals(constants, cs.constants);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Timing.java b/nashorn/src/jdk/nashorn/internal/runtime/Timing.java
index aa32f1c..ae61345 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Timing.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Timing.java
@@ -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
@@ -24,69 +24,67 @@
  */
 package jdk.nashorn.internal.runtime;
 
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.ArrayList;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
-
-import jdk.nashorn.internal.runtime.options.Options;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+import jdk.nashorn.internal.runtime.logging.DebugLogger;
+import jdk.nashorn.internal.runtime.logging.Loggable;
+import jdk.nashorn.internal.runtime.logging.Logger;
 
 /**
  * Simple wallclock timing framework
  */
-public final class Timing {
-    private static final boolean ENABLED = Options.getBooleanProperty("nashorn.time");
-    private static final Map<String, Long> TIMINGS;
-    private static final long START_TIME;
+@Logger(name="time")
+public final class Timing implements Loggable {
 
-    static {
-        if (ENABLED) {
-            TIMINGS    = new LinkedHashMap<>();
-            START_TIME = System.currentTimeMillis();
-            Runtime.getRuntime().addShutdownHook(new Thread() {
-                @Override
-                public void run() {
-                    final long t = System.currentTimeMillis();
-                    long knownTime = 0L;
-                    int  maxLength = 0;
+    private DebugLogger log;
+    private TimeSupplier timeSupplier;
+    private final boolean isEnabled;
+    private final long startTime;
 
-                    for (final Map.Entry<String, Long> entry : TIMINGS.entrySet()) {
-                        maxLength = Math.max(maxLength, entry.getKey().length());
-                    }
-                    maxLength++;
+    private static final String LOGGER_NAME = Timing.class.getAnnotation(Logger.class).name();
 
-                    for (final Map.Entry<String, Long> entry : TIMINGS.entrySet()) {
-                        final StringBuilder sb = new StringBuilder();
-
-                        sb.append(entry.getKey());
-                        while (sb.length() < maxLength) {
-                            sb.append(' ');
-                        }
-
-                        final long duration = entry.getValue();
-                        sb.append(duration);
-                        sb.append(' ');
-                        sb.append(" ms");
-
-                        knownTime += duration;
-
-                        System.err.println(sb.toString()); //Context err is gone by shutdown TODO
-                    }
-
-                    final long total = t - START_TIME;
-                    System.err.println("Total runtime: " + total + " ms (Non-runtime: " + knownTime + " ms [" + (int)(knownTime * 100.0 / total) + "%])");
-                }
-            });
-        } else {
-            TIMINGS = null;
-            START_TIME = 0L;
-        }
+    /**
+     * Instantiate singleton timer for ScriptEnvironment
+     * @param isEnabled true if enabled, otherwise we keep the instance around
+     *      for code brevity and "isEnabled" checks, but never instantiate anything
+     *      inside it
+     */
+    public Timing(final boolean isEnabled) {
+        this.isEnabled = isEnabled;
+        this.startTime = System.nanoTime();
     }
 
     /**
-     * Check if timing is inabled
+     * Get the log info accumulated by this Timing instance
+     * @return log info as one string
+     */
+    public String getLogInfo() {
+        assert isEnabled();
+        return timeSupplier.get();
+    }
+
+    /**
+     * Get the log info accumulated by this Timing instance
+     * @return log info as and array of strings, one per line
+     */
+    public String[] getLogInfoLines() {
+        assert isEnabled();
+        return timeSupplier.getStrings();
+    }
+
+    /**
+     * Check if timing is enabled
      * @return true if timing is enabled
      */
-    public static boolean isEnabled() {
-        return ENABLED;
+    boolean isEnabled() {
+        return isEnabled;
     }
 
     /**
@@ -94,16 +92,147 @@
      * or add to its accumulated time
      *
      * @param module   module name
-     * @param duration duration to add to accumulated time for module
+     * @param durationNano duration to add to accumulated time for module, in nanoseconds.
      */
-    public static void accumulateTime(final String module, final long duration) {
-        if (Timing.isEnabled()) {
-            Long accumulatedTime = TIMINGS.get(module);
-            if (accumulatedTime == null) {
-                accumulatedTime = 0L;
-            }
-            TIMINGS.put(module, accumulatedTime + duration);
+    public void accumulateTime(final String module, final long durationNano) {
+        if (isEnabled()) {
+            ensureInitialized(Context.getContextTrusted());
+            timeSupplier.accumulateTime(module, durationNano);
         }
     }
 
+    private DebugLogger ensureInitialized(final Context context) {
+        //lazy init, as there is not necessarily a context available when
+        //a ScriptEnvironment gets initialize
+        if (isEnabled() && log == null) {
+            log = initLogger(context);
+            if (log.isEnabled()) {
+                this.timeSupplier = new TimeSupplier();
+                Runtime.getRuntime().addShutdownHook(
+                        new Thread() {
+                            @Override
+                            public void run() {
+                                //System.err.println because the context and the output streams may be gone
+                                //when the shutdown hook executes
+                                final StringBuilder sb = new StringBuilder();
+                                for (final String str : timeSupplier.getStrings()) {
+                                    sb.append('[').
+                                        append(Timing.getLoggerName()).
+                                        append("] ").
+                                        append(str).
+                                        append('\n');
+                                }
+                                System.err.print(sb);
+                            }
+                        });
+            }
+        }
+        return log;
+    }
+
+    static String getLoggerName() {
+        return LOGGER_NAME;
+    }
+
+    @Override
+    public DebugLogger initLogger(final Context context) {
+        return context.getLogger(this.getClass());
+    }
+
+    @Override
+    public DebugLogger getLogger() {
+        return log;
+    }
+
+    /**
+     * Takes a duration in nanoseconds, and returns a string representation of it rounded to milliseconds.
+     * @param durationNano duration in nanoseconds
+     * @return the string representing the duration in milliseconds.
+     */
+    public static String toMillisPrint(final long durationNano) {
+        return Long.toString(TimeUnit.NANOSECONDS.toMillis(durationNano));
+    }
+
+    final class TimeSupplier implements Supplier<String> {
+        private final Map<String, Long> timings;
+
+        TimeSupplier() {
+            timings   = new LinkedHashMap<>();
+        }
+
+        String[] getStrings() {
+            final List<String> strs = new ArrayList<>();
+            final BufferedReader br = new BufferedReader(new StringReader(get()));
+            String line;
+            try {
+                while ((line = br.readLine()) != null) {
+                    strs.add(line);
+                }
+            } catch (final IOException e) {
+                throw new RuntimeException(e);
+            }
+            return strs.toArray(new String[strs.size()]);
+        }
+
+        @Override
+        public String get() {
+            final long t = System.nanoTime();
+
+            long knownTime = 0L;
+            int  maxKeyLength = 0;
+            int  maxValueLength = 0;
+
+            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+                maxKeyLength   = Math.max(maxKeyLength, entry.getKey().length());
+                maxValueLength = Math.max(maxValueLength, toMillisPrint(entry.getValue()).length());
+            }
+            maxKeyLength++;
+
+            final StringBuilder sb = new StringBuilder();
+            sb.append("Accumulated complation phase Timings:\n\n");
+            for (final Map.Entry<String, Long> entry : timings.entrySet()) {
+                int len;
+
+                len = sb.length();
+                sb.append(entry.getKey());
+                len = sb.length() - len;
+
+                while (len++ < maxKeyLength) {
+                    sb.append(' ');
+                }
+
+                final Long duration = entry.getValue();
+                final String strDuration = toMillisPrint(duration);
+                len = strDuration.length();
+                for (int i = 0; i < maxValueLength - len; i++) {
+                    sb.append(' ');
+                }
+
+                sb.append(strDuration).
+                    append(" ms\n");
+
+                knownTime += duration;
+            }
+
+            final long total = t - startTime;
+            sb.append('\n');
+            sb.append("Total runtime: ").
+                append(toMillisPrint(total)).
+                append(" ms (Non-runtime: ").
+                append(toMillisPrint(knownTime)).
+                append(" ms [").
+                append((int)(knownTime * 100.0 / total)).
+                append("%])");
+
+            return sb.toString();
+        }
+
+        private void accumulateTime(final String module, final long duration) {
+            Long accumulatedTime = timings.get(module);
+            if (accumulatedTime == null) {
+                accumulatedTime = 0L;
+            }
+            timings.put(module, accumulatedTime + duration);
+        }
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Undefined.java b/nashorn/src/jdk/nashorn/internal/runtime/Undefined.java
index a19c244..fc1a028 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/Undefined.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/Undefined.java
@@ -25,12 +25,11 @@
 
 package jdk.nashorn.internal.runtime;
 
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
-import java.lang.invoke.MethodType;
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
@@ -110,13 +109,13 @@
             if (desc.getNameTokenCount() < 3) {
                 return findGetIndexMethod(desc);
             }
-            throw lookupTypeError("cant.read.property.of.undefined", desc);
+            return findGetMethod(desc);
         case "setProp":
         case "setElem":
             if (desc.getNameTokenCount() < 3) {
                 return findSetIndexMethod(desc);
             }
-            throw lookupTypeError("cant.set.property.of.undefined", desc);
+            return findSetMethod(desc);
         default:
             break;
         }
@@ -128,44 +127,23 @@
         return typeError(msg, desc.getNameTokenCount() > 2 ? desc.getNameToken(2) : null);
     }
 
-    /**
-     * Find the appropriate GETINDEX method for an invoke dynamic call.
-     * @param desc The invoke dynamic callsite descriptor
-     * @param args arguments
-     * @return GuardedInvocation to be invoked at call site.
-     */
-    private static GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc, final Object... args) {
-        final MethodType callType  = desc.getMethodType();
-        final Class<?> returnClass = callType.returnType();
-        final Class<?> keyClass    = callType.parameterType(1);
+    private static final MethodHandle GET_METHOD = findOwnMH("get", Object.class, Object.class);
+    private static final MethodHandle SET_METHOD = MH.insertArguments(findOwnMH("set", void.class, Object.class, Object.class, boolean.class), 3, Boolean.TRUE);
 
-        String name = "get";
-        if (returnClass.isPrimitive()) {
-            //turn e.g. get with a double into getDouble
-            final String returnTypeName = returnClass.getName();
-            name += Character.toUpperCase(returnTypeName.charAt(0)) + returnTypeName.substring(1, returnTypeName.length());
-        }
-        MethodHandle methodHandle = findOwnMH(name, returnClass, keyClass);
-        methodHandle = MH.asType(methodHandle, methodHandle.type().changeParameterType(0, Object.class));
-
-        return new GuardedInvocation(methodHandle, UNDEFINED_GUARD);
+    private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
+        return new GuardedInvocation(MH.insertArguments(GET_METHOD, 1, desc.getNameToken(2)), UNDEFINED_GUARD).asType(desc);
     }
 
-    /**
-     * Find the appropriate SETINDEX method for an invoke dynamic call.
-     * @param desc The invoke dynamic callsite descriptor
-     * @return GuardedInvocation to be invoked at call site.
-     */
+    private static GuardedInvocation findGetIndexMethod(final CallSiteDescriptor desc) {
+        return new GuardedInvocation(GET_METHOD, UNDEFINED_GUARD).asType(desc);
+    }
+
+    private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
+        return new GuardedInvocation(MH.insertArguments(SET_METHOD, 1, desc.getNameToken(2)), UNDEFINED_GUARD).asType(desc);
+    }
+
     private static GuardedInvocation findSetIndexMethod(final CallSiteDescriptor desc) {
-        final MethodType callType   = desc.getMethodType();
-        final Class<?>   keyClass   = callType.parameterType(1);
-        final Class<?>   valueClass = callType.parameterType(2);
-
-        MethodHandle methodHandle = findOwnMH("set", void.class, keyClass, valueClass, boolean.class);
-        methodHandle = MH.asType(methodHandle, methodHandle.type().changeParameterType(0, Object.class));
-        methodHandle = MH.insertArguments(methodHandle, 3, false);
-
-        return new GuardedInvocation(methodHandle, UNDEFINED_GUARD);
+        return new GuardedInvocation(SET_METHOD, UNDEFINED_GUARD).asType(desc);
     }
 
     @Override
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java b/nashorn/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java
new file mode 100644
index 0000000..53ea7f7
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UnwarrantedOptimismException.java
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+package jdk.nashorn.internal.runtime;
+
+import java.io.NotSerializableException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import jdk.nashorn.internal.codegen.types.Type;
+
+/**
+ * This exception is thrown from an optimistic operation, e.g. an integer add,
+ * that was to optimistic for what really took place. Typically things like
+ * trying to get an array element that we want to be an int, and it was a double,
+ * and an int add that actually overflows and needs a double for the representation
+ */
+
+@SuppressWarnings("serial")
+public final class UnwarrantedOptimismException extends RuntimeException {
+    /** Denotes an invalid program point */
+    public static final int INVALID_PROGRAM_POINT = -1;
+
+    /** The value for the first ordinary program point */
+    public static final int FIRST_PROGRAM_POINT = 1;
+
+    private Object returnValue;
+    private final int    programPoint;
+    private final Type   returnType;
+
+    /**
+     * Constructor
+     * @param returnValue actual return value from the too narrow operation
+     * @param programPoint program point where unwarranted optimism was detected
+     */
+    public UnwarrantedOptimismException(final Object returnValue, final int programPoint) {
+        this(returnValue, programPoint, getReturnType(returnValue));
+    }
+
+    /**
+     * Check if a program point is valid
+     * @param programPoint the program point
+     * @return true if valid
+     */
+    public static boolean isValid(final int programPoint) {
+        assert programPoint >= INVALID_PROGRAM_POINT;
+        return programPoint != INVALID_PROGRAM_POINT;
+    }
+
+    private static Type getReturnType(final Object v) {
+        if (v instanceof Double) {
+            return Type.NUMBER;
+        } else if (v instanceof Long) {
+            return Type.LONG;
+        }
+        assert !(v instanceof Integer) : v + " is an int"; // Can't have an unwarranted optimism exception with int
+        return Type.OBJECT;
+    }
+
+    /**
+     * Constructor with explicit return value type.
+     * @param returnValue actual return value from the too narrow operation
+     * @param programPoint program point where unwarranted optimism was detected
+     * @param returnType type of the returned value. Used to disambiguate the return type. E.g. an {@code ObjectArrayData}
+     * might return a {@link Double} for a particular element getter, but still throw this exception even if the call
+     * site can accept a double, since the array's type is actually {@code Type#OBJECT}. In this case, it must
+     * explicitly use this constructor to indicate its values are to be considered {@code Type#OBJECT} and not
+     * {@code Type#NUMBER}.
+     */
+    public UnwarrantedOptimismException(final Object returnValue, final int programPoint, final Type returnType) {
+        super("", null, false, Context.DEBUG);
+        assert returnType != Type.OBJECT || returnValue == null || !Type.typeFor(returnValue.getClass()).isNumeric();
+        assert returnType != Type.INT;
+        this.returnValue  = returnValue;
+        this.programPoint = programPoint;
+        this.returnType   = returnType;
+    }
+
+    /**
+     * Get the return value. This is a destructive readout, after the method is invoked the return value is null'd out.
+     * @return return value
+     */
+    public Object getReturnValueDestructive() {
+        final Object retval = returnValue;
+        returnValue = null;
+        return retval;
+    }
+
+    Object getReturnValueNonDestructive() {
+        return returnValue;
+    }
+
+    /**
+     * Get the return type
+     * @return return type
+     */
+    public Type getReturnType() {
+        return returnType;
+    }
+
+    /**
+     * Does this exception refer to an invalid program point? This might be OK if
+     * we throw it, e.g. from a parameter guard
+     * @return true if invalid program point specified
+     */
+    public boolean hasInvalidProgramPoint() {
+        return programPoint == INVALID_PROGRAM_POINT;
+    }
+
+    /**
+     * Get the program point
+     * @return the program point
+     */
+    public int getProgramPoint() {
+        return programPoint;
+    }
+
+    /**
+     * Check if we ended up with a primitive return value (even though it may be
+     * too wide for what we tried to do, e.g. double instead of int)
+     * @return true if return value is primitive
+     */
+    public boolean hasPrimitiveReturnValue() {
+        return returnValue instanceof Number || returnValue instanceof Boolean;
+    }
+
+    @Override
+    public String getMessage() {
+        return "UNWARRANTED OPTIMISM: [returnValue=" +
+            returnValue +
+            " (class=" +
+            (returnValue == null ? "null" : returnValue.getClass().getSimpleName()) +
+            (hasInvalidProgramPoint() ?
+                " <invalid program point>" :
+                (" @ program point #" + programPoint)) +
+            ")]";
+    }
+
+
+    private void writeObject(final ObjectOutputStream out) throws NotSerializableException {
+        throw new NotSerializableException(getClass().getName());
+    }
+
+    private void readObject(final ObjectInputStream in) throws NotSerializableException {
+        throw new NotSerializableException(getClass().getName());
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
index 5b21f6e..d7b52c1 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/UserAccessorProperty.java
@@ -25,49 +25,55 @@
 
 package jdk.nashorn.internal.runtime;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+import static jdk.nashorn.internal.runtime.JSType.CONVERT_OBJECT_OPTIMISTIC;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
+
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.util.concurrent.Callable;
-
 import jdk.nashorn.internal.codegen.CompilerConstants;
 import jdk.nashorn.internal.lookup.Lookup;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
 
-import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
-import jdk.nashorn.internal.objects.Global;
-import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
-import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
-
 /**
  * Property with user defined getters/setters. Actual getter and setter
  * functions are stored in underlying ScriptObject. Only the 'slot' info is
  * stored in the property.
- *
- * The slots here denote either ScriptObject embed field number or spill
- * array index. For spill array index, we use slot value of
- * (index + ScriptObject.embedSize). See also ScriptObject.getEmbedOrSpill
- * method. Negative slot value means that the corresponding getter or setter
- * is null. Note that always two slots are allocated in ScriptObject - but
- * negative (less by 1) slot number is stored for null getter or setter.
- * This is done so that when the property is redefined with a different
- * getter and setter (say, both non-null), we'll have spill slots to store
- * those. When a slot is negative, (-slot - 1) is the embed/spill index.
  */
-public final class UserAccessorProperty extends Property {
+public final class UserAccessorProperty extends SpillProperty {
 
-    /** User defined getter function slot. */
-    private final int getterSlot;
+    private static final long serialVersionUID = -5928687246526840321L;
 
-    /** User defined setter function slot. */
-    private final int setterSlot;
+    static class Accessors {
+        Object getter;
+        Object setter;
+
+        Accessors(final Object getter, final Object setter) {
+            set(getter, setter);
+        }
+
+        final void set(final Object getter, final Object setter) {
+            this.getter = getter;
+            this.setter = setter;
+        }
+
+        @Override
+        public String toString() {
+            return "[getter=" + getter + " setter=" + setter + ']';
+        }
+    }
 
     /** Getter method handle */
     private final static CompilerConstants.Call USER_ACCESSOR_GETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
-            "userAccessorGetter", Object.class, ScriptObject.class, int.class, Object.class);
+            "userAccessorGetter", Object.class, Accessors.class, Object.class);
 
     /** Setter method handle */
     private final static CompilerConstants.Call USER_ACCESSOR_SETTER = staticCall(MethodHandles.lookup(), UserAccessorProperty.class,
-            "userAccessorSetter", void.class, ScriptObject.class, int.class, String.class, Object.class, Object.class);
+            "userAccessorSetter", void.class, Accessors.class, String.class, Object.class, Object.class);
 
     /** Dynamic invoker for getter */
     private static final Object INVOKE_UA_GETTER = new Object();
@@ -86,6 +92,7 @@
 
     /** Dynamic invoker for setter */
     private static Object INVOKE_UA_SETTER = new Object();
+
     private static MethodHandle getINVOKE_UA_SETTER() {
         return Context.getGlobal().getDynamicInvoker(INVOKE_UA_SETTER,
                 new Callable<MethodHandle>() {
@@ -100,101 +107,155 @@
     /**
      * Constructor
      *
-     * @param key        property key
-     * @param flags      property flags
-     * @param getterSlot getter slot, starting at first embed
-     * @param setterSlot setter slot, starting at first embed
+     * @param key   property key
+     * @param flags property flags
+     * @param slot  spill slot
      */
-    UserAccessorProperty(final String key, final int flags, final int getterSlot, final int setterSlot) {
-        super(key, flags, -1);
-        this.getterSlot = getterSlot;
-        this.setterSlot = setterSlot;
+    UserAccessorProperty(final String key, final int flags, final int slot) {
+        super(key, flags, slot);
     }
 
     private UserAccessorProperty(final UserAccessorProperty property) {
         super(property);
-        this.getterSlot = property.getterSlot;
-        this.setterSlot = property.setterSlot;
     }
 
-    /**
-     * Return getter spill slot for this UserAccessorProperty.
-     * @return getter slot
-     */
-    public int getGetterSlot() {
-        return getterSlot;
-    }
-
-    /**
-     * Return setter spill slot for this UserAccessorProperty.
-     * @return setter slot
-     */
-    public int getSetterSlot() {
-        return setterSlot;
+    private UserAccessorProperty(final UserAccessorProperty property, final Class<?> newType) {
+        super(property, newType);
     }
 
     @Override
-    protected Property copy() {
+    public Property copy() {
         return new UserAccessorProperty(this);
     }
 
     @Override
-    public boolean equals(final Object other) {
-        if (!super.equals(other)) {
-            return false;
+    public Property copy(final Class<?> newType) {
+        return new UserAccessorProperty(this, newType);
+    }
+
+    void setAccessors(final ScriptObject sobj, final PropertyMap map, final Accessors gs) {
+        try {
+            //invoke the getter and find out
+            super.getSetter(Object.class, map).invokeExact((Object)sobj, (Object)gs);
+        } catch (final Error | RuntimeException t) {
+            throw t;
+        } catch (final Throwable t) {
+            throw new RuntimeException(t);
         }
+    }
 
-        final UserAccessorProperty uc = (UserAccessorProperty) other;
-        return getterSlot == uc.getterSlot && setterSlot == uc.setterSlot;
+    //pick the getter setter out of the correct spill slot in sobj
+    Accessors getAccessors(final ScriptObject sobj) {
+        try {
+            //invoke the super getter with this spill slot
+            //get the getter setter from the correct spill slot
+            final Object gs = super.getGetter(Object.class).invokeExact((Object)sobj);
+            return (Accessors)gs;
+        } catch (final Error | RuntimeException t) {
+            throw t;
+        } catch (final Throwable t) {
+            throw new RuntimeException(t);
+        }
     }
 
     @Override
-    public int hashCode() {
-        return super.hashCode() ^ getterSlot ^ setterSlot;
-    }
-
-    /*
-     * Accessors.
-     */
-    @Override
-    public int getSpillCount() {
-        return 2;
+    public Class<?> getCurrentType() {
+        return Object.class;
     }
 
     @Override
-    public boolean hasGetterFunction(final ScriptObject obj) {
-        return obj.getSpill(getterSlot) != null;
+    public boolean hasGetterFunction(final ScriptObject sobj) {
+        return getAccessors(sobj).getter != null;
     }
 
     @Override
-    public boolean hasSetterFunction(final ScriptObject obj) {
-        return obj.getSpill(setterSlot) != null;
+    public boolean hasSetterFunction(final ScriptObject sobj) {
+        return getAccessors(sobj).setter != null;
+    }
+
+    @Override
+    public int getIntValue(final ScriptObject self, final ScriptObject owner) {
+        return (int)getObjectValue(self, owner);
+    }
+
+    @Override
+    public long getLongValue(final ScriptObject self, final ScriptObject owner) {
+        return (long)getObjectValue(self, owner);
+    }
+
+    @Override
+    public double getDoubleValue(final ScriptObject self, final ScriptObject owner) {
+        return (double)getObjectValue(self, owner);
     }
 
     @Override
     public Object getObjectValue(final ScriptObject self, final ScriptObject owner) {
-        return userAccessorGetter(owner, getGetterSlot(), self);
+        return userAccessorGetter(getAccessors((owner != null) ? owner : self), self);
     }
 
     @Override
-    public void setObjectValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
-        userAccessorSetter(owner, getSetterSlot(), strict ? getKey() : null, self, value);
+    public void setValue(final ScriptObject self, final ScriptObject owner, final int value, final boolean strict) {
+        setValue(self, owner, (Object) value, strict);
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final long value, final boolean strict) {
+        setValue(self, owner, (Object) value, strict);
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final double value, final boolean strict) {
+        setValue(self, owner, (Object) value, strict);
+    }
+
+    @Override
+    public void setValue(final ScriptObject self, final ScriptObject owner, final Object value, final boolean strict) {
+        userAccessorSetter(getAccessors((owner != null) ? owner : self), strict ? getKey() : null, self, value);
     }
 
     @Override
     public MethodHandle getGetter(final Class<?> type) {
+        //this returns a getter on the format (Accessors, Object receiver)
         return Lookup.filterReturnType(USER_ACCESSOR_GETTER.methodHandle(), type);
     }
 
     @Override
+    public MethodHandle getOptimisticGetter(final Class<?> type, final int programPoint) {
+        //fortype is always object, but in the optimistic world we have to throw
+        //unwarranted optimism exception for narrower types. We can improve this
+        //by checking for boxed types and unboxing them, but it is doubtful that
+        //this gives us any performance, as UserAccessorProperties are typically not
+        //primitives. Are there? TODO: investigate later. For now we just throw an
+        //exception for narrower types than object
+
+        if (type.isPrimitive()) {
+            final MethodHandle getter = getGetter(Object.class);
+            final MethodHandle mh =
+                    MH.asType(
+                            MH.filterReturnValue(
+                                    getter,
+                                    MH.insertArguments(
+                                            CONVERT_OBJECT_OPTIMISTIC.get(getAccessorTypeIndex(type)),
+                                            1,
+                                            programPoint)),
+                                    getter.type().changeReturnType(type));
+
+            return mh;
+        }
+
+        assert type == Object.class;
+        return getGetter(type);
+    }
+
+    @Override
     void initMethodHandles(final Class<?> structure) {
         throw new UnsupportedOperationException();
     }
 
     @Override
-    public ScriptFunction getGetterFunction(final ScriptObject obj) {
-        final Object value = obj.getSpill(getterSlot);
-        return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
+    public ScriptFunction getGetterFunction(final ScriptObject sobj) {
+        final Object value = getAccessors(sobj).getter;
+        return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
     }
 
     @Override
@@ -203,25 +264,23 @@
     }
 
     @Override
-    public ScriptFunction getSetterFunction(final ScriptObject obj) {
-        final Object value = obj.getSpill(setterSlot);
-        return (value instanceof ScriptFunction) ? (ScriptFunction) value : null;
+    public ScriptFunction getSetterFunction(final ScriptObject sobj) {
+        final Object value = getAccessors(sobj).setter;
+        return (value instanceof ScriptFunction) ? (ScriptFunction)value : null;
     }
 
     // User defined getter and setter are always called by "dyn:call". Note that the user
     // getter/setter may be inherited. If so, proto is bound during lookup. In either
     // inherited or self case, slot is also bound during lookup. Actual ScriptFunction
     // to be called is retrieved everytime and applied.
-    static Object userAccessorGetter(final ScriptObject proto, final int slot, final Object self) {
-        final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
-        final Object       func      = container.getSpill(slot);
-
+    static Object userAccessorGetter(final Accessors gs, final Object self) {
+        final Object func = gs.getter;
         if (func instanceof ScriptFunction) {
             try {
                 return getINVOKE_UA_GETTER().invokeExact(func, self);
-            } catch(final Error|RuntimeException t) {
+            } catch (final Error | RuntimeException t) {
                 throw t;
-            } catch(final Throwable t) {
+            } catch (final Throwable t) {
                 throw new RuntimeException(t);
             }
         }
@@ -229,19 +288,17 @@
         return UNDEFINED;
     }
 
-    static void userAccessorSetter(final ScriptObject proto, final int slot, final String name, final Object self, final Object value) {
-        final ScriptObject container = (proto != null) ? proto : (ScriptObject)self;
-        final Object       func      = container.getSpill(slot);
-
+    static void userAccessorSetter(final Accessors gs, final String name, final Object self, final Object value) {
+        final Object func = gs.setter;
         if (func instanceof ScriptFunction) {
             try {
                 getINVOKE_UA_SETTER().invokeExact(func, self, value);
-            } catch(final Error|RuntimeException t) {
+            } catch (final Error | RuntimeException t) {
                 throw t;
-            } catch(final Throwable t) {
+            } catch (final Throwable t) {
                 throw new RuntimeException(t);
             }
-        }  else if (name != null) {
+        } else if (name != null) {
             throw typeError("property.has.no.setter", name, ScriptRuntime.safeToString(self));
         }
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
index dc48d72..723b510 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java
@@ -35,6 +35,8 @@
 import jdk.internal.dynalink.linker.GuardedInvocation;
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.api.scripting.AbstractJSObject;
+import jdk.nashorn.api.scripting.ScriptObjectMirror;
 import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
 import jdk.nashorn.internal.runtime.linker.NashornGuards;
 
@@ -64,7 +66,6 @@
         this.expression = expression;
     }
 
-
     /**
      * Delete a property based on a key.
      * @param key Any valid JavaScript value.
@@ -98,11 +99,11 @@
         final NashornCallSiteDescriptor ndesc = (NashornCallSiteDescriptor)desc;
         FindProperty find = null;
         GuardedInvocation link = null;
-        ScriptObject self = null;
+        ScriptObject self;
 
         final boolean isNamedOperation;
         final String name;
-        if(desc.getNameTokenCount() > 2) {
+        if (desc.getNameTokenCount() > 2) {
             isNamedOperation = true;
             name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
         } else {
@@ -117,7 +118,6 @@
 
         if (find != null) {
             link = self.lookup(desc, request);
-
             if (link != null) {
                 return fixExpressionCallSite(ndesc, link);
             }
@@ -242,35 +242,65 @@
     private static GuardedInvocation fixExpressionCallSite(final NashornCallSiteDescriptor desc, final GuardedInvocation link) {
         // If it's not a getMethod, just add an expression filter that converts WithObject in "this" position to its
         // expression.
-        if(!"getMethod".equals(desc.getFirstOperator())) {
+        if (!"getMethod".equals(desc.getFirstOperator())) {
             return fixReceiverType(link, WITHEXPRESSIONFILTER).filterArguments(0, WITHEXPRESSIONFILTER);
         }
 
-        final MethodHandle linkInvocation = link.getInvocation();
-        final MethodType linkType = linkInvocation.type();
-        final boolean linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
+        final MethodHandle linkInvocation      = link.getInvocation();
+        final MethodType   linkType            = linkInvocation.type();
+        final boolean      linkReturnsFunction = ScriptFunction.class.isAssignableFrom(linkType.returnType());
+
         return link.replaceMethods(
                 // Make sure getMethod will bind the script functions it receives to WithObject.expression
-                MH.foldArguments(linkReturnsFunction ? BIND_TO_EXPRESSION_FN : BIND_TO_EXPRESSION_OBJ,
-                        filter(linkInvocation.asType(linkType.changeReturnType(
-                                linkReturnsFunction ? ScriptFunction.class : Object.class)), WITHEXPRESSIONFILTER)),
-                // No clever things for the guard -- it is still identically filtered.
-                filterGuard(link, WITHEXPRESSIONFILTER));
+                MH.foldArguments(
+                        linkReturnsFunction ?
+                                BIND_TO_EXPRESSION_FN :
+                                BIND_TO_EXPRESSION_OBJ,
+                        filterReceiver(
+                                linkInvocation.asType(
+                                        linkType.changeReturnType(
+                                                linkReturnsFunction ?
+                                                        ScriptFunction.class :
+                                                        Object.class).
+                                                            changeParameterType(
+                                                                    0,
+                                                                    Object.class)),
+                                        WITHEXPRESSIONFILTER)),
+                         filterGuardReceiver(link, WITHEXPRESSIONFILTER));
+     // No clever things for the guard -- it is still identically filtered.
+
     }
 
     private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name, final ScriptObject owner) {
-        final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER);
-        return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER),
-                NashornGuards.combineGuards(expressionGuard(name, owner), filterGuard(newLink, WITHSCOPEFILTER)));
+        final GuardedInvocation newLink             = fixReceiverType(link, WITHSCOPEFILTER);
+        final MethodHandle      expressionGuard     = expressionGuard(name, owner);
+        final MethodHandle      filterGuardReceiver = filterGuardReceiver(newLink, WITHSCOPEFILTER);
+        return link.replaceMethods(
+                filterReceiver(
+                        newLink.getInvocation(),
+                        WITHSCOPEFILTER),
+                NashornGuards.combineGuards(
+                        expressionGuard,
+                        filterGuardReceiver));
     }
 
-    private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) {
+    private static MethodHandle filterGuardReceiver(final GuardedInvocation link, final MethodHandle receiverFilter) {
         final MethodHandle test = link.getGuard();
-        return test == null ? null : filter(test, filter);
+        if (test == null) {
+            return null;
+        }
+
+        final Class<?> receiverType = test.type().parameterType(0);
+        final MethodHandle filter = MH.asType(receiverFilter,
+                receiverFilter.type().changeParameterType(0, receiverType).
+                changeReturnType(receiverType));
+
+        return filterReceiver(test, filter);
     }
 
-    private static MethodHandle filter(final MethodHandle mh, final MethodHandle filter) {
-        return MH.filterArguments(mh, 0, filter.asType(filter.type().changeReturnType(mh.type().parameterType(0))));
+    private static MethodHandle filterReceiver(final MethodHandle mh, final MethodHandle receiverFilter) {
+        //With expression filter == receiverFilter, i.e. receiver is cast to withobject and its expression returned
+        return MH.filterArguments(mh, 0, receiverFilter.asType(receiverFilter.type().changeReturnType(mh.type().parameterType(0))));
     }
 
     /**
@@ -284,11 +314,27 @@
 
     @SuppressWarnings("unused")
     private static Object bindToExpression(final Object fn, final Object receiver) {
-        return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn;
+        if (fn instanceof ScriptFunction) {
+            return bindToExpression((ScriptFunction) fn, receiver);
+        } else if (fn instanceof ScriptObjectMirror) {
+            final ScriptObjectMirror mirror = (ScriptObjectMirror)fn;
+            if (mirror.isFunction()) {
+                // We need to make sure correct 'this' is used for calls with Ident call
+                // expressions. We do so here using an AbstractJSObject instance.
+                return new AbstractJSObject() {
+                    @Override
+                    public Object call(final Object thiz, final Object... args) {
+                        return mirror.call(withFilterExpression(receiver), args);
+                    }
+                };
+            }
+        }
+
+        return fn;
     }
 
     private static Object bindToExpression(final ScriptFunction fn, final Object receiver) {
-        return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]);
+        return fn.makeBoundFunction(withFilterExpression(receiver), ScriptRuntime.EMPTY_ARRAY);
     }
 
     private MethodHandle expressionGuard(final String name, final ScriptObject owner) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
index 58f3296..ce678d1 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java
@@ -25,19 +25,27 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+
 import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.nio.ByteBuffer;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.codegen.CompilerConstants;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.PropertyDescriptor;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
 /**
  * ArrayData - abstraction for wrapping array elements
  */
 public abstract class ArrayData {
-
     /** Minimum chunk size for underlying arrays */
-    protected static final int CHUNK_SIZE = 16;
+    protected static final int CHUNK_SIZE = 32;
 
     /** Mask for getting a chunk */
     protected static final int CHUNK_MASK = CHUNK_SIZE - 1;
@@ -53,6 +61,12 @@
     private long length;
 
     /**
+     * Method handle to throw an {@link UnwarrantedOptimismException} when getting an element
+     * of the wrong type
+     */
+    protected static final CompilerConstants.Call THROW_UNWARRANTED = staticCall(MethodHandles.lookup(), ArrayData.class, "throwUnwarranted", void.class, ArrayData.class, int.class, int.class);
+
+    /**
      * Constructor
      * @param length Virtual length of the array.
      */
@@ -69,6 +83,37 @@
     }
 
     /**
+     * Unwarranted thrower
+     *
+     * @param data         array data
+     * @param programPoint program point
+     * @param index        array index
+     */
+    protected static void throwUnwarranted(final ArrayData data, final int programPoint, final int index) {
+        throw new UnwarrantedOptimismException(data.getObject(index), programPoint);
+    }
+
+    private static int alignUp(final int size) {
+        return size + CHUNK_SIZE - 1 & ~(CHUNK_SIZE - 1);
+    }
+
+    /**
+     * Generic invalidation hook for script object to have call sites to this array indexing
+     * relinked, e.g. when a native array is marked as non extensible
+     */
+    public void invalidateGetters() {
+        //subclass responsibility
+    }
+
+    /**
+     * Generic invalidation hook for script object to have call sites to this array indexing
+     * relinked, e.g. when a native array is marked as non extensible
+     */
+    public void invalidateSetters() {
+        //subclass responsibility
+    }
+
+    /**
      * Factory method for unspecified array with given length - start as int array data
      *
      * @param length the initial length
@@ -151,7 +196,7 @@
      * @return the ArrayData
      */
     public static ArrayData allocate(final ByteBuffer buf) {
-        return new ByteBufferArrayData((ByteBuffer)buf);
+        return new ByteBufferArrayData(buf);
     }
 
     /**
@@ -336,6 +381,27 @@
     public abstract int getInt(int index);
 
     /**
+     * Returns the optimistic type of this array data. Basically, when an array data object needs to throw an
+     * {@link UnwarrantedOptimismException}, this type is used as the actual type of the return value.
+     * @return the optimistic type of this array data.
+     */
+    public Type getOptimisticType() {
+        return Type.OBJECT;
+    }
+
+    /**
+     * Get optimistic int - default is that it's impossible. Overridden
+     * by arrays that actually represents ints
+     *
+     * @param index        the index
+     * @param programPoint program point
+     * @return the value
+     */
+    public int getIntOptimistic(final int index, final int programPoint) {
+        throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
+    }
+
+    /**
      * Get a long value from a given index
      *
      * @param index the index
@@ -344,6 +410,18 @@
     public abstract long getLong(int index);
 
     /**
+     * Get optimistic long - default is that it's impossible. Overridden
+     * by arrays that actually represents longs or narrower
+     *
+     * @param index        the index
+     * @param programPoint program point
+     * @return the value
+     */
+    public long getLongOptimistic(final int index, final int programPoint) {
+        throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
+    }
+
+    /**
      * Get a double value from a given index
      *
      * @param index the index
@@ -352,6 +430,18 @@
     public abstract double getDouble(int index);
 
     /**
+     * Get optimistic double - default is that it's impossible. Overridden
+     * by arrays that actually represents doubles or narrower
+     *
+     * @param index        the index
+     * @param programPoint program point
+     * @return the value
+     */
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        throw new UnwarrantedOptimismException(getObject(index), programPoint, getOptimisticType());
+    }
+
+    /**
      * Get an Object value from a given index
      *
      * @param index the index
@@ -456,6 +546,50 @@
     }
 
     /**
+     * Push an array of items to the end of the array
+     *
+     * @param strict are we in strict mode
+     * @param item   the item
+     * @return new array data (or same)
+     */
+    public ArrayData push(final boolean strict, final Object item) {
+        return push(strict, new Object[] { item });
+    }
+
+    /**
+     * Push an array of items to the end of the array
+     *
+     * @param strict are we in strict mode
+     * @param item   the item
+     * @return new array data (or same)
+     */
+    public ArrayData push(final boolean strict, final double item) {
+        return push(strict, item);
+    }
+
+    /**
+     * Push an array of items to the end of the array
+     *
+     * @param strict are we in strict mode
+     * @param item   the item
+     * @return new array data (or same)
+     */
+    public ArrayData push(final boolean strict, final long item) {
+        return push(strict, item);
+    }
+
+    /**
+     * Push an array of items to the end of the array
+     *
+     * @param strict are we in strict mode
+     * @param item   the item
+     * @return new array data (or same)
+     */
+    public ArrayData push(final boolean strict, final int item) {
+        return push(strict, item);
+    }
+
+    /**
      * Pop an element from the end of the array
      *
      * @return the popped element
@@ -482,12 +616,12 @@
      * @param removed number of removed elements
      * @param added number of added elements
      * @throws UnsupportedOperationException if fast splice is not supported for the class or arguments.
+     * @return new arraydata, but this never happens because we always throw an exception
      */
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
         throw new UnsupportedOperationException();
     }
 
-
     static Class<?> widestType(final Object... items) {
         assert items.length > 0;
 
@@ -520,16 +654,7 @@
      * @return next size to allocate for internal array
      */
     protected static int nextSize(final int size) {
-        if (size == 0) {
-            return CHUNK_SIZE;
-        }
-
-        int i = size;
-        while ((i & CHUNK_MASK) != 0) {
-            i++;
-        }
-
-        return i << 1;
+        return alignUp(size + 1) * 2;
     }
 
     /**
@@ -553,4 +678,42 @@
             throw new RuntimeException(t);
         }
     }
+
+    /**
+     * Find a fast property getter if one exists
+     *
+     * @param clazz    array data class
+     * @param desc     callsite descriptor
+     * @param request  link request
+     * @param operator operator
+     * @return fast property getter if one is found
+     */
+    public GuardedInvocation findFastGetMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+        return null;
+    }
+
+    /**
+     * Find a fast element getter if one exists
+     *
+     * @param clazz   array data class
+     * @param desc    callsite descriptor
+     * @param request link request
+     * @return fast index getter if one is found
+     */
+    public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+        return null;
+    }
+
+    /**
+     * Find a fast element setter if one exists
+     *
+     * @param clazz   array data class
+     * @param desc    callsite descriptor
+     * @param request link request
+     * @return fast index getter if one is found
+     */
+    public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+        return null;
+    }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
index 7a20f78..be41673 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayFilter.java
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.Undefined;
 import jdk.nashorn.internal.runtime.linker.Bootstrap;
@@ -141,21 +142,41 @@
     }
 
     @Override
+    public Type getOptimisticType() {
+        return underlying.getOptimisticType();
+    }
+
+    @Override
     public int getInt(final int index) {
         return underlying.getInt(index);
     }
 
     @Override
+    public int getIntOptimistic(final int index, final int programPoint) {
+        return underlying.getIntOptimistic(index, programPoint);
+    }
+
+    @Override
     public long getLong(final int index) {
         return underlying.getLong(index);
     }
 
     @Override
+    public long getLongOptimistic(final int index, final int programPoint) {
+        return underlying.getLongOptimistic(index, programPoint);
+    }
+
+    @Override
     public double getDouble(final int index) {
         return underlying.getDouble(index);
     }
 
     @Override
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        return underlying.getDoubleOptimistic(index, programPoint);
+    }
+
+    @Override
     public Object getObject(final int index) {
         return underlying.getObject(index);
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
index 33c8679..85f1b43 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ByteBufferArrayData.java
@@ -82,17 +82,17 @@
     }
 
     @Override
-    public void shiftLeft(int by) {
+    public void shiftLeft(final int by) {
         throw unsupported("shiftLeft");
     }
 
     @Override
-    public ArrayData shiftRight(int by) {
+    public ArrayData shiftRight(final int by) {
         throw unsupported("shiftRight");
     }
 
     @Override
-    public ArrayData ensure(long safeIndex) {
+    public ArrayData ensure(final long safeIndex) {
         if (safeIndex < buf.capacity()) {
             return this;
         }
@@ -101,12 +101,12 @@
     }
 
     @Override
-    public ArrayData shrink(long newLength) {
+    public ArrayData shrink(final long newLength) {
         throw unsupported("shrink");
     }
 
     @Override
-    public ArrayData set(int index, Object value, boolean strict) {
+    public ArrayData set(final int index, final Object value, final boolean strict) {
         if (value instanceof Number) {
             buf.put(index, ((Number)value).byteValue());
             return this;
@@ -116,45 +116,45 @@
     }
 
     @Override
-    public ArrayData set(int index, int value, boolean strict) {
+    public ArrayData set(final int index, final int value, final boolean strict) {
         buf.put(index, (byte)value);
         return this;
     }
 
     @Override
-    public ArrayData set(int index, long value, boolean strict) {
+    public ArrayData set(final int index, final long value, final boolean strict) {
         buf.put(index, (byte)value);
         return this;
     }
 
     @Override
-    public ArrayData set(int index, double value, boolean strict) {
+    public ArrayData set(final int index, final double value, final boolean strict) {
         buf.put(index, (byte)value);
         return this;
     }
 
     @Override
-    public int getInt(int index) {
+    public int getInt(final int index) {
         return 0x0ff & buf.get(index);
     }
 
     @Override
-    public long getLong(int index) {
+    public long getLong(final int index) {
         return 0x0ff & buf.get(index);
     }
 
     @Override
-    public double getDouble(int index) {
+    public double getDouble(final int index) {
         return 0x0ff & buf.get(index);
     }
 
     @Override
-    public Object getObject(int index) {
-        return (int)(0x0ff & buf.get(index));
+    public Object getObject(final int index) {
+        return 0x0ff & buf.get(index);
     }
 
     @Override
-    public boolean has(int index) {
+    public boolean has(final int index) {
         return index > -1 && index < buf.capacity();
     }
 
@@ -169,12 +169,12 @@
     }
 
     @Override
-    public ArrayData delete(int index) {
+    public ArrayData delete(final int index) {
         throw unsupported("delete");
     }
 
     @Override
-    public ArrayData delete(long fromIndex, long toIndex) {
+    public ArrayData delete(final long fromIndex, final long toIndex) {
         throw unsupported("delete");
     }
 
@@ -189,7 +189,7 @@
     }
 
     @Override
-    public ArrayData slice(long from, long to) {
+    public ArrayData slice(final long from, final long to) {
         throw unsupported("slice");
     }
 
@@ -198,7 +198,7 @@
         throw unsupported("convert");
     }
 
-    private UnsupportedOperationException unsupported(final String method) {
+    private static UnsupportedOperationException unsupported(final String method) {
         return new UnsupportedOperationException(method);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
new file mode 100644
index 0000000..f6e4d38
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ContinuousArrayData.java
@@ -0,0 +1,272 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+import static jdk.nashorn.internal.runtime.JSType.getAccessorTypeIndex;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
+import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.invoke.SwitchPoint;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor;
+import jdk.nashorn.internal.runtime.logging.Logger;
+
+/**
+ * Interface implemented by all arrays that are directly accessible as underlying
+ * native arrays
+ */
+@Logger(name="arrays")
+public abstract class ContinuousArrayData extends ArrayData {
+
+    private SwitchPoint sp;
+
+    /**
+     * Constructor
+     * @param length length (elementLength)
+     */
+    protected ContinuousArrayData(final long length) {
+        super(length);
+    }
+
+    private SwitchPoint ensureSwitchPointExists() {
+        if (sp == null){
+            sp = new SwitchPoint();
+        }
+        return sp;
+    }
+
+    @Override
+    public void invalidateSetters() {
+        SwitchPoint.invalidateAll(new SwitchPoint[] { ensureSwitchPointExists() });
+    }
+
+    /**
+     * Check if we can put one more element at the end of this continous
+     * array without reallocating, or if we are overwriting an already
+     * allocated element
+     *
+     * @param index
+     * @return true if we don't need to do any array reallocation to fit an element at index
+     */
+    public final boolean hasRoomFor(final int index) {
+        return has(index) || (index == length() && ensure(index) == this);
+    }
+
+    /**
+     * Return element getter for a certain type at a certain program point
+     * @param returnType   return type
+     * @param programPoint program point
+     * @return element getter or null if not supported (used to implement slow linkage instead
+     *   as fast isn't possible)
+     */
+    public abstract MethodHandle getElementGetter(final Class<?> returnType, final int programPoint);
+
+    /**
+     * Return element getter for a certain type at a certain program point
+     * @param elementType element type
+     * @return element setter or null if not supported (used to implement slow linkage instead
+     *   as fast isn't possible)
+     */
+    public abstract MethodHandle getElementSetter(final Class<?> elementType);
+
+    /**
+     * Version of has that throws a class cast exception if element does not exist
+     * used for relinking
+     *
+     * @param index index to check - currently only int indexes
+     * @return index
+     */
+    protected int throwHas(final int index) {
+        if (!has(index)) {
+            throw new ClassCastException();
+        }
+        return index;
+    }
+
+    /**
+     * Look up a continuous array element getter
+     * @param get          getter, sometimes combined with a has check that throws CCE on failure for relink
+     * @param returnType   return type
+     * @param programPoint program point
+     * @return array getter
+     */
+    protected final MethodHandle getContinuousElementGetter(final MethodHandle get, final Class<?> returnType, final int programPoint) {
+        return getContinuousElementGetter(getClass(), get, returnType, programPoint);
+    }
+
+    /**
+     * Look up a continuous array element setter
+     * @param set          setter, sometimes combined with a has check that throws CCE on failure for relink
+     * @param returnType   return type
+     * @return array setter
+     */
+    protected final MethodHandle getContinuousElementSetter(final MethodHandle set, final Class<?> returnType) {
+        return getContinuousElementSetter(getClass(), set, returnType);
+    }
+
+    /**
+     * Return element getter for a {@link ContinuousArrayData}
+     * @param clazz        clazz for exact type guard
+     * @param getHas       has getter
+     * @param returnType   return type
+     * @param programPoint program point
+     * @return method handle for element setter
+     */
+    protected MethodHandle getContinuousElementGetter(final Class<? extends ContinuousArrayData> clazz, final MethodHandle getHas, final Class<?> returnType, final int programPoint) {
+        final boolean isOptimistic = isValid(programPoint);
+        final int     fti          = getAccessorTypeIndex(getHas.type().returnType());
+        final int     ti           = getAccessorTypeIndex(returnType);
+        MethodHandle  mh           = getHas;
+
+        if (isOptimistic) {
+            if (ti < fti) {
+                mh = MH.insertArguments(ArrayData.THROW_UNWARRANTED.methodHandle(), 1, programPoint);
+            }
+        }
+        mh = MH.asType(mh, mh.type().changeReturnType(returnType).changeParameterType(0, clazz));
+
+        if (!isOptimistic) {
+            //for example a & array[17];
+            return Lookup.filterReturnType(mh, returnType);
+        }
+        return mh;
+    }
+
+    /**
+     * Return element setter for a {@link ContinuousArrayData}
+     * @param clazz        clazz for exact type guard
+     * @param setHas       set has guard
+     * @param elementType  element type
+     * @return method handle for element setter
+     */
+    protected MethodHandle getContinuousElementSetter(final Class<? extends ContinuousArrayData> clazz, final MethodHandle setHas, final Class<?> elementType) {
+        return MH.asType(setHas, setHas.type().changeParameterType(2, elementType).changeParameterType(0, clazz));
+    }
+
+    @Override
+    public GuardedInvocation findFastGetMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request, final String operator) {
+        return null;
+    }
+
+    /** Fast access guard - it is impractical for JIT performance reasons to use only CCE asType as guard :-(, also we need
+      the null case explicitly, which is the one that CCE doesn't handle */
+    protected static final MethodHandle FAST_ACCESS_GUARD =
+            MH.dropArguments(
+                    staticCall(
+                            MethodHandles.lookup(),
+                            ContinuousArrayData.class,
+                            "guard",
+                            boolean.class,
+                            Class.class,
+                            ScriptObject.class).methodHandle(),
+                    2,
+                    int.class);
+
+    @SuppressWarnings("unused")
+    private static final boolean guard(final Class<? extends ContinuousArrayData> clazz, final ScriptObject sobj) {
+        if (sobj != null && sobj.getArray().getClass() == clazz) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Return a fast linked array getter, or null if we have to dispatch to super class
+     * @param desc     descriptor
+     * @param request  link request
+     * @return invocation or null if needs to be sent to slow relink
+     */
+    @Override
+    public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
+        final MethodType callType   = desc.getMethodType();
+        final Class<?>   indexType  = callType.parameterType(1);
+        final Class<?>   returnType = callType.returnType();
+
+        if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
+            final Object[] args  = request.getArguments();
+            final int      index = (int)args[args.length - 1];
+
+            if (has(index)) {
+                final MethodHandle getArray     = ScriptObject.GET_ARRAY.methodHandle();
+                final int          programPoint = NashornCallSiteDescriptor.isOptimistic(desc) ? NashornCallSiteDescriptor.getProgramPoint(desc) : INVALID_PROGRAM_POINT;
+                MethodHandle       getElement   = getElementGetter(returnType, programPoint);
+                if (getElement != null) {
+                    getElement = MH.filterArguments(getElement, 0, MH.asType(getArray, getArray.type().changeReturnType(clazz)));
+                    final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
+                    return new GuardedInvocation(getElement, guard, (SwitchPoint)null, ClassCastException.class);
+                }
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * Return a fast linked array setter, or null if we have to dispatch to super class
+     * @param desc     descriptor
+     * @param request  link request
+     * @return invocation or null if needs to be sent to slow relink
+     */
+    @Override
+    public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+        final MethodType callType    = desc.getMethodType();
+        final Class<?>   indexType   = callType.parameterType(1);
+        final Class<?>   elementType = callType.parameterType(2);
+
+        if (ContinuousArrayData.class.isAssignableFrom(clazz) && indexType == int.class) {
+            final Object[]        args  = request.getArguments();
+            final int             index = (int)args[args.length - 2];
+
+            //sp may be invalidated by e.g. preventExtensions before the first setter is linked
+            //then it is already created. otherwise, create it here to guard against future
+            //invalidations
+            ensureSwitchPointExists();
+
+            if (!sp.hasBeenInvalidated() && hasRoomFor(index)) {
+                MethodHandle setElement = getElementSetter(elementType); //Z(continuousarraydata, int, int), return true if successful
+                if (setElement != null) {
+                    //else we are dealing with a wider type than supported by this callsite
+                    MethodHandle getArray = ScriptObject.GET_ARRAY.methodHandle();
+                    getArray   = MH.asType(getArray, getArray.type().changeReturnType(getClass()));
+                    setElement = MH.filterArguments(setElement, 0, getArray);
+                    final MethodHandle guard = MH.insertArguments(FAST_ACCESS_GUARD, 0, clazz);
+                    return new GuardedInvocation(setElement, guard, sp, ClassCastException.class); //CCE if not a scriptObject anymore
+                }
+            }
+        }
+
+        return null;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
index 20c415e..bf120ea 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedArrayFilter.java
@@ -45,7 +45,7 @@
 
     @Override
     public ArrayData copy() {
-        DeletedArrayFilter copy = new DeletedArrayFilter(underlying.copy());
+        final DeletedArrayFilter copy = new DeletedArrayFilter(underlying.copy());
         copy.getDeleted().copy(deleted);
         return copy;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
index 4036896..b74d078 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/DeletedRangeArrayFilter.java
@@ -36,17 +36,25 @@
     private long lo, hi;
 
     DeletedRangeArrayFilter(final ArrayData underlying, final long lo, final long hi) {
-        super(underlying);
+        super(maybeSparse(underlying, hi));
         this.lo = lo;
         this.hi = hi;
     }
 
+    private static ArrayData maybeSparse(final ArrayData underlying, final long hi) {
+        if(hi < SparseArrayData.MAX_DENSE_LENGTH || underlying instanceof SparseArrayData) {
+            return underlying;
+        }
+        return new SparseArrayData(underlying, underlying.length());
+    }
+
     private boolean isEmpty() {
         return lo > hi;
     }
 
     private boolean isDeleted(final int index) {
-        return lo <= index && index <= hi;
+        final long longIndex = ArrayIndex.toLongIndex(index);
+        return lo <= longIndex && longIndex <= hi;
     }
 
     @Override
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
index e15541d..ccf1d88 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/FrozenArrayFilter.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
-import jdk.nashorn.internal.objects.Global;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
+import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.PropertyDescriptor;
 
 /**
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
index 07ddda2..57d0cd9 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/IntArrayData.java
@@ -25,7 +25,12 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
@@ -33,7 +38,7 @@
  * Implementation of {@link ArrayData} as soon as an int has been
  * written to the array. This is the default data for new arrays
  */
-final class IntArrayData extends ArrayData {
+final class IntArrayData extends ContinuousArrayData {
     /**
      * The wrapped array
      */
@@ -59,6 +64,36 @@
         this.array = array;
     }
 
+    private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), IntArrayData.class, "getElem", int.class, int.class).methodHandle();
+    private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), IntArrayData.class, "setElem", void.class, int.class, int.class).methodHandle();
+
+    @SuppressWarnings("unused")
+    private int getElem(final int index) {
+        if (has(index)) {
+            return array[index];
+        }
+        throw new ClassCastException();
+    }
+
+    @SuppressWarnings("unused")
+    private void setElem(final int index, final int elem) {
+        if (hasRoomFor(index)) {
+            array[index] = elem;
+            return;
+        }
+        throw new ClassCastException();
+    }
+
+    @Override
+    public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+        return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+    }
+
+    @Override
+    public MethodHandle getElementSetter(final Class<?> elementType) {
+        return elementType == int.class ? getContinuousElementSetter(SET_ELEM, elementType) : null;
+    }
+
     @Override
     public ArrayData copy() {
         return new IntArrayData(array.clone(), (int) length());
@@ -71,7 +106,7 @@
 
     @Override
     public Object asArrayOfType(final Class<?> componentType) {
-        if(componentType == int.class) {
+        if (componentType == int.class) {
             return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
         }
         return super.asArrayOfType(componentType);
@@ -144,22 +179,15 @@
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
             return new SparseArrayData(this, safeIndex + 1);
         }
-
-        int newLength = array.length;
-
-        while (newLength <= safeIndex) {
-            newLength = ArrayData.nextSize(newLength);
-        }
-
-        if (array.length <= safeIndex) {
+        final int alen = array.length;
+        if (safeIndex >= alen) {
+            final int newLength = ArrayData.nextSize((int)safeIndex);
             array = Arrays.copyOf(array, newLength);
         }
-
         setLength(safeIndex + 1);
-
         return this;
     }
 
@@ -172,8 +200,8 @@
 
     @Override
     public ArrayData set(final int index, final Object value, final boolean strict) {
-        if (value instanceof Integer) {
-            return set(index, ((Number)value).intValue(), strict);
+        if (JSType.isRepresentableAsInt(value)) {
+            return set(index, JSType.toInt32(value), strict);
         } else if (value == ScriptRuntime.UNDEFINED) {
             return new UndefinedArrayFilter(this).set(index, value, strict);
         }
@@ -192,9 +220,8 @@
 
     @Override
     public ArrayData set(final int index, final long value, final boolean strict) {
-        final int intValue = (int)value;
-        if (intValue == value) {
-            array[index] = intValue;
+        if (JSType.isRepresentableAsInt(value)) {
+            array[index] = JSType.toInt32(value);
             setLength(Math.max(index + 1, length()));
             return this;
         }
@@ -214,21 +241,41 @@
     }
 
     @Override
+    public Type getOptimisticType() {
+        return Type.INT;
+    }
+
+    @Override
     public int getInt(final int index) {
         return array[index];
     }
 
     @Override
+    public int getIntOptimistic(final int index, final int programPoint) {
+        return array[index];
+    }
+
+    @Override
     public long getLong(final int index) {
         return array[index];
     }
 
     @Override
+    public long getLongOptimistic(final int index, final int programPoint) {
+        return array[index];
+    }
+
+    @Override
     public double getDouble(final int index) {
         return array[index];
     }
 
     @Override
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        return array[index];
+    }
+
+    @Override
     public Object getObject(final int index) {
         return array[index];
     }
@@ -264,20 +311,31 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? (from + length()) : from;
+        final long start     = from < 0 ? from + length() : from;
         final long newLength = to - start;
 
         return new IntArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
+    public final ArrayData push(final boolean strict, final int item) {
+        final long      length = length();
+        final ArrayData newData = ensure(length);
+        if (newData == this) {
+            array[(int)length] = item;
+            return this;
+        }
+        return newData.set((int)length, item, strict);
+    }
+
+    @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
         final long oldLength = length();
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
         }
-        final ArrayData returnValue = (removed == 0) ?
+        final ArrayData returnValue = removed == 0 ?
                 EMPTY_ARRAY : new IntArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
 
         if (newLength != oldLength) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
index 4bb96aa..4fc0c63 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/LongArrayData.java
@@ -25,7 +25,13 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
@@ -33,7 +39,7 @@
  * Implementation of {@link ArrayData} as soon as a long has been
  * written to the array
  */
-final class LongArrayData extends ArrayData {
+final class LongArrayData extends ContinuousArrayData {
     /**
      * The wrapped array
      */
@@ -52,12 +58,12 @@
 
     @Override
     public ArrayData copy() {
-        return new LongArrayData(array.clone(), (int) length());
+        return new LongArrayData(array.clone(), (int)length());
     }
 
     @Override
     public Object[] asObjectArray() {
-        return toObjectArray(array, (int) length());
+        return toObjectArray(array, (int)length());
     }
 
     private static Object[] toObjectArray(final long[] array, final int length) {
@@ -73,8 +79,8 @@
 
     @Override
     public Object asArrayOfType(final Class<?> componentType) {
-        if(componentType == long.class) {
-            return array.length == length() ? array.clone() : Arrays.copyOf(array, (int) length());
+        if (componentType == long.class) {
+            return array.length == length() ? array.clone() : Arrays.copyOf(array, (int)length());
         }
         return super.asArrayOfType(componentType);
     }
@@ -121,22 +127,15 @@
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
             return new SparseArrayData(this, safeIndex + 1);
         }
-
-        int newLength = array.length;
-
-        while (newLength <= safeIndex) {
-            newLength = ArrayData.nextSize(newLength);
-        }
-
-        if (array.length <= safeIndex) {
+        final int alen = array.length;
+        if (safeIndex >= alen) {
+            final int newLength = ArrayData.nextSize((int)safeIndex);
             array = Arrays.copyOf(array, newLength);
         }
-
         setLength(safeIndex + 1);
-
         return this;
     }
 
@@ -184,6 +183,44 @@
     }
 
     @Override
+    public Type getOptimisticType() {
+        return Type.LONG;
+    }
+
+    private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), LongArrayData.class, "getElem", long.class, int.class).methodHandle();
+    private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), LongArrayData.class, "setElem", void.class, int.class, long.class).methodHandle();
+
+    @SuppressWarnings("unused")
+    private long getElem(final int index) {
+        if (has(index)) {
+            return array[index];
+        }
+        throw new ClassCastException();
+    }
+
+    @SuppressWarnings("unused")
+    private void setElem(final int index, final long elem) {
+        if (hasRoomFor(index)) {
+            array[index] = elem;
+            return;
+        }
+        throw new ClassCastException();
+    }
+
+    @Override
+    public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+        if (returnType == int.class) {
+            return null;
+        }
+        return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+    }
+
+    @Override
+    public MethodHandle getElementSetter(final Class<?> elementType) {
+        return elementType == int.class || elementType == long.class ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null;
+    }
+
+    @Override
     public int getInt(final int index) {
         return (int)array[index];
     }
@@ -194,11 +231,21 @@
     }
 
     @Override
+    public long getLongOptimistic(final int index, final int programPoint) {
+        return array[index];
+    }
+
+    @Override
     public double getDouble(final int index) {
         return array[index];
     }
 
     @Override
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        return array[index];
+    }
+
+    @Override
     public Object getObject(final int index) {
         return array[index];
     }
@@ -234,19 +281,30 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? (from + length()) : from;
+        final long start     = from < 0 ? from + length() : from;
         final long newLength = to - start;
         return new LongArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
+    public final ArrayData push(final boolean strict, final long item) {
+        final long      length = length();
+        final ArrayData newData = ensure(length);
+        if (newData == this) {
+            array[(int)length] = item;
+            return this;
+        }
+        return newData.set((int)length, item, strict);
+    }
+
+    @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
         final long oldLength = length();
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
         }
-        final ArrayData returnValue = (removed == 0) ?
+        final ArrayData returnValue = removed == 0 ?
                 EMPTY_ARRAY : new LongArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
 
         if (newLength != oldLength) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java
index 1f2298c..4e0ce37 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/NoTypeArrayData.java
@@ -43,7 +43,7 @@
 
     @Override
     public Object[] asObjectArray() {
-        return new Object[0];
+        return ScriptRuntime.EMPTY_ARRAY;
     }
 
     @Override
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
index 8254db6..0739ae8 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/NumberArrayData.java
@@ -25,15 +25,20 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+import static jdk.nashorn.internal.lookup.Lookup.MH;
 import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
 
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
+import jdk.nashorn.internal.codegen.types.Type;
 
 /**
  * Implementation of {@link ArrayData} as soon as a double has been
  * written to the array
  */
-final class NumberArrayData extends ArrayData {
+final class NumberArrayData extends ContinuousArrayData {
     /**
      * The wrapped array
      */
@@ -105,24 +110,17 @@
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
             return new SparseArrayData(this, safeIndex + 1);
         }
-
-        int newLength = array.length;
-
-        while (newLength <= safeIndex) {
-            newLength = ArrayData.nextSize(newLength);
+        final int alen = array.length;
+        if (safeIndex >= alen) {
+            final int newLength = ArrayData.nextSize((int)safeIndex);
+            array = Arrays.copyOf(array, newLength); //todo fill with nan or never accessed?
         }
-
-        if (array.length <= safeIndex) {
-            array = Arrays.copyOf(array, newLength);
-            Arrays.fill(array, (int) length(), newLength, Double.NaN);
-        }
-
         setLength(safeIndex + 1);
-
         return this;
+
     }
 
     @Override
@@ -165,6 +163,44 @@
     }
 
     @Override
+    public Type getOptimisticType() {
+        return Type.NUMBER;
+    }
+
+    private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), NumberArrayData.class, "getElem", double.class, int.class).methodHandle();
+    private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), NumberArrayData.class, "setElem", void.class, int.class, double.class).methodHandle();
+
+    @SuppressWarnings("unused")
+    private double getElem(final int index) {
+        if (has(index)) {
+            return array[index];
+        }
+        throw new ClassCastException();
+    }
+
+    @SuppressWarnings("unused")
+    private void setElem(final int index, final double elem) {
+        if (hasRoomFor(index)) {
+            array[index] = elem;
+            return;
+        }
+        throw new ClassCastException();
+    }
+
+    @Override
+    public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+        if (returnType == int.class || returnType == long.class) {
+            return null;
+        }
+        return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+    }
+
+    @Override
+    public MethodHandle getElementSetter(final Class<?> elementType) {
+        return elementType.isPrimitive() ? getContinuousElementSetter(MH.asType(SET_ELEM, SET_ELEM.type().changeParameterType(2, elementType)), elementType) : null;
+    }
+
+    @Override
     public int getInt(final int index) {
         return (int)array[index];
     }
@@ -180,6 +216,11 @@
     }
 
     @Override
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        return array[index];
+    }
+
+    @Override
     public Object getObject(final int index) {
         return array[index];
     }
@@ -214,19 +255,30 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? (from + length()) : from;
+        final long start     = from < 0 ? from + length() : from;
         final long newLength = to - start;
         return new NumberArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
+    public final ArrayData push(final boolean strict, final double item) {
+        final long      length = length();
+        final ArrayData newData = ensure(length);
+        if (newData == this) {
+            array[(int)length] = item;
+            return this;
+        }
+        return newData.set((int)length, item, strict);
+    }
+
+    @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
         final long oldLength = length();
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
         }
-        final ArrayData returnValue = (removed == 0) ?
+        final ArrayData returnValue = removed == 0 ?
                 EMPTY_ARRAY : new NumberArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
 
         if (newLength != oldLength) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
index a9a1b5b..636c8c2 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ObjectArrayData.java
@@ -25,7 +25,12 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
+import static jdk.nashorn.internal.codegen.CompilerConstants.specialCall;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
 import java.util.Arrays;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
@@ -33,7 +38,7 @@
  * Implementation of {@link ArrayData} as soon as an Object has been
  * written to the array
  */
-final class ObjectArrayData extends ArrayData {
+final class ObjectArrayData extends ContinuousArrayData {
 
     /**
      * The wrapped array
@@ -58,7 +63,15 @@
 
     @Override
     public Object[] asObjectArray() {
-        return Arrays.copyOf(array, (int) length());
+        return array.length == length() ? array.clone() : asObjectArrayCopy();
+    }
+
+    private Object[] asObjectArrayCopy() {
+        final long l = length();
+        assert l <= Integer.MAX_VALUE;
+        final Object[] copy = new Object[(int)l];
+        System.arraycopy(array, 0, copy, 0, (int)l);
+        return copy;
     }
 
     @Override
@@ -84,23 +97,15 @@
 
     @Override
     public ArrayData ensure(final long safeIndex) {
-        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH && safeIndex >= array.length) {
+        if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
             return new SparseArrayData(this, safeIndex + 1);
         }
-
-        int newLength = array.length;
-
-        while (newLength <= safeIndex) {
-            newLength = ArrayData.nextSize(newLength);
+        final int alen = array.length;
+        if (safeIndex >= alen) {
+            final int newLength = ArrayData.nextSize((int)safeIndex);
+            array = Arrays.copyOf(array, newLength); //fill with undefined or OK? TODO
         }
-
-        if (array.length <= safeIndex) {
-            array = Arrays.copyOf(array, newLength);
-            Arrays.fill(array, (int) length(), newLength, ScriptRuntime.UNDEFINED);
-        }
-
         setLength(safeIndex + 1);
-
         return this;
     }
 
@@ -151,6 +156,45 @@
     }
 
     @Override
+    public Type getOptimisticType() {
+        return Type.OBJECT;
+    }
+
+    private static final MethodHandle HAS_GET_ELEM = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "getElem", Object.class, int.class).methodHandle();
+    private static final MethodHandle SET_ELEM     = specialCall(MethodHandles.lookup(), ObjectArrayData.class, "setElem", void.class, int.class, Object.class).methodHandle();
+
+    @SuppressWarnings("unused")
+    private Object getElem(final int index) {
+        if (has(index)) {
+            return array[index];
+        }
+        throw new ClassCastException();
+    }
+
+    @SuppressWarnings("unused")
+    private void setElem(final int index, final Object elem) {
+        if (hasRoomFor(index)) {
+            array[index] = elem;
+            return;
+        }
+        throw new ClassCastException();
+    }
+
+    @Override
+    public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+        if (returnType.isPrimitive()) {
+            return null;
+        }
+        return getContinuousElementGetter(HAS_GET_ELEM, returnType, programPoint);
+    }
+
+    @Override
+    public MethodHandle getElementSetter(final Class<?> elementType) {
+        return getContinuousElementSetter(SET_ELEM, Object.class);
+    }
+
+
+    @Override
     public int getInt(final int index) {
         return JSType.toInt32(array[index]);
     }
@@ -202,19 +246,30 @@
 
     @Override
     public ArrayData slice(final long from, final long to) {
-        final long start     = from < 0 ? (from + length()) : from;
+        final long start     = from < 0 ? from + length() : from;
         final long newLength = to - start;
         return new ObjectArrayData(Arrays.copyOfRange(array, (int)from, (int)to), (int)newLength);
     }
 
     @Override
+    public ArrayData push(final boolean strict, final Object item) {
+        final long      length = length();
+        final ArrayData newData = ensure(length);
+        if (newData == this) {
+            array[(int)length] = item;
+            return this;
+        }
+        return newData.set((int)length, item, strict);
+    }
+
+    @Override
     public ArrayData fastSplice(final int start, final int removed, final int added) throws UnsupportedOperationException {
         final long oldLength = length();
         final long newLength = oldLength - removed + added;
         if (newLength > SparseArrayData.MAX_DENSE_LENGTH && newLength > array.length) {
             throw new UnsupportedOperationException();
         }
-        final ArrayData returnValue = (removed == 0) ?
+        final ArrayData returnValue = removed == 0 ?
                 EMPTY_ARRAY : new ObjectArrayData(Arrays.copyOfRange(array, start, start + removed), removed);
 
         if (newLength != oldLength) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
index bc6de9f..3e78f2d 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/SealedArrayFilter.java
@@ -25,9 +25,9 @@
 
 package jdk.nashorn.internal.runtime.arrays;
 
-import jdk.nashorn.internal.objects.Global;
 import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
 
+import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.PropertyDescriptor;
 
 /**
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
index ed99ce1..623e315 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/SparseArrayData.java
@@ -28,6 +28,7 @@
 import java.util.Arrays;
 import java.util.Map;
 import java.util.TreeMap;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
@@ -35,7 +36,7 @@
  * Handle arrays where the index is very large.
  */
 class SparseArrayData extends ArrayData {
-    static final long MAX_DENSE_LENGTH = 512 * 1024;
+    static final long MAX_DENSE_LENGTH = 16 * 512 * 1024;
 
     /** Underlying array. */
     private ArrayData underlying;
@@ -161,8 +162,9 @@
             underlying = underlying.set(index, value, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
-            sparseMap.put(indexToKey(index), value);
-            setLength(Math.max(index + 1, length()));
+            final Long longIndex = indexToKey(index);
+            sparseMap.put(longIndex, value);
+            setLength(Math.max(longIndex + 1, length()));
         }
 
         return this;
@@ -175,8 +177,9 @@
             underlying = underlying.set(index, value, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
-            sparseMap.put(indexToKey(index), value);
-            setLength(Math.max(index + 1, length()));
+            final Long longIndex = indexToKey(index);
+            sparseMap.put(longIndex, value);
+            setLength(Math.max(longIndex + 1, length()));
         }
         return this;
     }
@@ -188,8 +191,9 @@
             underlying = underlying.set(index, value, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
-            sparseMap.put(indexToKey(index), value);
-            setLength(Math.max(index + 1, length()));
+            final Long longIndex = indexToKey(index);
+            sparseMap.put(longIndex, value);
+            setLength(Math.max(longIndex + 1, length()));
         }
         return this;
     }
@@ -201,8 +205,9 @@
             underlying = underlying.set(index, value, strict);
             setLength(Math.max(underlying.length(), length()));
         } else {
-            sparseMap.put(indexToKey(index), value);
-            setLength(Math.max(index + 1, length()));
+            final Long longIndex = indexToKey(index);
+            sparseMap.put(longIndex, value);
+            setLength(Math.max(longIndex + 1, length()));
         }
         return this;
     }
@@ -220,6 +225,11 @@
     }
 
     @Override
+    public Type getOptimisticType() {
+        return underlying.getOptimisticType();
+    }
+
+    @Override
     public int getInt(final int index) {
         if (index >= 0 && index < maxDenseLength) {
             return underlying.getInt(index);
@@ -228,6 +238,14 @@
     }
 
     @Override
+    public int getIntOptimistic(final int index, final int programPoint) {
+        if (index >= 0 && index < maxDenseLength) {
+            return underlying.getIntOptimistic(index, programPoint);
+        }
+        return JSType.toInt32Optimistic(sparseMap.get(indexToKey(index)), programPoint);
+    }
+
+    @Override
     public long getLong(final int index) {
         if (index >= 0 && index < maxDenseLength) {
             return underlying.getLong(index);
@@ -236,6 +254,14 @@
     }
 
     @Override
+    public long getLongOptimistic(final int index, final int programPoint) {
+        if (index >= 0 && index < maxDenseLength) {
+            return underlying.getLongOptimistic(index, programPoint);
+        }
+        return JSType.toLongOptimistic(sparseMap.get(indexToKey(index)), programPoint);
+    }
+
+    @Override
     public double getDouble(final int index) {
         if (index >= 0 && index < maxDenseLength) {
             return underlying.getDouble(index);
@@ -244,6 +270,14 @@
     }
 
     @Override
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        if (index >= 0 && index < maxDenseLength) {
+            return underlying.getDouble(index);
+        }
+        return JSType.toNumberOptimistic(sparseMap.get(indexToKey(index)), programPoint);
+    }
+
+    @Override
     public Object getObject(final int index) {
         if (index >= 0 && index < maxDenseLength) {
             return underlying.getObject(index);
@@ -291,7 +325,7 @@
     }
 
     private static Long indexToKey(final int index) {
-        return Long.valueOf(index & JSType.MAX_UINT);
+        return Long.valueOf(ArrayIndex.toLongIndex(index));
     }
 
     @Override
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
new file mode 100644
index 0000000..291e59e
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/TypedArrayData.java
@@ -0,0 +1,205 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.runtime.arrays;
+
+import static jdk.nashorn.internal.lookup.Lookup.MH;
+
+import java.lang.invoke.MethodHandle;
+import java.nio.Buffer;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.nashorn.internal.lookup.Lookup;
+
+/**
+ * The superclass of all ArrayData used by TypedArrays
+ *
+ * @param <T> buffer implementation
+ */
+public abstract class TypedArrayData<T extends Buffer> extends ContinuousArrayData {
+
+    /** wrapped native buffer */
+    protected final T nb;
+
+    /**
+     * Constructor
+     * @param nb wrapped native buffer
+     * @param elementLength length in elements
+     */
+    protected TypedArrayData(final T nb, final int elementLength) {
+        super(elementLength); //TODO is this right?
+        this.nb = nb;
+    }
+
+    /**
+     * Length in elements. Accessed from {@code ArrayBufferView}
+     * @return element length
+     */
+    public final int getElementLength() {
+        return (int)length();
+    }
+
+    /**
+     * Is this an unsigned array data?
+     * @return true if unsigned
+     */
+    public boolean isUnsigned() {
+        return false;
+    }
+
+    /**
+     * Is this a clamped array data?
+     * @return true if clamped
+     */
+    public boolean isClamped() {
+        return false;
+    }
+
+    @Override
+    public boolean canDelete(final int index, final boolean strict) {
+        return false;
+    }
+
+    @Override
+    public boolean canDelete(final long fromIndex, final long toIndex, final boolean strict) {
+        return false;
+    }
+
+    @Override
+    public ArrayData copy() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object[] asObjectArray() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void shiftLeft(final int by) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArrayData shiftRight(final int by) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArrayData ensure(final long safeIndex) {
+        return this;
+    }
+
+    @Override
+    public ArrayData shrink(final long newLength) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final boolean has(final int index) {
+        return 0 <= index && index < length();
+    }
+
+    @Override
+    public ArrayData delete(final int index) {
+        return this;
+    }
+
+    @Override
+    public ArrayData delete(final long fromIndex, final long toIndex) {
+        return this;
+    }
+
+    @Override
+    protected ArrayData convert(final Class<?> type) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Object pop() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public ArrayData slice(final long from, final long to) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Element getter method handle
+     * @return getter
+     */
+    protected abstract MethodHandle getGetElem();
+
+    /**
+     * Element setter method handle
+     * @return setter
+     */
+    protected abstract MethodHandle getSetElem();
+
+    @Override
+    public MethodHandle getElementGetter(final Class<?> returnType, final int programPoint) {
+        final MethodHandle getter = getContinuousElementGetter(getClass(), getGetElem(), returnType, programPoint);
+        if (getter != null) {
+            return Lookup.filterReturnType(getter, returnType);
+        }
+        return getter;
+    }
+
+    @Override
+    public MethodHandle getElementSetter(final Class<?> elementType) {
+        return getContinuousElementSetter(getClass(), Lookup.filterArgumentType(getSetElem(), 2, elementType), elementType);
+    }
+
+    @Override
+    protected MethodHandle getContinuousElementSetter(final Class<? extends ContinuousArrayData> clazz, final MethodHandle setHas, final Class<?> elementType) {
+        final MethodHandle mh = Lookup.filterArgumentType(setHas, 2, elementType);
+        return MH.asType(mh, mh.type().changeParameterType(0, clazz));
+    }
+
+    @Override
+    public GuardedInvocation findFastGetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) {
+        final GuardedInvocation inv = super.findFastGetIndexMethod(clazz, desc, request);
+
+        if (inv != null) {
+            return inv;
+        }
+
+        return null;
+    }
+
+    @Override
+    public GuardedInvocation findFastSetIndexMethod(final Class<? extends ArrayData> clazz, final CallSiteDescriptor desc, final LinkRequest request) { // array, index, value
+        final GuardedInvocation inv = super.findFastSetIndexMethod(clazz, desc, request);
+
+        if (inv != null) {
+            return inv;
+        }
+
+        return null;
+    }
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
index 57046f8..e2488d3 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/UndefinedArrayFilter.java
@@ -29,6 +29,7 @@
 
 import java.lang.reflect.Array;
 import jdk.nashorn.internal.runtime.BitVector;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
 /**
  * This filter handles the presence of undefined array elements.
@@ -45,7 +46,7 @@
 
     @Override
     public ArrayData copy() {
-        UndefinedArrayFilter copy = new UndefinedArrayFilter(underlying.copy());
+        final UndefinedArrayFilter copy = new UndefinedArrayFilter(underlying.copy());
         copy.getUndefined().copy(undefined);
         return copy;
     }
@@ -154,6 +155,15 @@
     }
 
     @Override
+    public int getIntOptimistic(final int index, final int programPoint) {
+        if (undefined.isSet(index)) {
+            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+        }
+
+        return super.getIntOptimistic(index, programPoint);
+    }
+
+    @Override
     public long getLong(final int index) {
         if (undefined.isSet(index)) {
             return 0L;
@@ -163,6 +173,15 @@
     }
 
     @Override
+    public long getLongOptimistic(final int index, final int programPoint) {
+        if (undefined.isSet(index)) {
+            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+        }
+
+        return super.getLongOptimistic(index, programPoint);
+    }
+
+    @Override
     public double getDouble(final int index) {
         if (undefined.isSet(index)) {
             return Double.NaN;
@@ -172,6 +191,15 @@
     }
 
     @Override
+    public double getDoubleOptimistic(final int index, final int programPoint) {
+        if (undefined.isSet(index)) {
+            throw new UnwarrantedOptimismException(UNDEFINED, programPoint);
+        }
+
+        return super.getDoubleOptimistic(index, programPoint);
+    }
+
+    @Override
     public Object getObject(final int index) {
         if (undefined.isSet(index)) {
             return UNDEFINED;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java b/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java
new file mode 100644
index 0000000..bdc73bf
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/events/RecompilationEvent.java
@@ -0,0 +1,68 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime.events;
+
+import java.util.logging.Level;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.RecompilableScriptFunctionData;
+import jdk.nashorn.internal.runtime.RewriteException;
+
+/**
+ * Subclass of runtime event for {@link RewriteException}. In order not
+ * to leak memory, RewriteExceptions get their return value destroyed
+ * and nulled out during recompilation. If we are running with event
+ * logging enabled, we need to retain the returnValue, hence the extra
+ * field
+ */
+public final class RecompilationEvent extends RuntimeEvent<RewriteException> {
+
+    private final Object returnValue;
+
+    /**
+     * Constructor
+     *
+     * @param level            logging level
+     * @param rewriteException rewriteException wrapped by this RuntimEvent
+     * @param returnValue      rewriteException return value - as we don't want to make
+     *     {@link RewriteException#getReturnValueNonDestructive()} public, we pass it as
+     *     an extra parameter, rather than querying the getter from another package.
+     */
+    @SuppressWarnings("javadoc")
+    public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) {
+        super(level, rewriteException);
+        assert Context.getContext().getLogger(RecompilableScriptFunctionData.class).isEnabled() :
+            "Unit test/instrumentation purpose only: RecompilationEvent instances should not be created without '--log=recompile', or we will leak memory in the general case";
+        this.returnValue = returnValue;
+    }
+
+    /**
+     * Get the preserved return value for the RewriteException
+     * @return return value
+     */
+    public Object getReturnValue() {
+        return returnValue;
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java b/nashorn/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java
new file mode 100644
index 0000000..29a3714
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/events/RuntimeEvent.java
@@ -0,0 +1,87 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime.events;
+
+import java.util.logging.Level;
+import jdk.nashorn.internal.objects.NativeDebug;
+import jdk.nashorn.internal.runtime.options.Options;
+
+/**
+ * Class for representing a runtime event, giving less global dependencies than logger.
+ * Every {@link NativeDebug} object keeps a queue of RuntimeEvents that can be explored
+ * through the debug API.
+ *
+ * @param <T> class of the value this event wraps
+ */
+public class RuntimeEvent<T> {
+    /** Queue size for the runtime event buffer */
+    public static final int RUNTIME_EVENT_QUEUE_SIZE = Options.getIntProperty("nashorn.runtime.event.queue.size", 1024);
+
+    private final Level level;
+    private final T value;
+
+    /**
+     * Constructor
+     *
+     * @param level  log level for runtime event to create
+     * @param object object to wrap
+     */
+    public RuntimeEvent(final Level level, final T object) {
+        this.level = level;
+        this.value = object;
+    }
+
+    /**
+     * Return the value wrapped in this runtime event
+     * @return value
+     */
+    public final T getValue() {
+        return value;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+
+        sb.append('[').
+            append(level).
+            append("] ").
+            append(value == null ? "null" : getValueClass().getSimpleName()).
+            append(" value=").
+            append(value);
+
+        return sb.toString();
+    }
+
+    /**
+     * Descriptor for this runtime event, must be overridden and
+     * implemented, e.g. "RewriteException"
+     * @return event name
+     */
+    public final Class<?> getValueClass() {
+        return value.getClass();
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
index 4882103..67dd88e 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.codegen.CompilerConstants.staticCallNoLookup;
 
 import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
 import java.lang.invoke.MethodHandle;
 import java.lang.invoke.MethodHandles;
 import java.lang.invoke.MethodHandles.Lookup;
@@ -35,14 +36,20 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.DynamicLinkerFactory;
+import jdk.internal.dynalink.GuardedInvocationFilter;
 import jdk.internal.dynalink.beans.BeansLinker;
 import jdk.internal.dynalink.beans.StaticClass;
 import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.CompilerConstants.Call;
+import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.codegen.RuntimeCallSite;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
 import jdk.nashorn.internal.runtime.JSType;
+import jdk.nashorn.internal.runtime.OptimisticReturnFilters;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 import jdk.nashorn.internal.runtime.options.Options;
@@ -54,6 +61,25 @@
     /** Reference to the seed boostrap function */
     public static final Call BOOTSTRAP = staticCallNoLookup(Bootstrap.class, "bootstrap", CallSite.class, Lookup.class, String.class, MethodType.class, int.class);
 
+    private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+
+    /**
+     * The default dynalink relink threshold for megamorphisism is 8. In the case
+     * of object fields only, it is fine. However, with dual fields, in order to get
+     * performance on benchmarks with a lot of object instantiation and then field
+     * reassignment, it can take slightly more relinks to become stable with type
+     * changes swapping out an entire proprety map and making a map guard fail.
+     * Therefore the relink threshold is set to 16 for dual fields (now the default).
+     * This doesn't seem to have any other negative performance implication.
+     *
+     * See for example octane.gbemu, run with --log=fields:warning to study
+     * megamorphic behavior
+     */
+    private static final int NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD =
+            ObjectClassGenerator.OBJECT_FIELDS_ONLY ?
+                     8 :
+                    16;
+
     // do not create me!!
     private Bootstrap() {
     }
@@ -62,18 +88,25 @@
     static {
         final DynamicLinkerFactory factory = new DynamicLinkerFactory();
         final NashornBeansLinker nashornBeansLinker = new NashornBeansLinker();
-        final JSObjectLinker jsObjectLinker = new JSObjectLinker(nashornBeansLinker);
         factory.setPrioritizedLinkers(
             new NashornLinker(),
             new NashornPrimitiveLinker(),
             new NashornStaticClassLinker(),
             new BoundDynamicMethodLinker(),
             new JavaSuperAdapterLinker(),
-            jsObjectLinker,
+            new JSObjectLinker(nashornBeansLinker),
+            new BrowserJSObjectLinker(nashornBeansLinker),
             new ReflectionCheckLinker());
         factory.setFallbackLinkers(nashornBeansLinker, new NashornBottomLinker());
         factory.setSyncOnRelink(true);
-        final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", -1);
+        factory.setPrelinkFilter(new GuardedInvocationFilter() {
+            @Override
+            public GuardedInvocation filter(final GuardedInvocation inv, final LinkRequest request, final LinkerServices linkerServices) {
+                final CallSiteDescriptor desc = request.getCallSiteDescriptor();
+                return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType());
+            }
+        });
+        final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD);
         if (relinkThreshold > -1) {
             factory.setUnstableRelinkThreshold(relinkThreshold);
         }
@@ -148,6 +181,60 @@
     }
 
     /**
+     * Boostrapper for math calls that may overflow
+     * @param lookup         lookup
+     * @param name           name of operation
+     * @param type           method type
+     * @param programPoint   program point to bind to callsite
+     *
+     * @return callsite for a math instrinic node
+     */
+    public static CallSite mathBootstrap(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int programPoint) {
+        final MethodHandle mh;
+        switch (name) {
+        case "iadd":
+            mh = JSType.ADD_EXACT.methodHandle();
+            break;
+        case "isub":
+            mh = JSType.SUB_EXACT.methodHandle();
+            break;
+        case "imul":
+            mh = JSType.MUL_EXACT.methodHandle();
+            break;
+        case "idiv":
+            mh = JSType.DIV_EXACT.methodHandle();
+            break;
+        case "irem":
+            mh = JSType.REM_EXACT.methodHandle();
+            break;
+        case "ineg":
+            mh = JSType.NEGATE_EXACT.methodHandle();
+            break;
+        case "ladd":
+            mh = JSType.ADD_EXACT_LONG.methodHandle();
+            break;
+        case "lsub":
+            mh = JSType.SUB_EXACT_LONG.methodHandle();
+            break;
+        case "lmul":
+            mh = JSType.MUL_EXACT_LONG.methodHandle();
+            break;
+        case "ldiv":
+            mh = JSType.DIV_EXACT_LONG.methodHandle();
+            break;
+        case "lrem":
+            mh = JSType.REM_EXACT_LONG.methodHandle();
+            break;
+        case "lneg":
+            mh = JSType.NEGATE_EXACT_LONG.methodHandle();
+            break;
+        default:
+            throw new AssertionError("unsupported math intrinsic");
+        }
+        return new ConstantCallSite(MH.insertArguments(mh, mh.type().parameterCount() - 1, programPoint));
+    }
+
+    /**
      * Returns a dynamic invoker for a specified dynamic operation using the public lookup. You can use this method to
      * create a method handle that when invoked acts completely as if it were a Nashorn-linked call site. An overview of
      * available dynamic operations can be found in the
@@ -267,7 +354,7 @@
      * @param boundThis the bound "this" value.
      * @return a bound dynamic method.
      */
-    public static Object bindDynamicMethod(Object dynamicMethod, Object boundThis) {
+    public static Object bindDynamicMethod(final Object dynamicMethod, final Object boundThis) {
         return new BoundDynamicMethod(dynamicMethod, boundThis);
     }
 
@@ -288,7 +375,7 @@
      * @param clazz the class being tested
      * @param isStatic is access checked for static members (or instance members)
      */
-    public static void checkReflectionAccess(Class<?> clazz, boolean isStatic) {
+    public static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
         ReflectionCheckLinker.checkReflectionAccess(clazz, isStatic);
     }
 
@@ -307,16 +394,16 @@
     /**
      * Takes a guarded invocation, and ensures its method and guard conform to the type of the call descriptor, using
      * all type conversions allowed by the linker's services. This method is used by Nashorn's linkers as a last step
-     * before returning guarded invocations to the callers. Most of the code used to produce the guarded invocations
-     * does not make an effort to coordinate types of the methods, and so a final type adjustment before a guarded
-     * invocation is returned is the responsibility of the linkers themselves.
+     * before returning guarded invocations. Most of the code used to produce the guarded invocations does not make an
+     * effort to coordinate types of the methods, and so a final type adjustment before a guarded invocation is returned
+     * to the aggregating linker is the responsibility of the linkers themselves.
      * @param inv the guarded invocation that needs to be type-converted. Can be null.
      * @param linkerServices the linker services object providing the type conversions.
      * @param desc the call site descriptor to whose method type the invocation needs to conform.
      * @return the type-converted guarded invocation. If input is null, null is returned. If the input invocation
      * already conforms to the requested type, it is returned unchanged.
      */
-    static GuardedInvocation asType(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
-        return inv == null ? null : inv.asType(linkerServices, desc.getMethodType());
+    static GuardedInvocation asTypeSafeReturn(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
+        return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType());
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
index f2089d5..9008547 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethod.java
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import java.util.Objects;
 import jdk.internal.dynalink.beans.BeansLinker;
 
 /**
@@ -48,4 +49,9 @@
     Object getBoundThis() {
         return boundThis;
     }
+
+    @Override
+    public String toString() {
+        return dynamicMethod.toString() + " on " + Objects.toString(boundThis);
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
index 77c1618..67e2983 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/BoundDynamicMethodLinker.java
@@ -42,12 +42,12 @@
  */
 final class BoundDynamicMethodLinker implements TypeBasedGuardingDynamicLinker {
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return type == BoundDynamicMethod.class;
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception {
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
         final Object objBoundDynamicMethod = linkRequest.getReceiver();
         if(!(objBoundDynamicMethod instanceof BoundDynamicMethod)) {
             return null;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
new file mode 100644
index 0000000..e8cfa4e
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/BrowserJSObjectLinker.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime.linker;
+
+import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.*;
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.GuardedInvocation;
+import jdk.internal.dynalink.linker.LinkRequest;
+import jdk.internal.dynalink.linker.LinkerServices;
+import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
+import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFactory;
+import jdk.nashorn.internal.lookup.MethodHandleFunctionality;
+import jdk.nashorn.internal.runtime.JSType;
+
+/**
+ * A Dynalink linker to handle web browser built-in JS (DOM etc.) objects.
+ */
+final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
+    private static final ClassLoader myLoader = BrowserJSObjectLinker.class.getClassLoader();
+    private static final String JSOBJECT_CLASS = "netscape.javascript.JSObject";
+    // not final because this is lazily initialized
+    // when we hit a subclass for the first time.
+    private static volatile Class<?> jsObjectClass;
+    private final NashornBeansLinker nashornBeansLinker;
+
+    BrowserJSObjectLinker(final NashornBeansLinker nashornBeansLinker) {
+        this.nashornBeansLinker = nashornBeansLinker;
+    }
+
+    @Override
+    public boolean canLinkType(final Class<?> type) {
+        return canLinkTypeStatic(type);
+    }
+
+    static boolean canLinkTypeStatic(final Class<?> type) {
+        if (jsObjectClass != null && jsObjectClass.isAssignableFrom(type)) {
+            return true;
+        }
+
+        // check if this class is a subclass of JSObject
+        Class<?> clazz = type;
+        while (clazz != null) {
+            if (clazz.getClassLoader() == myLoader &&
+                clazz.getName().equals(JSOBJECT_CLASS)) {
+                jsObjectClass = clazz;
+                return true;
+            }
+            clazz = clazz.getSuperclass();
+        }
+
+        return false;
+    }
+
+    private static void checkJSObjectClass() {
+        assert jsObjectClass != null : JSOBJECT_CLASS + " not found!";
+    }
+
+    @Override
+    public GuardedInvocation getGuardedInvocation(final LinkRequest request, final LinkerServices linkerServices) throws Exception {
+        final LinkRequest requestWithoutContext = request.withoutRuntimeContext(); // Nashorn has no runtime context
+        final Object self = requestWithoutContext.getReceiver();
+        final CallSiteDescriptor desc = requestWithoutContext.getCallSiteDescriptor();
+        checkJSObjectClass();
+
+        if (desc.getNameTokenCount() < 2 || !"dyn".equals(desc.getNameToken(CallSiteDescriptor.SCHEME))) {
+            // We only support standard "dyn:*[:*]" operations
+            return null;
+        }
+
+        final GuardedInvocation inv;
+        if (jsObjectClass.isInstance(self)) {
+            inv = lookup(desc, request, linkerServices);
+        } else {
+            throw new AssertionError(); // Should never reach here.
+        }
+
+        return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
+    }
+
+    private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception {
+        final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
+        final int c = desc.getNameTokenCount();
+
+        switch (operator) {
+            case "getProp":
+            case "getElem":
+            case "getMethod":
+                if (c > 2) {
+                    return findGetMethod(desc);
+                } else {
+                    // For indexed get, we want GuardedInvocation from beans linker and pass it.
+                    // BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access.
+                    final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
+                    return findGetIndexMethod(beanInv);
+                }
+            case "setProp":
+            case "setElem":
+                return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
+            default:
+                return null;
+        }
+    }
+
+    private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
+        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name);
+        return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
+    }
+
+    private static GuardedInvocation findGetIndexMethod(final GuardedInvocation inv) {
+        final MethodHandle getter = MH.insertArguments(JSOBJECTLINKER_GET, 0, inv.getInvocation());
+        return inv.replaceMethods(getter, inv.getGuard());
+    }
+
+    private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
+        final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2));
+        return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
+    }
+
+    private static GuardedInvocation findSetIndexMethod() {
+        return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD);
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean isJSObject(final Object self) {
+        return jsObjectClass.isInstance(self);
+    }
+
+    @SuppressWarnings("unused")
+    private static Object get(final MethodHandle fallback, final Object jsobj, final Object key) throws Throwable {
+        if (key instanceof Integer) {
+            return JSOBJECT_GETSLOT.invokeExact(jsobj, (int)key);
+        } else if (key instanceof Number) {
+            final int index = getIndex((Number)key);
+            if (index > -1) {
+                return JSOBJECT_GETSLOT.invokeExact(jsobj, index);
+            }
+        } else if (key instanceof String) {
+            final String name = (String)key;
+            if (name.indexOf('(') != -1) {
+                return fallback.invokeExact(jsobj, key);
+            } else {
+                return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key);
+            }
+        }
+        return null;
+    }
+
+    @SuppressWarnings("unused")
+    private static void put(final Object jsobj, final Object key, final Object value) throws Throwable {
+        if (key instanceof Integer) {
+            JSOBJECT_SETSLOT.invokeExact(jsobj, (int)key, value);
+        } else if (key instanceof Number) {
+            JSOBJECT_SETSLOT.invokeExact(jsobj, getIndex((Number)key), value);
+        } else if (key instanceof String) {
+            JSOBJECT_SETMEMBER.invokeExact(jsobj, (String)key, value);
+        }
+    }
+
+    private static int getIndex(final Number n) {
+        final double value = n.doubleValue();
+        return JSType.isRepresentableAsInt(value) ? (int)value : -1;
+    }
+
+    private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
+    // method handles of the current class
+    private static final MethodHandle IS_JSOBJECT_GUARD  = findOwnMH_S("isJSObject", boolean.class, Object.class);
+    private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class);
+    private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class);
+
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+            return MH.findStatic(MethodHandles.lookup(), BrowserJSObjectLinker.class, name, MH.type(rtype, types));
+    }
+
+    // method handles of netscape.javascript.JSObject class
+    // These are in separate class as we lazily initialize these
+    // method handles when we hit a subclass of JSObject first time.
+    static class JSObjectHandles {
+        // method handles of JSObject class
+        static final MethodHandle JSOBJECT_GETMEMBER     = findJSObjectMH_V("getMember", Object.class, String.class).asType(MH.type(Object.class, Object.class, String.class));
+        static final MethodHandle JSOBJECT_GETSLOT       = findJSObjectMH_V("getSlot", Object.class, int.class).asType(MH.type(Object.class, Object.class, int.class));
+        static final MethodHandle JSOBJECT_SETMEMBER     = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class).asType(MH.type(Void.TYPE, Object.class, String.class, Object.class));
+        static final MethodHandle JSOBJECT_SETSLOT       = findJSObjectMH_V("setSlot", Void.TYPE, int.class, Object.class).asType(MH.type(Void.TYPE, Object.class, int.class, Object.class));
+
+        private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+            checkJSObjectClass();
+            return MH.findVirtual(MethodHandles.publicLookup(), jsObjectClass, name, MH.type(rtype, types));
+        }
+    }
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
index b139da1..6a3d933 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/ClassAndLoader.java
@@ -75,7 +75,7 @@
         return representativeClass;
     }
 
-    boolean canSee(ClassAndLoader other) {
+    boolean canSee(final ClassAndLoader other) {
         try {
             final Class<?> otherClass = other.getRepresentativeClass();
             return Class.forName(otherClass.getName(), false, getLoader()) == otherClass;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
index e6d13c2..19fe6bd 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/InvokeByName.java
@@ -90,7 +90,7 @@
         if(plength == 0) {
             finalPtypes = new Class<?>[] { Object.class, targetClass };
         } else {
-            finalPtypes = new Class[plength + 2];
+            finalPtypes = new Class<?>[plength + 2];
             finalPtypes[0] = Object.class;
             finalPtypes[1] = targetClass;
             System.arraycopy(ptypes, 0, finalPtypes, 2, plength);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
index 52fb46b..67c8e4b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java
@@ -81,7 +81,7 @@
 
         final GuardedInvocation inv;
         if (self instanceof JSObject) {
-            inv = lookup(desc);
+            inv = lookup(desc, request, linkerServices);
         } else if (self instanceof Map || self instanceof Bindings) {
             // guard to make sure the Map or Bindings does not turn into JSObject later!
             final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
@@ -91,7 +91,7 @@
             throw new AssertionError(); // Should never reach here.
         }
 
-        return Bootstrap.asType(inv, linkerServices, desc);
+        return Bootstrap.asTypeSafeReturn(inv, linkerServices, desc);
     }
 
     @Override
@@ -110,14 +110,22 @@
     }
 
 
-    private static GuardedInvocation lookup(final CallSiteDescriptor desc) {
+    private GuardedInvocation lookup(final CallSiteDescriptor desc, final LinkRequest request, final LinkerServices linkerServices) throws Exception {
         final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
         final int c = desc.getNameTokenCount();
+
         switch (operator) {
             case "getProp":
             case "getElem":
             case "getMethod":
-                return c > 2 ? findGetMethod(desc) : findGetIndexMethod();
+                if (c > 2) {
+                    return findGetMethod(desc);
+                } else {
+                    // For indexed get, we want get GuardedInvocation beans linker and pass it.
+                    // JSObjectLinker.get uses this fallback getter for explicit signature method access.
+                    final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
+                    return findGetIndexMethod(beanInv);
+                }
             case "setProp":
             case "setElem":
                 return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
@@ -131,31 +139,37 @@
     }
 
     private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) {
-        final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, desc.getNameToken(2));
-        return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD);
+        final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
+        final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, name);
+        return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
     }
 
-    private static GuardedInvocation findGetIndexMethod() {
-        return new GuardedInvocation(JSOBJECTLINKER_GET, null, IS_JSOBJECT_GUARD);
+    private static GuardedInvocation findGetIndexMethod(final GuardedInvocation inv) {
+        final MethodHandle getter = MH.insertArguments(JSOBJECTLINKER_GET, 0, inv.getInvocation());
+        return inv.replaceMethods(getter, inv.getGuard());
     }
 
     private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) {
         final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2));
-        return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD);
+        return new GuardedInvocation(getter, IS_JSOBJECT_GUARD);
     }
 
     private static GuardedInvocation findSetIndexMethod() {
-        return new GuardedInvocation(JSOBJECTLINKER_PUT, null, IS_JSOBJECT_GUARD);
+        return new GuardedInvocation(JSOBJECTLINKER_PUT, IS_JSOBJECT_GUARD);
     }
 
     private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc) {
-        final MethodHandle func = MH.asCollector(JSOBJECT_CALL, Object[].class, desc.getMethodType().parameterCount() - 2);
-        return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD);
+        // TODO: if call site is already a vararg, don't do asCollector
+        MethodHandle mh = JSOBJECT_CALL;
+        if (NashornCallSiteDescriptor.isApplyToCall(desc)) {
+            mh = MH.insertArguments(JSOBJECT_CALL_TO_APPLY, 0, JSOBJECT_CALL);
+        }
+        return new GuardedInvocation(MH.asCollector(mh, Object[].class, desc.getMethodType().parameterCount() - 2), IS_JSOBJECT_GUARD);
     }
 
     private static GuardedInvocation findNewMethod(final CallSiteDescriptor desc) {
         final MethodHandle func = MH.asCollector(JSOBJECT_NEW, Object[].class, desc.getMethodType().parameterCount() - 1);
-        return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD);
+        return new GuardedInvocation(func, IS_JSOBJECT_GUARD);
     }
 
     @SuppressWarnings("unused")
@@ -164,7 +178,8 @@
     }
 
     @SuppressWarnings("unused")
-    private static Object get(final Object jsobj, final Object key) {
+    private static Object get(final MethodHandle fallback, final Object jsobj, final Object key)
+        throws Throwable {
         if (key instanceof Integer) {
             return ((JSObject)jsobj).getSlot((Integer)key);
         } else if (key instanceof Number) {
@@ -173,7 +188,13 @@
                 return ((JSObject)jsobj).getSlot(index);
             }
         } else if (key instanceof String) {
-            return ((JSObject)jsobj).getMember((String)key);
+            final String name = (String)key;
+            // get with method name and signature. delegate it to beans linker!
+            if (name.indexOf('(') != -1) {
+                return fallback.invokeExact(jsobj, key);
+            } else {
+                return ((JSObject)jsobj).getMember(name);
+            }
         }
         return null;
     }
@@ -195,8 +216,8 @@
     }
 
     @SuppressWarnings("unused")
-    private static long toInt64(final JSObject obj) {
-        return JSType.toInt64(toNumber(obj));
+    private static long toLong(final JSObject obj) {
+        return JSType.toLong(toNumber(obj));
     }
 
     private static double toNumber(final JSObject obj) {
@@ -213,41 +234,48 @@
         return JSType.isRepresentableAsInt(value) ? (int)value : -1;
     }
 
+    @SuppressWarnings("unused")
+    private static Object callToApply(final MethodHandle mh, final JSObject obj, final Object thiz, final Object... args) {
+        assert args.length >= 2;
+        final Object   receiver  = args[0];
+        final Object[] arguments = new Object[args.length - 1];
+        System.arraycopy(args, 1, arguments, 0, arguments.length);
+        try {
+            return mh.invokeExact(obj, thiz, new Object[] { receiver, arguments });
+        } catch (final RuntimeException | Error e) {
+            throw e;
+        } catch (final Throwable e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality();
 
     // method handles of the current class
-    private static final MethodHandle IS_JSOBJECT_GUARD  = findOwnMH("isJSObject", boolean.class, Object.class);
-    private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH("get", Object.class, Object.class, Object.class);
-    private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH("put", Void.TYPE, Object.class, Object.class, Object.class);
+    private static final MethodHandle IS_JSOBJECT_GUARD  = findOwnMH_S("isJSObject", boolean.class, Object.class);
+    private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH_S("get", Object.class, MethodHandle.class, Object.class, Object.class);
+    private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH_S("put", Void.TYPE, Object.class, Object.class, Object.class);
 
     // method handles of JSObject class
-    private static final MethodHandle JSOBJECT_GETMEMBER  = findJSObjectMH("getMember", Object.class, String.class);
-    private static final MethodHandle JSOBJECT_SETMEMBER  = findJSObjectMH("setMember", Void.TYPE, String.class, Object.class);
-    private static final MethodHandle JSOBJECT_CALL       = findJSObjectMH("call", Object.class, Object.class, Object[].class);
-    private static final MethodHandle JSOBJECT_NEW        = findJSObjectMH("newObject", Object.class, Object[].class);
+    private static final MethodHandle JSOBJECT_GETMEMBER     = findJSObjectMH_V("getMember", Object.class, String.class);
+    private static final MethodHandle JSOBJECT_SETMEMBER     = findJSObjectMH_V("setMember", Void.TYPE, String.class, Object.class);
+    private static final MethodHandle JSOBJECT_CALL          = findJSObjectMH_V("call", Object.class, Object.class, Object[].class);
+    private static final MethodHandle JSOBJECT_CALL_TO_APPLY = findOwnMH_S("callToApply", Object.class, MethodHandle.class, JSObject.class, Object.class, Object[].class);
+    private static final MethodHandle JSOBJECT_NEW           = findJSObjectMH_V("newObject", Object.class, Object[].class);
 
     private static final Map<Class<?>, MethodHandle> CONVERTERS = new HashMap<>();
     static {
-        CONVERTERS.put(boolean.class, findOwnMH("toBoolean", boolean.class, JSObject.class));
-        CONVERTERS.put(int.class, findOwnMH("toInt32", int.class, JSObject.class));
-        CONVERTERS.put(long.class, findOwnMH("toInt64", long.class, JSObject.class));
-        CONVERTERS.put(double.class, findOwnMH("toNumber", double.class, JSObject.class));
+        CONVERTERS.put(boolean.class, findOwnMH_S("toBoolean", boolean.class, JSObject.class));
+        CONVERTERS.put(int.class,     findOwnMH_S("toInt32", int.class, JSObject.class));
+        CONVERTERS.put(long.class,    findOwnMH_S("toLong", long.class, JSObject.class));
+        CONVERTERS.put(double.class,  findOwnMH_S("toNumber", double.class, JSObject.class));
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        return findMH(name, JSObjectLinker.class, rtype, types);
+    private static MethodHandle findJSObjectMH_V(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findVirtual(MethodHandles.lookup(), JSObject.class, name, MH.type(rtype, types));
     }
 
-    private static MethodHandle findJSObjectMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        return findMH(name, JSObject.class, rtype, types);
-    }
-
-    private static MethodHandle findMH(final String name, final Class<?> target, final Class<?> rtype, final Class<?>... types) {
-        final MethodType mt  = MH.type(rtype, types);
-        try {
-            return MH.findStatic(MethodHandles.lookup(), target, name, mt);
-        } catch (final MethodHandleFactory.LookupException e) {
-            return MH.findVirtual(MethodHandles.lookup(), target, name, mt);
-        }
+    private static MethodHandle findOwnMH_S(final String name, final Class<?> rtype, final Class<?>... types) {
+        return MH.findStatic(MethodHandles.lookup(), JSObjectLinker.class, name, MH.type(rtype, types));
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
index 6b3acf6..44ea184 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterBytecodeGenerator.java
@@ -56,7 +56,9 @@
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 import jdk.internal.org.objectweb.asm.ClassWriter;
 import jdk.internal.org.objectweb.asm.Handle;
@@ -64,7 +66,9 @@
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
 import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
+import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
 import jdk.nashorn.internal.runtime.linker.AdaptationResult.Outcome;
@@ -131,9 +135,12 @@
  * implemented securely.
  */
 final class JavaAdapterBytecodeGenerator {
-    static final Type OBJECT_TYPE = Type.getType(Object.class);
+    private static final Type SCRIPTUTILS_TYPE = Type.getType(ScriptUtils.class);
+    private static final Type OBJECT_TYPE = Type.getType(Object.class);
+    private static final Type CLASS_TYPE  = Type.getType(Class.class);
 
     static final String OBJECT_TYPE_NAME  = OBJECT_TYPE.getInternalName();
+    static final String SCRIPTUTILS_TYPE_NAME  = SCRIPTUTILS_TYPE.getInternalName();
 
     static final String INIT = "<init>";
 
@@ -166,7 +173,12 @@
 
     private static final String METHOD_HANDLE_TYPE_DESCRIPTOR = METHOD_HANDLE_TYPE.getDescriptor();
     private static final String GET_GLOBAL_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE);
-    private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.getType(Class.class));
+    private static final String GET_CLASS_METHOD_DESCRIPTOR = Type.getMethodDescriptor(CLASS_TYPE);
+    private static final String EXPORT_RETURN_VALUE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE);
+    private static final String UNWRAP_METHOD_DESCRIPTOR = Type.getMethodDescriptor(OBJECT_TYPE, OBJECT_TYPE);
+    private static final String GET_CONVERTER_METHOD_DESCRIPTOR = Type.getMethodDescriptor(METHOD_HANDLE_TYPE, CLASS_TYPE);
+    private static final String TO_CHAR_PRIMITIVE_METHOD_DESCRIPTOR = Type.getMethodDescriptor(Type.CHAR_TYPE, OBJECT_TYPE);
+    private static final String TO_STRING_METHOD_DESCRIPTOR = Type.getMethodDescriptor(STRING_TYPE, OBJECT_TYPE);
 
     // Package used when the adapter can't be defined in the adaptee's package (either because it's sealed, or because
     // it's a java.* package.
@@ -177,6 +189,7 @@
     private static final int MAX_GENERATED_TYPE_NAME_LENGTH = 255;
 
     private static final String CLASS_INIT = "<clinit>";
+    static final String CONVERTER_INIT = "<converter-init>";
 
     // Method name prefix for invoking super-methods
     static final String SUPER_PREFIX = "super$";
@@ -206,6 +219,22 @@
     private boolean autoConvertibleFromFunction = false;
     private boolean hasExplicitFinalizer = false;
 
+    /**
+     * Names of static fields holding type converter method handles for return value conversion. We are emitting code
+     * for invoking these explicitly after the delegate handle is invoked, instead of doing an asType or
+     * filterReturnValue on the delegate handle, as that would create a new converter handle wrapping the function's
+     * handle for every instance of the adapter, causing the handle.invokeExact() call sites to become megamorphic.
+     */
+    private final Map<Class<?>, String> converterFields = new LinkedHashMap<>();
+
+    /**
+     * Subset of possible return types for all methods; namely, all possible return types of the SAM methods (we
+     * identify SAM types by having all of their abstract methods share a single name, so there can be multiple
+     * overloads with multiple return types. We use this set when emitting the constructor taking a ScriptFunction (the
+     * SAM initializer) to avoid populating converter fields that will never be used by SAM methods.
+     */
+    private final Set<Class<?>> samReturnTypes = new HashSet<>();
+
     private final ClassWriter cw;
 
     /**
@@ -243,6 +272,7 @@
         gatherMethods(interfaces);
         samName = abstractMethodNames.size() == 1 ? abstractMethodNames.iterator().next() : null;
         generateHandleFields();
+        generateConverterFields();
         if(classOverride) {
             generateClassInit();
         }
@@ -315,6 +345,24 @@
         }
     }
 
+    private void generateConverterFields() {
+        final int flags = ACC_PRIVATE | ACC_FINAL | (classOverride ? ACC_STATIC : 0);
+        for (final MethodInfo mi: methodInfos) {
+            final Class<?> returnType = mi.type.returnType();
+            // Handle primitive types, Object, and String specially
+            if(!returnType.isPrimitive() && returnType != Object.class && returnType != String.class) {
+                if(!converterFields.containsKey(returnType)) {
+                    final String name = nextName("convert");
+                    converterFields.put(returnType, name);
+                    if(mi.getName().equals(samName)) {
+                        samReturnTypes.add(returnType);
+                    }
+                    cw.visitField(flags, name, METHOD_HANDLE_TYPE_DESCRIPTOR, null, null).visitEnd();
+                }
+            }
+        }
+    }
+
     private void generateClassInit() {
         final InstructionAdapter mv = new InstructionAdapter(cw.visitMethod(ACC_STATIC, CLASS_INIT,
                 Type.getMethodDescriptor(Type.VOID_TYPE), null, null));
@@ -334,8 +382,7 @@
             for (final MethodInfo mi : methodInfos) {
                 if(mi.getName().equals(samName)) {
                     mv.dup();
-                    mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
-                    mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_FUNCTION_DESCRIPTOR, false);
+                    loadMethodTypeAndGetHandle(mv, mi, GET_HANDLE_FUNCTION_DESCRIPTOR);
                 } else {
                     mv.visitInsn(ACONST_NULL);
                 }
@@ -351,8 +398,7 @@
         for (final MethodInfo mi : methodInfos) {
             mv.dup();
             mv.aconst(mi.getName());
-            mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
-            mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", GET_HANDLE_OBJECT_DESCRIPTOR, false);
+            loadMethodTypeAndGetHandle(mv, mi, GET_HANDLE_OBJECT_DESCRIPTOR);
             mv.putstatic(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
         }
 
@@ -363,9 +409,41 @@
         invokeGetGlobalWithNullCheck(mv);
         mv.putstatic(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
 
+        generateConverterInit(mv, false);
         endInitMethod(mv);
     }
 
+    private void generateConverterInit(final InstructionAdapter mv, final boolean samOnly) {
+        assert !samOnly || !classOverride;
+        for(final Map.Entry<Class<?>, String> converterField: converterFields.entrySet()) {
+            final Class<?> returnType = converterField.getKey();
+            if(!classOverride) {
+                mv.visitVarInsn(ALOAD, 0);
+            }
+
+            if(samOnly && !samReturnTypes.contains(returnType)) {
+                mv.visitInsn(ACONST_NULL);
+            } else {
+                mv.aconst(Type.getType(converterField.getKey()));
+                mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getObjectConverter", GET_CONVERTER_METHOD_DESCRIPTOR, false);
+            }
+
+            if(classOverride) {
+                mv.putstatic(generatedClassName, converterField.getValue(), METHOD_HANDLE_TYPE_DESCRIPTOR);
+            } else {
+                mv.putfield(generatedClassName, converterField.getValue(), METHOD_HANDLE_TYPE_DESCRIPTOR);
+            }
+        }
+    }
+
+    private static void loadMethodTypeAndGetHandle(final InstructionAdapter mv, final MethodInfo mi, final String getHandleDescriptor) {
+        // NOTE: we're using generic() here because we'll be linking to the "generic" invoker version of
+        // the functions anyway, so we cut down on megamorphism in the invokeExact() calls in adapter
+        // bodies. Once we start linking to type-specializing invokers, this should be changed.
+        mv.aconst(Type.getMethodType(mi.type.generic().toMethodDescriptorString()));
+        mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
+    }
+
     private static void invokeGetGlobalWithNullCheck(final InstructionAdapter mv) {
         invokeGetGlobal(mv);
         mv.dup();
@@ -422,7 +500,7 @@
         // Invoke super constructor with the same arguments.
         mv.visitVarInsn(ALOAD, 0);
         int offset = 1; // First arg is at position 1, after this.
-        for (Type argType: argTypes) {
+        for (final Type argType: argTypes) {
             mv.load(offset, argType);
             offset += argType.getSize();
         }
@@ -497,8 +575,7 @@
                 if(!fromFunction) {
                     mv.aconst(mi.getName());
                 }
-                mv.aconst(Type.getMethodType(mi.type.toMethodDescriptorString()));
-                mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "getHandle", getHandleDescriptor, false);
+                loadMethodTypeAndGetHandle(mv, mi, getHandleDescriptor);
             }
             mv.putfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
         }
@@ -508,6 +585,8 @@
         invokeGetGlobalWithNullCheck(mv);
         mv.putfield(generatedClassName, GLOBAL_FIELD_NAME, GLOBAL_TYPE_DESCRIPTOR);
 
+        // Initialize converters
+        generateConverterInit(mv, fromFunction);
         endInitMethod(mv);
     }
 
@@ -622,7 +701,8 @@
 
         final Label handleDefined = new Label();
 
-        final Type asmReturnType = Type.getType(type.returnType());
+        final Class<?> returnType = type.returnType();
+        final Type asmReturnType = Type.getType(returnType);
 
         // See if we have overriding method handle defined
         if(classOverride) {
@@ -632,7 +712,8 @@
             mv.getfield(generatedClassName, mi.methodHandleFieldName, METHOD_HANDLE_TYPE_DESCRIPTOR);
         }
         // stack: [handle]
-        jumpIfNonNullKeepOperand(mv, handleDefined);
+        mv.visitInsn(DUP);
+        mv.visitJumpInsn(IFNONNULL, handleDefined);
 
         // No handle is available, fall back to default behavior
         if(Modifier.isAbstract(method.getModifiers())) {
@@ -642,6 +723,7 @@
             mv.invokespecial(UNSUPPORTED_OPERATION_TYPE_NAME, INIT, VOID_NOARG_METHOD_DESCRIPTOR, false);
             mv.athrow();
         } else {
+            mv.visitInsn(POP);
             // If the super method is not abstract, delegate to it.
             emitSuperCall(mv, method.getDeclaringClass(), name, methodDesc);
         }
@@ -703,17 +785,20 @@
         mv.visitVarInsn(ISTORE, globalsDifferVar);
         // stack: [handle]
 
-        // Load all parameters back on stack for dynamic invocation.
+        // Load all parameters back on stack for dynamic invocation. NOTE: since we're using a generic
+        // Object(Object, Object, ...) type signature for the method, we must box all arguments here.
         int varOffset = 1;
         for (final Type t : asmArgTypes) {
             mv.load(varOffset, t);
+            boxStackTop(mv, t);
             varOffset += t.getSize();
         }
 
         // Invoke the target method handle
         final Label tryBlockStart = new Label();
         mv.visitLabel(tryBlockStart);
-        mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
+        emitInvokeExact(mv, type.generic());
+        convertReturnValue(mv, returnType, asmReturnType);
         final Label tryBlockEnd = new Label();
         mv.visitLabel(tryBlockEnd);
         emitFinally(mv, currentGlobalVar, globalsDifferVar);
@@ -743,7 +828,7 @@
         mv.visitLabel(methodEnd);
 
         mv.visitLocalVariable("currentGlobal", GLOBAL_TYPE_DESCRIPTOR, null, setupGlobal, methodEnd, currentGlobalVar);
-        mv.visitLocalVariable("globalsDiffer", Type.INT_TYPE.getDescriptor(), null, setupGlobal, methodEnd, globalsDifferVar);
+        mv.visitLocalVariable("globalsDiffer", Type.BOOLEAN_TYPE.getDescriptor(), null, setupGlobal, methodEnd, globalsDifferVar);
 
         if(throwableDeclared) {
             mv.visitTryCatchBlock(tryBlockStart, tryBlockEnd, rethrowHandler, THROWABLE_TYPE_NAME);
@@ -759,16 +844,110 @@
         endMethod(mv);
     }
 
-    /**
-     * Emits code for jumping to a label if the top stack operand is not null. The operand is kept on the stack if it
-     * is not null (so is available to code at the jump address) and is popped if it is null.
-     * @param mv the instruction adapter being used to emit code
-     * @param label the label to jump to
-     */
-    private static void jumpIfNonNullKeepOperand(final InstructionAdapter mv, final Label label) {
-        mv.visitInsn(DUP);
-        mv.visitJumpInsn(IFNONNULL, label);
-        mv.visitInsn(POP);
+    private void convertReturnValue(final InstructionAdapter mv, final Class<?> returnType, final Type asmReturnType) {
+        switch(asmReturnType.getSort()) {
+        case Type.VOID:
+            mv.pop();
+            break;
+        case Type.BOOLEAN:
+            JSType.TO_BOOLEAN.invoke(mv);
+            break;
+        case Type.BYTE:
+            JSType.TO_INT32.invoke(mv);
+            mv.visitInsn(Opcodes.I2B);
+            break;
+        case Type.SHORT:
+            JSType.TO_INT32.invoke(mv);
+            mv.visitInsn(Opcodes.I2S);
+            break;
+        case Type.CHAR:
+            // JSType doesn't have a TO_CHAR, so we have services supply us one.
+            mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "toCharPrimitive", TO_CHAR_PRIMITIVE_METHOD_DESCRIPTOR, false);
+            break;
+        case Type.INT:
+            JSType.TO_INT32.invoke(mv);
+            break;
+        case Type.LONG:
+            JSType.TO_LONG.invoke(mv);
+            break;
+        case Type.FLOAT:
+            JSType.TO_NUMBER.invoke(mv);
+            mv.visitInsn(Opcodes.D2F);
+            break;
+        case Type.DOUBLE:
+            JSType.TO_NUMBER.invoke(mv);
+            break;
+        default:
+            if(asmReturnType.equals(OBJECT_TYPE)) {
+                // Must hide ConsString (and potentially other internal Nashorn types) from callers
+                mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "exportReturnValue", EXPORT_RETURN_VALUE_METHOD_DESCRIPTOR, false);
+            } else if(asmReturnType.equals(STRING_TYPE)){
+                // Well-known conversion to String. Not using the JSType one as we want to preserve null as null instead
+                // of the string "n,u,l,l".
+                mv.invokestatic(SERVICES_CLASS_TYPE_NAME, "toString", TO_STRING_METHOD_DESCRIPTOR, false);
+            } else {
+                // Invoke converter method handle for everything else. Note that we could have just added an asType or
+                // filterReturnValue to the invoked handle instead, but then every instance would have the function
+                // method handle wrapped in a separate converter method handle, making handle.invokeExact() megamorphic.
+                if(classOverride) {
+                    mv.getstatic(generatedClassName, converterFields.get(returnType), METHOD_HANDLE_TYPE_DESCRIPTOR);
+                } else {
+                    mv.visitVarInsn(ALOAD, 0);
+                    mv.getfield(generatedClassName, converterFields.get(returnType), METHOD_HANDLE_TYPE_DESCRIPTOR);
+                }
+                mv.swap();
+                emitInvokeExact(mv, MethodType.methodType(returnType, Object.class));
+            }
+        }
+    }
+
+    private static void emitInvokeExact(final InstructionAdapter mv, final MethodType type) {
+        mv.invokevirtual(METHOD_HANDLE_TYPE.getInternalName(), "invokeExact", type.toMethodDescriptorString(), false);
+    }
+
+    private static void boxStackTop(final InstructionAdapter mv, final Type t) {
+        switch(t.getSort()) {
+        case Type.BOOLEAN:
+            invokeValueOf(mv, "Boolean", 'Z');
+            break;
+        case Type.BYTE:
+        case Type.SHORT:
+        case Type.INT:
+            // bytes and shorts get boxed as integers
+            invokeValueOf(mv, "Integer", 'I');
+            break;
+        case Type.CHAR:
+            invokeValueOf(mv, "Character", 'C');
+            break;
+        case Type.FLOAT:
+            // floats get boxed as doubles
+            mv.visitInsn(Opcodes.F2D);
+            invokeValueOf(mv, "Double", 'D');
+            break;
+        case Type.LONG:
+            invokeValueOf(mv, "Long", 'J');
+            break;
+        case Type.DOUBLE:
+            invokeValueOf(mv, "Double", 'D');
+            break;
+        case Type.ARRAY:
+        case Type.METHOD:
+            // Already boxed
+            break;
+        case Type.OBJECT:
+            if(t.equals(OBJECT_TYPE)) {
+                mv.invokestatic(SCRIPTUTILS_TYPE_NAME, "unwrap", UNWRAP_METHOD_DESCRIPTOR, false);
+            }
+            break;
+        default:
+            // Not expecting anything else (e.g. VOID)
+            assert false;
+            break;
+        }
+    }
+
+    private static void invokeValueOf(final InstructionAdapter mv, final String boxedType, final char unboxedType) {
+        mv.invokestatic("java/lang/" + boxedType, "valueOf", "(" + unboxedType + ")Ljava/lang/" + boxedType + ";", false);
     }
 
     /**
@@ -805,7 +984,7 @@
         }
     }
 
-    private void generateSuperMethod(MethodInfo mi) {
+    private void generateSuperMethod(final MethodInfo mi) {
         final Method method = mi.method;
 
         final String methodDesc = mi.type.toMethodDescriptorString();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
index 879d908..f5ba8b1 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterClassLoader.java
@@ -30,8 +30,14 @@
 import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.security.SecureClassLoader;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import jdk.internal.dynalink.beans.StaticClass;
+import jdk.nashorn.internal.codegen.DumpBytecode;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 
 /**
@@ -39,16 +45,18 @@
  * It can be invoked repeatedly to create multiple adapter classes from the same bytecode; adapter classes that have
  * class-level overrides must be re-created for every set of such overrides. Note that while this class is named
  * "class loader", it does not, in fact, extend {@code ClassLoader}, but rather uses them internally. Instances of this
- * class are normally created by {@link JavaAdapterBytecodeGenerator}.
+ * class are normally created by {@code JavaAdapterBytecodeGenerator}.
  */
-@SuppressWarnings("javadoc")
 final class JavaAdapterClassLoader {
     private static final AccessControlContext CREATE_LOADER_ACC_CTXT = ClassAndLoader.createPermAccCtxt("createClassLoader");
+    private static final AccessControlContext GET_CONTEXT_ACC_CTXT = ClassAndLoader.createPermAccCtxt(Context.NASHORN_GET_CONTEXT);
+    private static final Collection<String> VISIBLE_INTERNAL_CLASS_NAMES = Collections.unmodifiableCollection(new HashSet<>(
+            Arrays.asList(JavaAdapterServices.class.getName(), ScriptFunction.class.getName(), JSType.class.getName())));
 
     private final String className;
     private final byte[] classBytes;
 
-    JavaAdapterClassLoader(String className, byte[] classBytes) {
+    JavaAdapterClassLoader(final String className, final byte[] classBytes) {
         this.className = className.replace('/', '.');
         this.classBytes = classBytes;
     }
@@ -94,7 +102,7 @@
                     // loaded by a loader that prevents package.access. If so, it'd throw
                     // SecurityException for nashorn's classes!. For adapter's to work, we
                     // should be able to refer to the few classes it needs in its implementation.
-                    if(ScriptFunction.class.getName().equals(name) || JavaAdapterServices.class.getName().equals(name)) {
+                    if(VISIBLE_INTERNAL_CLASS_NAMES.contains(name)) {
                         return myLoader.loadClass(name);
                     }
                     throw se;
@@ -105,6 +113,14 @@
             protected Class<?> findClass(final String name) throws ClassNotFoundException {
                 if(name.equals(className)) {
                     assert classBytes != null : "what? already cleared .class bytes!!";
+
+                    final Context ctx = AccessController.doPrivileged(new PrivilegedAction<Context>() {
+                        @Override
+                        public Context run() {
+                            return Context.getContext();
+                        }
+                    }, GET_CONTEXT_ACC_CTXT);
+                    DumpBytecode.dumpBytecode(ctx.getEnv(), ctx.getLogger(jdk.nashorn.internal.codegen.Compiler.class), classBytes, name);
                     return defineClass(name, classBytes, 0, classBytes.length, protectionDomain);
                 }
                 throw new ClassNotFoundException(name);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
index 1b5345b..40ea01a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterFactory.java
@@ -113,15 +113,15 @@
      * @throws ECMAException with a TypeError if the adapter class can not be generated because the original class is
      * final, non-public, or has no public or protected constructors.
      */
-    public static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
+    public static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final MethodHandles.Lookup lookup) {
         return getAdapterClassFor(types, classOverrides, getProtectionDomain(lookup));
     }
 
-    private static StaticClass getAdapterClassFor(final Class<?>[] types, ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
+    private static StaticClass getAdapterClassFor(final Class<?>[] types, final ScriptObject classOverrides, final ProtectionDomain protectionDomain) {
         assert types != null && types.length > 0;
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
-            for (Class<?> type : types) {
+            for (final Class<?> type : types) {
                 // check for restricted package access
                 Context.checkPackageAccess(type);
                 // check for classes, interfaces in reflection
@@ -163,7 +163,7 @@
         final StaticClass adapterClass = getAdapterClassFor(new Class<?>[] { targetType }, null, lookup);
         return MH.bindTo(Bootstrap.getLinkerServices().getGuardedInvocation(new LinkRequestImpl(
                 NashornCallSiteDescriptor.get(lookup, "dyn:new",
-                        MethodType.methodType(targetType, StaticClass.class, sourceType), 0), false,
+                        MethodType.methodType(targetType, StaticClass.class, sourceType), 0), null, 0, false,
                         adapterClass, null)).getInvocation(), adapterClass);
     }
 
@@ -257,7 +257,7 @@
         final boolean autoConvertibleFromFunction;
         final AdaptationResult adaptationResult;
 
-        AdapterInfo(Class<?> superClass, List<Class<?>> interfaces, ClassAndLoader definingLoader) throws AdaptationException {
+        AdapterInfo(final Class<?> superClass, final List<Class<?>> interfaces, final ClassAndLoader definingLoader) throws AdaptationException {
             this.commonLoader = findCommonLoader(definingLoader);
             final JavaAdapterBytecodeGenerator gen = new JavaAdapterBytecodeGenerator(superClass, interfaces, commonLoader, false);
             this.autoConvertibleFromFunction = gen.isAutoConvertibleFromFunction();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
index 4cb8cfa..ef91f35 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaAdapterServices.java
@@ -47,6 +47,7 @@
 import jdk.internal.org.objectweb.asm.Opcodes;
 import jdk.internal.org.objectweb.asm.Type;
 import jdk.internal.org.objectweb.asm.commons.InstructionAdapter;
+import jdk.nashorn.api.scripting.ScriptUtils;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -150,7 +151,7 @@
         return Context.getGlobal();
     }
 
-    static void setClassOverrides(ScriptObject overrides) {
+    static void setClassOverrides(final ScriptObject overrides) {
         classOverrides.set(overrides);
     }
 
@@ -183,7 +184,7 @@
             public ClassLoader run() {
                 return new SecureClassLoader(null) {
                     @Override
-                    protected Class<?> findClass(String name) throws ClassNotFoundException {
+                    protected Class<?> findClass(final String name) throws ClassNotFoundException {
                         if(name.equals(className)) {
                             return defineClass(name, bytes, 0, bytes.length, new ProtectionDomain(
                                     new CodeSource(null, (CodeSigner[])null), new Permissions()));
@@ -197,8 +198,49 @@
         try {
             return MethodHandles.lookup().findStatic(Class.forName(className, true, loader), "invoke",
                     MethodType.methodType(void.class, MethodHandle.class, Object.class));
-        } catch(ReflectiveOperationException e) {
+        } catch(final ReflectiveOperationException e) {
             throw new AssertionError(e.getMessage(), e);
         }
     }
+
+    /**
+     * Returns a method handle used to convert a return value from a delegate method (always Object) to the expected
+     * Java return type.
+     * @param returnType the return type
+     * @return the converter for the expected return type
+     */
+    public static MethodHandle getObjectConverter(final Class<?> returnType) {
+        return Bootstrap.getLinkerServices().getTypeConverter(Object.class, returnType);
+    }
+
+    /**
+     * Invoked when returning Object from an adapted method to filter out internal Nashorn objects that must not be seen
+     * by the callers. Currently only transforms {@code ConsString} into {@code String} and transforms {@code ScriptObject} into {@code ScriptObjectMirror}.
+     * @param obj the return value
+     * @return the filtered return value.
+     */
+    public static Object exportReturnValue(final Object obj) {
+        return ScriptUtils.wrap(NashornBeansLinker.exportArgument(obj));
+    }
+
+    /**
+     * Invoked to convert a return value of a delegate function to primitive char. There's no suitable conversion in
+     * {@code JSType}, so we provide our own to adapters.
+     * @param obj the return value.
+     * @return the character value of the return value
+     */
+    public static char toCharPrimitive(final Object obj) {
+        return JavaArgumentConverters.toCharPrimitive(obj);
+    }
+
+    /**
+     * Invoked to convert a return value of a delegate function to String. It is similar to
+     * {@code JSType.toString(Object)}, except it doesn't handle StaticClass specially, and it returns null for null
+     * input instead of the string "null".
+     * @param obj the return value.
+     * @return the String value of the return value
+     */
+    public static String toString(final Object obj) {
+        return JavaArgumentConverters.toString(obj);
+    }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
index 984d0f4..8b085e4 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaArgumentConverters.java
@@ -124,34 +124,14 @@
         return s.charAt(0);
     }
 
-    @SuppressWarnings("unused")
-    private static char toCharPrimitive(final Object obj0) {
+    static char toCharPrimitive(final Object obj0) {
         final Character c = toChar(obj0);
         return c == null ? (char)0 : c;
     }
 
-    // Almost identical to ScriptRuntime.toString, but doesn't handle StaticClass specially, and it returns null for
-    // null instead of the string "null".
-    private static String toString(final Object obj0) {
-        for (Object obj = obj0; ;) {
-            if (obj == null) {
-                return null;
-            } else if (obj instanceof String) {
-                return (String) obj;
-            } else if (obj instanceof ConsString) {
-                return obj.toString();
-            } else if (obj instanceof Number) {
-                return JSType.toString(((Number)obj).doubleValue());
-            } else if (obj instanceof Boolean) {
-                return ((Boolean) obj).toString();
-            } else if (obj == UNDEFINED) {
-                return "undefined";
-            } else if (obj instanceof ScriptObject) {
-                obj = JSType.toPrimitive(obj, String.class);
-                continue;
-            }
-            throw assertUnexpectedType(obj);
-        }
+    // Almost identical to ScriptRuntime.toString, but returns null for null instead of the string "null".
+    static String toString(final Object obj) {
+        return obj == null ? null : JSType.toString(obj);
     }
 
     @SuppressWarnings("unused")
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
index a4af318..3c7fcb2 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapter.java
@@ -27,7 +27,7 @@
 
 /**
  * Represents a an adapter for invoking superclass methods on an adapter instance generated by
- * {@link JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
+ * {@code JavaAdapterBytecodeGenerator}. Note that objects of this class are just wrappers around the adapter instances,
  * without any behavior. All the behavior is defined in the {@code JavaSuperAdapterLinker}.
  */
 class JavaSuperAdapter {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
index c42af1d..5fc93cb 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JavaSuperAdapterLinker.java
@@ -42,7 +42,7 @@
 import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
- * A linker for instances of {@link JavaSuperAdapter}. Only links {@code getMethod} calls, by forwarding them to the
+ * A linker for instances of {@code JavaSuperAdapter}. Only links {@code getMethod} calls, by forwarding them to the
  * bean linker for the adapter class and prepending {@code super$} to method names.
  *
  */
@@ -115,15 +115,15 @@
 
         final MethodHandle invocation = guardedInv.getInvocation();
         final MethodType invType = invocation.type();
-        // For invocation typed R(T0, ...) create a dynamic method binder of type R(R, T0)
-        final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(invType.returnType(),
+        // For invocation typed R(T0, ...) create a dynamic method binder of type Object(R, T0)
+        final MethodHandle typedBinder = BIND_DYNAMIC_METHOD.asType(MethodType.methodType(Object.class,
                 invType.returnType(), invType.parameterType(0)));
-        // For invocation typed R(T0, T1, ...) create a dynamic method binder of type R(R, T0, T1, ...)
+        // For invocation typed R(T0, T1, ...) create a dynamic method binder of type Object(R, T0, T1, ...)
         final MethodHandle droppingBinder = MethodHandles.dropArguments(typedBinder, 2,
                 invType.parameterList().subList(1, invType.parameterCount()));
         // Finally, fold the invocation into the binder to produce a method handle that will bind every returned
         // DynamicMethod object from dyn:getMethod calls to the actual receiver
-        // R(R(T0, T1, ...), T0, T1, ...)
+        // Object(R(T0, T1, ...), T0, T1, ...)
         final MethodHandle bindingInvocation = MethodHandles.foldArguments(droppingBinder, invocation);
 
         final MethodHandle typedGetAdapter = asFilterType(GET_ADAPTER, 0, invType, type);
@@ -147,7 +147,7 @@
      * @param sourceType the source method type for filtering
      * @return a type adapted filter
      */
-    private static MethodHandle asFilterType(final MethodHandle filter, int pos, MethodType targetType, MethodType sourceType) {
+    private static MethodHandle asFilterType(final MethodHandle filter, final int pos, final MethodType targetType, final MethodType sourceType) {
         return filter.asType(MethodType.methodType(targetType.parameterType(pos), sourceType.parameterType(pos)));
     }
 
@@ -175,7 +175,7 @@
      * @return true if the receiver is a super adapter, and its underlying adapter is of the specified class
      */
     @SuppressWarnings("unused")
-    private static boolean isAdapterOfClass(Class<?> clazz, Object obj) {
+    private static boolean isAdapterOfClass(final Class<?> clazz, final Object obj) {
         return obj instanceof JavaSuperAdapter && clazz == (((JavaSuperAdapter)obj).getAdapter()).getClass();
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
index 882c65d..46324db 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/LinkerCallSite.java
@@ -46,7 +46,6 @@
 import jdk.internal.dynalink.ChainedCallSite;
 import jdk.internal.dynalink.DynamicLinker;
 import jdk.internal.dynalink.linker.GuardedInvocation;
-import jdk.nashorn.internal.lookup.MethodHandleFactory;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.Debug;
 import jdk.nashorn.internal.runtime.ScriptObject;
@@ -63,7 +62,10 @@
 
     private static final String PROFILEFILE = Options.getStringProperty("nashorn.profilefile", "NashornProfile.txt");
 
-    private static final MethodHandle INCREASE_MISS_COUNTER = findOwnMH("increaseMissCount", Object.class, String.class, Object.class);
+    private static final MethodHandle INCREASE_MISS_COUNTER = MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, "increaseMissCount", MH.type(Object.class, String.class, Object.class));
+    private static final MethodHandle ON_CATCH_INVALIDATION = MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, "onCatchInvalidation", MH.type(ChainedCallSite.class, LinkerCallSite.class));
+
+    private int catchInvalidations;
 
     LinkerCallSite(final NashornCallSiteDescriptor descriptor) {
         super(descriptor);
@@ -72,6 +74,34 @@
         }
     }
 
+    @Override
+    protected MethodHandle getPruneCatches() {
+        return MH.filterArguments(super.getPruneCatches(), 0, ON_CATCH_INVALIDATION);
+    }
+
+    /**
+     * Action to perform when a catch guard around a callsite triggers. Increases
+     * catch invalidation counter
+     * @param callSite callsite
+     * @return the callsite, so this can be used as argument filter
+     */
+    @SuppressWarnings("unused")
+    private static ChainedCallSite onCatchInvalidation(final LinkerCallSite callSite) {
+        ++callSite.catchInvalidations;
+        return callSite;
+    }
+
+    /**
+     * Get the number of catch invalidations that have happened at this call site so far
+     * @param callSiteToken call site token, unique to the callsite.
+     * @return number of catch invalidations, i.e. thrown exceptions caught by the linker
+     */
+    public static int getCatchInvalidationCount(final Object callSiteToken) {
+        if (callSiteToken instanceof LinkerCallSite) {
+            return ((LinkerCallSite)callSiteToken).catchInvalidations;
+        }
+        return 0;
+    }
     /**
      * Construct a new linker call site.
      * @param name     Name of method.
@@ -79,8 +109,7 @@
      * @param flags    Call site specific flags.
      * @return New LinkerCallSite.
      */
-    static LinkerCallSite newLinkerCallSite(final MethodHandles.Lookup lookup, final String name, final MethodType type,
-            final int flags) {
+    static LinkerCallSite newLinkerCallSite(final MethodHandles.Lookup lookup, final String name, final MethodType type, final int flags) {
         final NashornCallSiteDescriptor desc = NashornCallSiteDescriptor.get(lookup, name, type, flags);
 
         if (desc.isProfile()) {
@@ -145,11 +174,10 @@
      */
     public static Object increaseMissCount(final String desc, final Object self) {
         ++missCount;
-        if(r.nextInt(100) < missSamplingPercentage) {
-            AtomicInteger i = missCounts.get(desc);
-            if(i == null) {
-                i = new AtomicInteger(1);
-                missCounts.put(desc, i);
+        if (r.nextInt(100) < missSamplingPercentage) {
+            final AtomicInteger i = missCounts.get(desc);
+            if (i == null) {
+                missCounts.put(desc, new AtomicInteger(1));
             } else {
                 i.incrementAndGet();
             }
@@ -157,14 +185,6 @@
         return self;
     }
 
-    private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-        try {
-            return MH.findStatic(MethodHandles.lookup(), LinkerCallSite.class, name, MH.type(rtype, types));
-        } catch (final MethodHandleFactory.LookupException e) {
-            return MH.findVirtual(MethodHandles.lookup(), LinkerCallSite.class, name, MH.type(rtype, types));
-        }
-    }
-
     /*
      * Debugging call sites.
      */
@@ -276,7 +296,6 @@
         }
 
         static class ProfileDumper implements Runnable {
-            @SuppressWarnings("resource")
             @Override
             public void run() {
                 PrintWriter out    = null;
@@ -314,10 +333,11 @@
      * Debug subclass for LinkerCallSite that allows tracing
      */
     private static class TracingLinkerCallSite extends LinkerCallSite {
+        private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
 
-        private static final MethodHandle TRACEOBJECT = findOwnMH("traceObject", Object.class, MethodHandle.class, Object[].class);
-        private static final MethodHandle TRACEVOID   = findOwnMH("traceVoid", void.class, MethodHandle.class, Object[].class);
-        private static final MethodHandle TRACEMISS   = findOwnMH("traceMiss", void.class, String.class, Object[].class);
+        private static final MethodHandle TRACEOBJECT = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceObject", MH.type(Object.class, MethodHandle.class, Object[].class));
+        private static final MethodHandle TRACEVOID   = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceVoid", MH.type(void.class, MethodHandle.class, Object[].class));
+        private static final MethodHandle TRACEMISS   = MH.findVirtual(LOOKUP, TracingLinkerCallSite.class, "traceMiss", MH.type(void.class, String.class, Object[].class));
 
         TracingLinkerCallSite(final NashornCallSiteDescriptor desc) {
            super(desc);
@@ -420,7 +440,7 @@
                     final Object arg = args[i];
                     out.print(", ");
 
-                    if (getNashornDescriptor().isTraceScope() || !(arg instanceof ScriptObject && ((ScriptObject)arg).isScope())) {
+                    if (!(arg instanceof ScriptObject && ((ScriptObject)arg).isScope())) {
                         printObject(out, arg);
                     } else {
                         out.print("SCOPE");
@@ -448,7 +468,7 @@
          *
          * @throws Throwable if invocation fails or throws exception/error
          */
-        @SuppressWarnings({"unused", "resource"})
+        @SuppressWarnings("unused")
         public Object traceObject(final MethodHandle mh, final Object... args) throws Throwable {
             final PrintWriter out = Context.getCurrentErr();
             tracePrint(out, "ENTER ", args, null);
@@ -466,7 +486,7 @@
          *
          * @throws Throwable if invocation fails or throws exception/error
          */
-        @SuppressWarnings({"unused", "resource"})
+        @SuppressWarnings("unused")
         public void traceVoid(final MethodHandle mh, final Object... args) throws Throwable {
             final PrintWriter out = Context.getCurrentErr();
             tracePrint(out, "ENTER ", args, null);
@@ -486,14 +506,6 @@
         public void traceMiss(final String desc, final Object... args) throws Throwable {
             tracePrint(Context.getCurrentErr(), desc, args, null);
         }
-
-        private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
-            try {
-                return MH.findStatic(MethodHandles.lookup(), TracingLinkerCallSite.class, name, MH.type(rtype, types));
-            } catch (final MethodHandleFactory.LookupException e) {
-                return MH.findVirtual(MethodHandles.lookup(), TracingLinkerCallSite.class, name, MH.type(rtype, types));
-            }
-        }
     }
 
     // counters updated in debug mode
@@ -503,6 +515,11 @@
     private static final Random r = new Random();
     private static final int missSamplingPercentage = Options.getIntProperty("nashorn.tcs.miss.samplePercent", 1);
 
+    @Override
+    protected int getMaxChainLength() {
+        return 8;
+    }
+
     /**
      * Get the callsite count
      * @return the count
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
index e2db2b1..e6b8b90 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBeansLinker.java
@@ -67,8 +67,7 @@
         return delegateLinker.getGuardedInvocation(linkRequest, new NashornBeansLinkerServices(linkerServices));
     }
 
-    @SuppressWarnings("unused")
-    private static Object exportArgument(final Object arg) {
+    static Object exportArgument(final Object arg) {
         return arg instanceof ConsString ? arg.toString() : arg;
     }
 
@@ -100,6 +99,11 @@
             return filters != null ? MethodHandles.filterArguments(typed, 0, filters) : typed;
         }
 
+        @Override
+        public MethodHandle asTypeLosslessReturn(final MethodHandle handle, final MethodType fromType) {
+            return Implementation.asTypeLosslessReturn(this, handle, fromType);
+        }
+
         private static boolean shouldConvert(final Class<?> handleType, final Class<?> fromType) {
             return handleType == Object.class && fromType == Object.class;
         }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
index 88ccf5a..f859f7b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornBottomLinker.java
@@ -44,9 +44,11 @@
 import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.support.Guards;
+import jdk.nashorn.internal.codegen.types.Type;
 import jdk.nashorn.internal.runtime.Context;
 import jdk.nashorn.internal.runtime.JSType;
 import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.UnwarrantedOptimismException;
 
 /**
  * Nashorn bottom linker; used as a last-resort catch-all linker for all linking requests that fall through all other
@@ -104,10 +106,13 @@
                 if (callType.parameterCount() != m.getParameterCount() + 2) {
                     throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
                 }
-                return new GuardedInvocation(
+                return Bootstrap.asTypeSafeReturn(new GuardedInvocation(
                         // drop 'thiz' passed from the script.
                         MH.dropArguments(desc.getLookup().unreflect(m), 1, callType.parameterType(1)),
-                        Guards.getInstanceOfGuard(m.getDeclaringClass())).asType(callType);
+                        Guards.getInstanceOfGuard(m.getDeclaringClass())), linkerServices, desc);
+            }
+            if(BeansLinker.isDynamicConstructor(self)) {
+                throw typeError("constructor.requires.new", ScriptRuntime.safeToString(self));
             }
             if(BeansLinker.isDynamicMethod(self)) {
                 throw typeError("no.method.matches.args", ScriptRuntime.safeToString(self));
@@ -118,6 +123,9 @@
             throw typeError("no.such.function", getArgument(linkRequest), ScriptRuntime.safeToString(self));
         case "getProp":
         case "getElem":
+            if(NashornCallSiteDescriptor.isOptimistic(desc)) {
+                throw new UnwarrantedOptimismException(UNDEFINED, NashornCallSiteDescriptor.getProgramPoint(desc), Type.OBJECT);
+            }
             if (desc.getOperand() != null) {
                 return getInvocation(EMPTY_PROP_GETTER, self, linkerServices, desc);
             }
@@ -151,14 +159,14 @@
     private static GuardedInvocation convertToTypeNoCast(final Class<?> sourceType, final Class<?> targetType) throws Exception {
         final MethodHandle mh = CONVERTERS.get(targetType);
         if (mh != null) {
-            return new GuardedInvocation(mh, null);
+            return new GuardedInvocation(mh);
         }
 
         return null;
     }
 
     private static GuardedInvocation getInvocation(final MethodHandle handle, final Object self, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
-        return Bootstrap.asType(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc);
+        return Bootstrap.asTypeSafeReturn(new GuardedInvocation(handle, Guards.getClassGuard(self.getClass())), linkerServices, desc);
     }
 
     // Used solely in an assertion to figure out if the object we get here is something we in fact expect. Objects
@@ -218,7 +226,7 @@
                 return null;
             }
 
-            for (Class<?> iface : clazz.getInterfaces()) {
+            for (final Class<?> iface : clazz.getInterfaces()) {
                 // check accessiblity up-front
                 if (! Context.isAccessibleClass(iface)) {
                     continue;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
index 0c2c4d5..a4f6988 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornCallSiteDescriptor.java
@@ -33,6 +33,7 @@
 import jdk.internal.dynalink.CallSiteDescriptor;
 import jdk.internal.dynalink.support.AbstractCallSiteDescriptor;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.internal.ir.debug.NashornTextifier;
 
 /**
  * Nashorn-specific implementation of Dynalink's {@link CallSiteDescriptor}. The reason we have our own subclass is that
@@ -42,40 +43,61 @@
 public final class NashornCallSiteDescriptor extends AbstractCallSiteDescriptor {
     /** Flags that the call site references a scope variable (it's an identifier reference or a var declaration, not a
      * property access expression. */
-    public static final int CALLSITE_SCOPE                = 0x01;
+    public static final int CALLSITE_SCOPE         = 1 << 0;
     /** Flags that the call site is in code that uses ECMAScript strict mode. */
-    public static final int CALLSITE_STRICT               = 0x02;
+    public static final int CALLSITE_STRICT        = 1 << 1;
     /** Flags that a property getter or setter call site references a scope variable that is located at a known distance
      * in the scope chain. Such getters and setters can often be linked more optimally using these assumptions. */
-    public static final int CALLSITE_FAST_SCOPE    = 0x400;
+    public static final int CALLSITE_FAST_SCOPE    = 1 << 2;
+    /** Flags that a callsite type is optimistic, i.e. we might get back a wider return value than encoded in the
+     * descriptor, and in that case we have to throw an UnwarrantedOptimismException */
+    public static final int CALLSITE_OPTIMISTIC    = 1 << 3;
+    /** Is this really an apply that we try to call as a call? */
+    public static final int CALLSITE_APPLY_TO_CALL = 1 << 4;
 
     /** Flags that the call site is profiled; Contexts that have {@code "profile.callsites"} boolean property set emit
      * code where call sites have this flag set. */
-    public static final int CALLSITE_PROFILE          = 0x10;
+    public static final int CALLSITE_PROFILE        = 1 << 5;
     /** Flags that the call site is traced; Contexts that have {@code "trace.callsites"} property set emit code where
      * call sites have this flag set. */
-    public static final int CALLSITE_TRACE            = 0x20;
+    public static final int CALLSITE_TRACE          = 1 << 6;
     /** Flags that the call site linkage miss (and thus, relinking) is traced; Contexts that have the keyword
      * {@code "miss"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
-    public static final int CALLSITE_TRACE_MISSES     = 0x40;
+    public static final int CALLSITE_TRACE_MISSES   = 1 << 7;
     /** Flags that entry/exit to/from the method linked at call site are traced; Contexts that have the keyword
-     * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag
-     * set. */
-    public static final int CALLSITE_TRACE_ENTEREXIT  = 0x80;
+     * {@code "enterexit"} in their {@code "trace.callsites"} property emit code where call sites have this flag set. */
+    public static final int CALLSITE_TRACE_ENTEREXIT = 1 << 8;
     /** Flags that values passed as arguments to and returned from the method linked at call site are traced; Contexts
      * that have the keyword {@code "values"} in their {@code "trace.callsites"} property emit code where call sites
      * have this flag set. */
-    public static final int CALLSITE_TRACE_VALUES    = 0x100;
-    /** Ordinarily, when {@link #CALLSITE_TRACE_VALUES} is set, scope objects are not printed in the trace but instead
-     * the word {@code "SCOPE"} is printed instead With this flag, scope objects are also printed. Contexts that have
-     * the keyword {@code "scope"} in their {@code "trace.callsites"} property emit code where call sites have this flag
-     * set. */
-    public static final int CALLSITE_TRACE_SCOPE      = 0x200;
+    public static final int CALLSITE_TRACE_VALUES   = 1 << 9;
+
+    //we could have more tracing flags here, for example CALLSITE_TRACE_SCOPE, but bits are a bit precious
+    //right now given the program points
+
+    /**
+     * Number of bits the program point is shifted to the left in the flags (lowest bit containing a program point).
+     * Always one larger than the largest flag shift. Note that introducing a new flag halves the number of program
+     * points we can have.
+     * TODO: rethink if we need the various profile/trace flags or the linker can use the Context instead to query its
+     * trace/profile settings.
+     */
+    public static final int CALLSITE_PROGRAM_POINT_SHIFT = 10;
+
+    /**
+     * Maximum program point value. 22 bits should be enough for anyone
+     */
+    public static final int MAX_PROGRAM_POINT_VALUE = (1 << 32 - CALLSITE_PROGRAM_POINT_SHIFT) - 1;
+
+    /**
+     * Flag mask to get the program point flags
+     */
+    public static final int FLAGS_MASK = (1 << CALLSITE_PROGRAM_POINT_SHIFT) - 1;
 
     private static final ClassValue<ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor>> canonicals =
             new ClassValue<ConcurrentMap<NashornCallSiteDescriptor,NashornCallSiteDescriptor>>() {
         @Override
-        protected ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> computeValue(Class<?> type) {
+        protected ConcurrentMap<NashornCallSiteDescriptor, NashornCallSiteDescriptor> computeValue(final Class<?> type) {
             return new ConcurrentHashMap<>();
         }
     };
@@ -87,6 +109,31 @@
     private final int flags;
 
     /**
+     * Function used by {@link NashornTextifier} to represent call site flags in
+     * human readable form
+     * @param flags call site flags
+     * @return human readable form of this callsite descriptor
+     */
+    public static String toString(final int flags) {
+        final StringBuilder sb = new StringBuilder();
+        if ((flags & CALLSITE_SCOPE) != 0) {
+            if ((flags & CALLSITE_FAST_SCOPE) != 0) {
+                sb.append("fastscope ");
+            } else {
+                assert (flags & CALLSITE_FAST_SCOPE) == 0 : "can't be fastscope without scope";
+                sb.append("scope ");
+            }
+        }
+        if ((flags & CALLSITE_APPLY_TO_CALL) != 0) {
+            sb.append("apply2call ");
+        }
+        if ((flags & CALLSITE_STRICT) != 0) {
+            sb.append("strict ");
+        }
+        return sb.length() == 0 ? "" : " " + sb.toString().trim();
+    }
+
+    /**
      * Retrieves a Nashorn call site descriptor with the specified values. Since call site descriptors are immutable
      * this method is at liberty to retrieve canonicalized instances (although it is not guaranteed it will do so).
      * @param lookup the lookup describing the script
@@ -262,6 +309,35 @@
         return isFlag(desc, CALLSITE_STRICT);
     }
 
+    /**
+     * Returns true if this is an apply call that we try to call as
+     * a "call"
+     * @param desc descriptor
+     * @return true if apply to call
+     */
+    public static boolean isApplyToCall(final CallSiteDescriptor desc) {
+        return isFlag(desc, CALLSITE_APPLY_TO_CALL);
+    }
+
+    /**
+     * Is this an optimistic call site
+     * @param desc descriptor
+     * @return true if optimistic
+     */
+    public static boolean isOptimistic(final CallSiteDescriptor desc) {
+        return isFlag(desc, CALLSITE_OPTIMISTIC);
+    }
+
+    /**
+     * Get a program point from a descriptor (must be optimistic)
+     * @param desc descriptor
+     * @return program point
+     */
+    public static int getProgramPoint(final CallSiteDescriptor desc) {
+        assert isOptimistic(desc) : "program point requested from non-optimistic descriptor " + desc;
+        return getFlags(desc) >> CALLSITE_PROGRAM_POINT_SHIFT;
+    }
+
     boolean isProfile() {
         return isFlag(CALLSITE_PROFILE);
     }
@@ -282,12 +358,13 @@
         return isFlag(CALLSITE_TRACE_VALUES);
     }
 
-    boolean isTraceScope() {
-        return isFlag(CALLSITE_TRACE_SCOPE);
+    boolean isOptimistic() {
+        return isFlag(CALLSITE_OPTIMISTIC);
     }
 
     @Override
     public CallSiteDescriptor changeMethodType(final MethodType newMethodType) {
         return get(getLookup(), operator, operand, newMethodType, flags);
     }
+
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
index 77c5e93..dac36d4 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornGuards.java
@@ -31,6 +31,7 @@
 import java.lang.invoke.MethodHandles;
 import java.lang.ref.WeakReference;
 import jdk.internal.dynalink.CallSiteDescriptor;
+import jdk.internal.dynalink.linker.LinkRequest;
 import jdk.nashorn.api.scripting.JSObject;
 import jdk.nashorn.internal.codegen.ObjectClassGenerator;
 import jdk.nashorn.internal.objects.Global;
@@ -38,56 +39,80 @@
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptFunction;
 import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.options.Options;
 
 /**
  * Constructor of method handles used to guard call sites.
  */
 public final class NashornGuards {
-    private static final MethodHandle IS_SCRIPTOBJECT   = findOwnMH("isScriptObject", boolean.class, Object.class);
-    private static final MethodHandle IS_NOT_JSOBJECT   = findOwnMH("isNotJSObject", boolean.class, Object.class);
-    private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
-    private static final MethodHandle IS_MAP            = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
+    private static final MethodHandle IS_MAP              = findOwnMH("isMap", boolean.class, ScriptObject.class, PropertyMap.class);
+    private static final MethodHandle IS_MAP_SCRIPTOBJECT = findOwnMH("isMap", boolean.class, Object.class, PropertyMap.class);
+    private static final MethodHandle IS_INSTANCEOF_2     = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
+    private static final MethodHandle IS_SCRIPTOBJECT     = findOwnMH("isScriptObject", boolean.class, Object.class);
+    private static final MethodHandle IS_NOT_JSOBJECT     = findOwnMH("isNotJSObject", boolean.class, Object.class);
     private static final MethodHandle SAME_OBJECT       = findOwnMH("sameObject", boolean.class, Object.class, WeakReference.class);
-    private static final MethodHandle IS_INSTANCEOF_2   = findOwnMH("isInstanceOf2", boolean.class, Object.class, Class.class, Class.class);
+    //TODO - maybe put this back in ScriptFunction instead of the ClassCastException.class relinkage
+    //private static final MethodHandle IS_SCRIPTFUNCTION = findOwnMH("isScriptFunction", boolean.class, Object.class);
+
+    private static final boolean CCE_ONLY = Options.getBooleanProperty("nashorn.cce");
 
     // don't create me!
     private NashornGuards() {
     }
 
     /**
-     * Get the guard that checks if an item is a {@code ScriptObject}
-     * @return method handle for guard
+     * Given a callsite descriptor and a link request, determine whether we should use an instanceof
+     * check explicitly for the guard if needed, or if we should link it with a try/catch ClassCastException
+     * combinator as its relink criteria - i.e. relink when CCE is thrown.
+     *
+     * @param desc     callsite descriptor
+     * @param request  link request
+     * @return true of explicit instanceof check is needed
+     */
+    public static boolean explicitInstanceOfCheck(final CallSiteDescriptor desc, final LinkRequest request) {
+        //THIS is currently true, as the inliner encounters several problems with sun.misc.ValueConversions.castReference
+        //otherwise. We should only use the exception based relink where we have no choice, and the result is faster code,
+        //for example in the NativeArray, TypedArray, ContinuousArray getters. For the standard callsite, it appears that
+        //we lose performance rather than gain it, due to JVM issues. :-(
+        return !CCE_ONLY;
+    }
+
+    /**
+     * Returns a guard that does an instanceof ScriptObject check on the receiver
+     * @return guard
      */
     public static MethodHandle getScriptObjectGuard() {
         return IS_SCRIPTOBJECT;
     }
 
-    /**
-     * Get the guard that checks if an item is not a {@code JSObject}
-     * @return method handle for guard
-     */
-    public static MethodHandle getNotJSObjectGuard() {
-        return IS_NOT_JSOBJECT;
-    }
+   /**
+    * Get the guard that checks if an item is not a {@code JSObject}
+    * @return method handle for guard
+    */
+   public static MethodHandle getNotJSObjectGuard() {
+       return IS_NOT_JSOBJECT;
+   }
 
     /**
-     * Get the guard that checks if an item is a {@code ScriptFunction}
-     * @return method handle for guard
+     * Returns a guard that does an instanceof ScriptObject check on the receiver
+     * @param explicitInstanceOfCheck - if false, then this is a nop, because it's all the guard does
+     * @return guard
      */
-    public static MethodHandle getScriptFunctionGuard() {
-        return IS_SCRIPTFUNCTION;
+    public static MethodHandle getScriptObjectGuard(final boolean explicitInstanceOfCheck) {
+        return explicitInstanceOfCheck ? IS_SCRIPTOBJECT : null;
     }
 
     /**
      * Get the guard that checks if a {@link PropertyMap} is equal to
      * a known map, using reference comparison
      *
+     * @param explicitInstanceOfCheck true if we should do an explicit script object instanceof check instead of just casting
      * @param map The map to check against. This will be bound to the guard method handle
      *
      * @return method handle for guard
      */
-    public static MethodHandle getMapGuard(final PropertyMap map) {
-        return MH.insertArguments(IS_MAP, 1, map);
+    public static MethodHandle getMapGuard(final PropertyMap map, final boolean explicitInstanceOfCheck) {
+        return MH.insertArguments(explicitInstanceOfCheck ? IS_MAP_SCRIPTOBJECT : IS_MAP, 1, map);
     }
 
     /**
@@ -109,23 +134,24 @@
      * @param sobj the first object in the prototype chain
      * @param property the property
      * @param desc the callsite descriptor
+     * @param explicitInstanceOfCheck true if we should do an explicit script object instanceof check instead of just casting
      * @return method handle for guard
      */
-    public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc) {
+    public static MethodHandle getGuard(final ScriptObject sobj, final Property property, final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck) {
         if (!needsGuard(property, desc)) {
             return null;
         }
         if (NashornCallSiteDescriptor.isScope(desc)) {
-            if (property != null && property.isBound()) {
+            if (property != null && property.isBound() && !property.canChangeType()) {
                 // This is a declared top level variables in main script or eval, use identity guard.
                 return getIdentityGuard(sobj);
             }
             if (!(sobj instanceof Global) && (property == null || property.isConfigurable())) {
                 // Undeclared variables in nested evals need stronger guards
-                return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap()));
+                return combineGuards(getIdentityGuard(sobj), getMapGuard(sobj.getMap(), explicitInstanceOfCheck));
             }
         }
-        return getMapGuard(sobj.getMap());
+        return getMapGuard(sobj.getMap(), explicitInstanceOfCheck);
     }
 
 
@@ -158,7 +184,13 @@
      * @return true if both guard1 and guard2 returned true
      */
     public static MethodHandle combineGuards(final MethodHandle guard1, final MethodHandle guard2) {
-        return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
+        if (guard1 == null) {
+            return guard2;
+        } else if (guard2 == null) {
+            return guard1;
+        } else {
+            return MH.guardWithTest(guard1, guard2, MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class));
+        }
     }
 
     @SuppressWarnings("unused")
@@ -167,13 +199,18 @@
     }
 
     @SuppressWarnings("unused")
-    private static boolean isNotJSObject(final Object self) {
-        return !(self instanceof JSObject);
+    private static boolean isScriptObject(final Class<? extends ScriptObject> clazz, final Object self) {
+        return clazz.isInstance(self);
     }
 
     @SuppressWarnings("unused")
-    private static boolean isScriptFunction(final Object self) {
-        return self instanceof ScriptFunction;
+    private static boolean isMap(final ScriptObject self, final PropertyMap map) {
+        return self.getMap() == map;
+    }
+
+    @SuppressWarnings("unused")
+    private static boolean isNotJSObject(final Object self) {
+        return !(self instanceof JSObject);
     }
 
     @SuppressWarnings("unused")
@@ -181,6 +218,7 @@
         return self instanceof ScriptObject && ((ScriptObject)self).getMap() == map;
     }
 
+
     @SuppressWarnings("unused")
     private static boolean sameObject(final Object self, final WeakReference<ScriptObject> ref) {
         return self == ref.get();
@@ -191,8 +229,12 @@
         return class1.isInstance(self) || class2.isInstance(self);
     }
 
+    @SuppressWarnings("unused")
+    private static boolean isScriptFunction(final Object self) {
+        return self instanceof ScriptFunction;
+    }
+
     private static MethodHandle findOwnMH(final String name, final Class<?> rtype, final Class<?>... types) {
         return MH.findStatic(MethodHandles.lookup(), NashornGuards.class, name, MH.type(rtype, types));
     }
-
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
index 0ac5f9a..bde0156 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornLinker.java
@@ -63,7 +63,7 @@
 final class NashornLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator {
     private static final ClassValue<MethodHandle> ARRAY_CONVERTERS = new ClassValue<MethodHandle>() {
         @Override
-        protected MethodHandle computeValue(Class<?> type) {
+        protected MethodHandle computeValue(final Class<?> type) {
             return createArrayConverter(type);
         }
     };
@@ -91,16 +91,20 @@
             return null;
         }
 
+        return Bootstrap.asTypeSafeReturn(getGuardedInvocation(self,  request, desc), linkerServices, desc);
+    }
+
+    private static GuardedInvocation getGuardedInvocation(final Object self, final LinkRequest request, final CallSiteDescriptor desc) {
         final GuardedInvocation inv;
         if (self instanceof ScriptObject) {
             inv = ((ScriptObject)self).lookup(desc, request);
         } else if (self instanceof Undefined) {
             inv = Undefined.lookup(desc);
         } else {
-            throw new AssertionError(); // Should never reach here.
+            throw new AssertionError(self.getClass().getName()); // Should never reach here.
         }
 
-        return Bootstrap.asType(inv, linkerServices, desc);
+        return inv;
     }
 
     @Override
@@ -184,7 +188,7 @@
      */
     private static GuardedInvocation getArrayConverter(final Class<?> sourceType, final Class<?> targetType) {
         final boolean isSourceTypeNativeArray = sourceType == NativeArray.class;
-        // If source type is more generic than ScriptFunction class, we'll need to use a guard
+        // If source type is more generic than NativeArray class, we'll need to use a guard
         final boolean isSourceTypeGeneric = !isSourceTypeNativeArray && sourceType.isAssignableFrom(NativeArray.class);
 
         if (isSourceTypeNativeArray || isSourceTypeGeneric) {
@@ -208,12 +212,12 @@
         return MH.asType(converter, converter.type().changeReturnType(type));
     }
 
-    private static GuardedInvocation getMirrorConverter(Class<?> sourceType, Class<?> targetType) {
+    private static GuardedInvocation getMirrorConverter(final Class<?> sourceType, final Class<?> targetType) {
         // Could've also used (targetType.isAssignableFrom(ScriptObjectMirror.class) && targetType != Object.class) but
         // it's probably better to explicitly spell out the supported target types
         if (targetType == Map.class || targetType == Bindings.class || targetType == JSObject.class || targetType == ScriptObjectMirror.class) {
             if(ScriptObject.class.isAssignableFrom(sourceType)) {
-                return new GuardedInvocation(CREATE_MIRROR, null);
+                return new GuardedInvocation(CREATE_MIRROR);
             }
             return new GuardedInvocation(CREATE_MIRROR, IS_SCRIPT_OBJECT);
         }
@@ -270,7 +274,7 @@
         return Comparison.INDETERMINATE;
     }
 
-    private static boolean isList(Class<?> clazz) {
+    private static boolean isList(final Class<?> clazz) {
         return clazz == List.class || clazz == Deque.class;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
index 22135bc..e8b8c43 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornPrimitiveLinker.java
@@ -39,7 +39,7 @@
 import jdk.internal.dynalink.support.TypeUtilities;
 import jdk.nashorn.internal.objects.Global;
 import jdk.nashorn.internal.runtime.ConsString;
-import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
 
 /**
  * Internal linker for String, Boolean, and Number objects, only ever used by Nashorn engine and not exposed to other
@@ -47,6 +47,9 @@
  * primitive type conversions for these types when linking to Java methods.
  */
 final class NashornPrimitiveLinker implements TypeBasedGuardingDynamicLinker, GuardingTypeConverterFactory, ConversionComparator {
+    private static final GuardedTypeConversion VOID_TO_OBJECT = new GuardedTypeConversion(
+            new GuardedInvocation(MethodHandles.constant(Object.class, ScriptRuntime.UNDEFINED)), true);
+
     @Override
     public boolean canLinkType(final Class<?> type) {
         return canLinkTypeStatic(type);
@@ -62,10 +65,9 @@
         final LinkRequest request = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
 
         final Object self = request.getReceiver();
-        final Global global = Context.getGlobal();
         final NashornCallSiteDescriptor desc = (NashornCallSiteDescriptor) request.getCallSiteDescriptor();
 
-        return Bootstrap.asType(global.primitiveLookup(request, self), linkerServices, desc);
+        return Bootstrap.asTypeSafeReturn(Global.primitiveLookup(request, self), linkerServices, desc);
     }
 
     /**
@@ -79,6 +81,9 @@
     public GuardedTypeConversion convertToType(final Class<?> sourceType, final Class<?> targetType) {
         final MethodHandle mh = JavaArgumentConverters.getConverter(targetType);
         if (mh == null) {
+            if(targetType == Object.class && sourceType == void.class) {
+                return VOID_TO_OBJECT;
+            }
             return null;
         }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
index f8ea991..c870f39 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/NashornStaticClassLinker.java
@@ -54,12 +54,12 @@
     private static final GuardingDynamicLinker staticClassLinker = BeansLinker.getLinkerForClass(StaticClass.class);
 
     @Override
-    public boolean canLinkType(Class<?> type) {
+    public boolean canLinkType(final Class<?> type) {
         return type == StaticClass.class;
     }
 
     @Override
-    public GuardedInvocation getGuardedInvocation(LinkRequest linkRequest, LinkerServices linkerServices) throws Exception {
+    public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
         final LinkRequest request = linkRequest.withoutRuntimeContext(); // Nashorn has no runtime context
         final Object self = request.getReceiver();
         if (self.getClass() != StaticClass.class) {
@@ -99,7 +99,7 @@
         return delegate(linkerServices, request);
     }
 
-    private static GuardedInvocation delegate(LinkerServices linkerServices, final LinkRequest request) throws Exception {
+    private static GuardedInvocation delegate(final LinkerServices linkerServices, final LinkRequest request) throws Exception {
         return NashornBeansLinker.getGuardedInvocation(staticClassLinker, request, linkerServices);
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
index 7665be7..d271da6 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/PrimitiveLookup.java
@@ -59,6 +59,7 @@
      * creates a transient native wrapper of the same type as {@code wrappedReceiver} for subsequent invocations of the
      * method - it will be combined into the returned invocation as an argument filter on the receiver.
      * @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive
+     * @param protoFilter A method handle that walks up the proto chain of this receiver object
      * type {@code receiverClass}.
      */
     public static GuardedInvocation lookupPrimitive(final LinkRequest request, final Class<?> receiverClass,
@@ -77,6 +78,7 @@
      * @param wrapFilter A method handle that takes a primitive value of type guarded by the {@code guard} and
      * creates a transient native wrapper of the same type as {@code wrappedReceiver} for subsequent invocations of the
      * method - it will be combined into the returned invocation as an argument filter on the receiver.
+     * @param protoFilter A method handle that walks up the proto chain of this receiver object
      * @return a guarded invocation representing the operation at the call site when performed on a JavaScript primitive
      * type (that is implied by both {@code guard} and {@code wrappedReceiver}).
      */
@@ -86,7 +88,7 @@
         final CallSiteDescriptor desc = request.getCallSiteDescriptor();
         final String operator = CallSiteDescriptorFactory.tokenizeOperators(desc).get(0);
         if ("setProp".equals(operator) || "setElem".equals(operator)) {
-            MethodType type = desc.getMethodType();
+            final MethodType type = desc.getMethodType();
             MethodHandle method = MH.asType(Lookup.EMPTY_SETTER, MH.type(void.class, Object.class, type.parameterType(1)));
             if (type.parameterCount() == 3) {
                 method = MH.dropArguments(method, 2, type.parameterType(2));
@@ -124,7 +126,7 @@
                 assert receiverType.isAssignableFrom(wrapType.returnType());
                 method = MH.filterArguments(method, 0, MH.asType(wrapFilter, wrapType.changeReturnType(receiverType)));
             }
-            return new GuardedInvocation(method, guard, link.getSwitchPoint());
+            return new GuardedInvocation(method, guard, link.getSwitchPoints(), null);
         }
         return null;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
index 66720c2..10ab434 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/ReflectionCheckLinker.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime.linker;
 
+import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
+
 import java.lang.reflect.Modifier;
 import java.lang.reflect.Proxy;
 import jdk.internal.dynalink.CallSiteDescriptor;
@@ -33,7 +35,9 @@
 import jdk.internal.dynalink.linker.LinkerServices;
 import jdk.internal.dynalink.linker.TypeBasedGuardingDynamicLinker;
 import jdk.internal.dynalink.support.CallSiteDescriptorFactory;
+import jdk.nashorn.api.scripting.ClassFilter;
 import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.objects.Global;
 
 /**
  * Check java reflection permission for java reflective and java.lang.invoke access from scripts
@@ -100,6 +104,12 @@
     }
 
     static void checkReflectionAccess(final Class<?> clazz, final boolean isStatic) {
+        final Global global = Context.getGlobal();
+        final ClassFilter cf = global.getClassFilter();
+        if (cf != null && isReflectiveCheckNeeded(clazz, isStatic)) {
+            throw typeError("no.reflection.with.classfilter");
+        }
+
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null && isReflectiveCheckNeeded(clazz, isStatic)) {
             checkReflectionPermission(sm);
@@ -107,6 +117,12 @@
     }
 
     private static void checkLinkRequest(final LinkRequest origRequest) {
+        final Global global = Context.getGlobal();
+        final ClassFilter cf = global.getClassFilter();
+        if (cf != null) {
+            throw typeError("no.reflection.with.classfilter");
+        }
+
         final SecurityManager sm = System.getSecurityManager();
         if (sm != null) {
             final LinkRequest requestWithoutContext = origRequest.withoutRuntimeContext(); // Nashorn has no runtime context
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java b/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
new file mode 100644
index 0000000..084f765
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/DebugLogger.java
@@ -0,0 +1,606 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.runtime.logging;
+
+import java.io.PrintWriter;
+import java.security.AccessControlContext;
+import java.security.AccessController;
+import java.security.Permissions;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Formatter;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+import java.util.logging.LoggingPermission;
+import jdk.nashorn.internal.objects.Global;
+import jdk.nashorn.internal.runtime.Context;
+import jdk.nashorn.internal.runtime.ScriptFunction;
+import jdk.nashorn.internal.runtime.ScriptObject;
+import jdk.nashorn.internal.runtime.ScriptRuntime;
+import jdk.nashorn.internal.runtime.events.RuntimeEvent;
+
+/**
+ * Wrapper class for Logging system. This is how you are supposed to register a logger and use it
+ */
+
+public final class DebugLogger {
+
+    /** Disabled logger used for all loggers that need an instance, but shouldn't output anything */
+    public static final DebugLogger DISABLED_LOGGER = new DebugLogger("disabled", Level.OFF, false);
+
+    private final Logger  logger;
+    private final boolean isEnabled;
+
+    private int indent;
+
+    private static final int INDENT_SPACE = 4;
+
+    /** A quiet logger only logs {@link RuntimeEvent}s and does't output any text, regardless of level */
+    private final boolean isQuiet;
+
+    /**
+     * Constructor
+     *
+     * A logger can be paired with a property, e.g. {@code --log:codegen:info} is equivalent to {@code -Dnashorn.codegen.log}
+     *
+     * @param loggerName  name of logger - this is the unique key with which it can be identified
+     * @param loggerLevel level of the logger
+     * @param isQuiet     is this a quiet logger, i.e. enabled for things like e.g. RuntimeEvent:s, but quiet otherwise
+     */
+    public DebugLogger(final String loggerName, final Level loggerLevel, final boolean isQuiet) {
+        this.logger  = instantiateLogger(loggerName, loggerLevel);
+        this.isQuiet = isQuiet;
+        assert logger != null;
+        this.isEnabled = getLevel() != Level.OFF;
+    }
+
+    private static Logger instantiateLogger(final String name, final Level level) {
+        final Logger logger = java.util.logging.Logger.getLogger(name);
+        AccessController.doPrivileged(new PrivilegedAction<Void>() {
+            @Override
+            public Void run() {
+                for (final Handler h : logger.getHandlers()) {
+                    logger.removeHandler(h);
+                }
+
+                logger.setLevel(level);
+                logger.setUseParentHandlers(false);
+                final Handler c = new ConsoleHandler();
+
+                c.setFormatter(new Formatter() {
+                    @Override
+                    public String format(final LogRecord record) {
+                        final StringBuilder sb = new StringBuilder();
+
+                        sb.append('[')
+                           .append(record.getLoggerName())
+                           .append("] ")
+                           .append(record.getMessage())
+                           .append('\n');
+
+                        return sb.toString();
+                    }
+                });
+                logger.addHandler(c);
+                c.setLevel(level);
+                return null;
+            }
+        }, createLoggerControlAccCtxt());
+
+        return logger;
+    }
+
+    /**
+     * Do not currently support chaining this with parent logger. Logger level null
+     * means disabled
+     * @return level
+     */
+    public Level getLevel() {
+        return logger.getLevel() == null ? Level.OFF : logger.getLevel();
+    }
+
+    /**
+     * Get the output writer for the logger. Loggers always default to
+     * stderr for output as they are used mainly to output debug info
+     *
+     * Can be inherited so this should not be static.
+     *
+     * @return print writer for log output.
+     */
+    @SuppressWarnings("static-method")
+    public PrintWriter getOutputStream() {
+        return Context.getCurrentErr();
+    }
+
+    /**
+     * Add quotes around a string
+     * @param str string
+     * @return quoted string
+     */
+    public static String quote(final String str) {
+        if (str.isEmpty()) {
+            return "''";
+        }
+
+        char startQuote = '\0';
+        char endQuote   = '\0';
+        char quote      = '\0';
+
+        if (str.startsWith("\\") || str.startsWith("\"")) {
+            startQuote = str.charAt(0);
+        }
+        if (str.endsWith("\\") || str.endsWith("\"")) {
+            endQuote = str.charAt(str.length() - 1);
+        }
+
+        if (startQuote == '\0' || endQuote == '\0') {
+            quote = startQuote == '\0' ? endQuote : startQuote;
+        }
+        if (quote == '\0') {
+            quote = '\'';
+        }
+
+        return (startQuote == '\0' ? quote : startQuote) + str + (endQuote == '\0' ? quote : endQuote);
+    }
+
+    /**
+     * Check if the logger is enabled
+     * @return true if enabled
+     */
+    public boolean isEnabled() {
+        return isEnabled;
+    }
+
+    /**
+     * Check if the logger is enabled
+     * @param logger logger to check, null will return false
+     * @return true if enabled
+     */
+    public static boolean isEnabled(final DebugLogger logger) {
+        return logger != null && logger.isEnabled();
+    }
+
+    /**
+     * If you want to change the indent level of your logger, call indent with a new position.
+     * Positions start at 0 and are increased by one for a new "tab"
+     *
+     * @param pos indent position
+     */
+    public void indent(final int pos) {
+        if (isEnabled) {
+           indent += pos * INDENT_SPACE;
+        }
+    }
+
+    /**
+     * Add an indent position
+     */
+    public void indent() {
+        indent += INDENT_SPACE;
+    }
+
+    /**
+     * Unindent a position
+     */
+    public void unindent() {
+        indent -= INDENT_SPACE;
+        if (indent < 0) {
+            indent = 0;
+        }
+    }
+
+    private static void logEvent(final RuntimeEvent<?> event) {
+        if (event != null) {
+            final Global global = Context.getGlobal();
+            if (global.has("Debug")) {
+                final ScriptObject debug = (ScriptObject)global.get("Debug");
+                final ScriptFunction addRuntimeEvent = (ScriptFunction)debug.get("addRuntimeEvent");
+                ScriptRuntime.apply(addRuntimeEvent, debug, event);
+            }
+        }
+    }
+
+    /**
+     * Check if the logger is above the level of detail given
+     * @see java.util.logging.Level
+     *
+     * The higher the level, the more severe the warning
+     *
+     * @param level logging level
+     * @return true if level is above the given one
+     */
+    public boolean levelCoarserThan(final Level level) {
+        return getLevel().intValue() > level.intValue();
+    }
+
+    /**
+     * Check if the logger is above or equal to the level
+     * of detail given
+     * @see java.util.logging.Level
+     *
+     * The higher the level, the more severe the warning
+     *
+     * @param level logging level
+     * @return true if level is above the given one
+     */
+    public boolean levelCoarserThanOrEqual(final Level level) {
+        return getLevel().intValue() >= level.intValue();
+    }
+
+    /**
+     * Check if the logger is below the level of detail given
+     * @see java.util.logging.Level
+     *
+     * The higher the level, the more severe the warning
+     *
+     * @param level logging level
+     * @return true if level is above the given one
+     */
+    public boolean levelFinerThan(final Level level) {
+        return getLevel().intValue() < level.intValue();
+    }
+
+    /**
+     * Check if the logger is below or equal to the level
+     * of detail given
+     * @see java.util.logging.Level
+     *
+     * The higher the level, the more severe the warning
+     *
+     * @param level logging level
+     * @return true if level is above the given one
+     */
+    public boolean levelFinerThanOrEqual(final Level level) {
+        return getLevel().intValue() <= level.intValue();
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger
+     * @param str the string to log
+     */
+    public void finest(final String str) {
+        log(Level.FINEST, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level {@link java.util.logging.Level#FINEST} on this logger
+     * @param event optional runtime event to log
+     * @param str the string to log
+     */
+    public void finest(final RuntimeEvent<?> event, final String str) {
+        finest(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINEST} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void finest(final Object... objs) {
+        log(Level.FINEST, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINEST} on this logger
+     * @param event optional runtime event to log
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void finest(final RuntimeEvent<?> event, final Object... objs) {
+        finest(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINER} on this logger
+     * @param str the string to log
+     */
+    public void finer(final String str) {
+        log(Level.FINER, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINER} on this logger
+     * @param event optional runtime event to log
+     * @param str the string to log
+     */
+    public void finer(final RuntimeEvent<?> event, final String str) {
+        finer(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINER} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void finer(final Object... objs) {
+        log(Level.FINER, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINER} on this logger
+     * @param event optional runtime event to log
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void finer(final RuntimeEvent<?> event, final Object... objs) {
+        finer(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param str the string to log
+     */
+    public void fine(final String str) {
+        log(Level.FINE, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param event optional runtime event to log
+     * @param str the string to log
+     */
+    public void fine(final RuntimeEvent<?> event, final String str) {
+        fine(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void fine(final Object... objs) {
+        log(Level.FINE, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param event optional runtime event to log
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void fine(final RuntimeEvent<?> event, final Object... objs) {
+        fine(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#CONFIG} on this logger
+     * @param str the string to log
+     */
+    public void config(final String str) {
+        log(Level.CONFIG, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#CONFIG} on this logger
+     * @param event optional runtime event to log
+     * @param str the string to log
+     */
+    public void config(final RuntimeEvent<?> event, final String str) {
+        config(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#CONFIG} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void config(final Object... objs) {
+        log(Level.CONFIG, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#CONFIG} on this logger
+     * @param event optional runtime event to log
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void config(final RuntimeEvent<?> event, final Object... objs) {
+        config(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#INFO} on this logger
+     * @param str the string to log
+     */
+    public void info(final String str) {
+        log(Level.INFO, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#INFO} on this logger
+     * @param event optional runtime event to log
+     * @param str the string to log
+     */
+    public void info(final RuntimeEvent<?> event, final String str) {
+        info(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void info(final Object... objs) {
+        log(Level.INFO, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param event optional runtime event to log
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void info(final RuntimeEvent<?> event, final Object... objs) {
+        info(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#WARNING} on this logger
+     * @param str the string to log
+     */
+    public void warning(final String str) {
+        log(Level.WARNING, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#WARNING} on this logger
+     * @param event optional runtime event to log
+     * @param str the string to log
+     */
+    public void warning(final RuntimeEvent<?> event, final String str) {
+        warning(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void warning(final Object... objs) {
+        log(Level.WARNING, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     * @param event optional runtime event to log
+     */
+    public void warning(final RuntimeEvent<?> event, final Object... objs) {
+        warning(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#SEVERE} on this logger
+     * @param str the string to log
+     */
+    public void severe(final String str) {
+        log(Level.SEVERE, str);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#SEVERE} on this logger
+     * @param str the string to log
+     * @param event optional runtime event to log
+     */
+    public void severe(final RuntimeEvent<?> event, final String str) {
+        severe(str);
+        logEvent(event);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#SEVERE} on this logger
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void severe(final Object... objs) {
+        log(Level.SEVERE, objs);
+    }
+
+    /**
+     * Shorthand for outputting a log string as log level
+     * {@link java.util.logging.Level#FINE} on this logger
+     * @param event optional runtime event to log
+     * @param objs object array to log - use this to perform lazy concatenation to avoid unconditional toString overhead
+     */
+    public void severe(final RuntimeEvent<?> event, final Object... objs) {
+        severe(objs);
+        logEvent(event);
+    }
+
+    /**
+     * Output log line on this logger at a given level of verbosity
+     * @see java.util.logging.Level
+     *
+     * @param level minimum log level required for logging to take place
+     * @param str   string to log
+     */
+    public void log(final Level level, final String str) {
+        if (isEnabled && !isQuiet) {
+            final StringBuilder sb = new StringBuilder();
+            for (int i = 0 ; i < indent ; i++) {
+                sb.append(' ');
+            }
+            sb.append(str);
+            logger.log(level, sb.toString());
+        }
+    }
+
+    /**
+     * Output log line on this logger at a given level of verbosity
+     * @see java.util.logging.Level
+     *
+     * @param level minimum log level required for logging to take place
+     * @param objs  objects for which to invoke toString and concatenate to log
+     */
+    public void log(final Level level, final Object... objs) {
+        if (isEnabled && !isQuiet) {
+            final StringBuilder sb = new StringBuilder();
+            for (final Object obj : objs) {
+                sb.append(obj);
+            }
+            log(level, sb.toString());
+        }
+    }
+
+    /**
+     * Access control context for logger level and instantiation permissions
+     * @return access control context
+     */
+    private static AccessControlContext createLoggerControlAccCtxt() {
+        final Permissions perms = new Permissions();
+        perms.add(new LoggingPermission("control", null));
+        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
+    }
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java b/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java
new file mode 100644
index 0000000..3295003
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/Loggable.java
@@ -0,0 +1,56 @@
+/*
+ * 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.  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.
+ */
+package jdk.nashorn.internal.runtime.logging;
+
+import jdk.nashorn.internal.runtime.Context;
+
+/**
+ * Interface implemented by classes that are loggable.
+ * Their instances will provide functionality for initializing
+ * a logger (usually by asking Global for it, with a reference
+ * to this.getClass()) and a method to return the logger in
+ * use
+ *
+ * Typically a class implementing this interface also has the
+ * Logger annotation
+ *
+ * @see Logger
+ */
+public interface Loggable {
+    /**
+     * Initialize a logger, by asking Context to get or create it
+     * and then keep it in a table by name
+     *
+     * @param context context
+     * @return the initialized logger
+     */
+    public DebugLogger initLogger(final Context context);
+
+    /**
+     * Return the logger in use
+     * @return logger
+     */
+    public DebugLogger getLogger();
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java b/nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java
new file mode 100644
index 0000000..a407fec
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/logging/Logger.java
@@ -0,0 +1,48 @@
+/*
+ * 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.  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.
+ */
+package jdk.nashorn.internal.runtime.logging;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * This annotation is associated with a class that has a logger.
+ * It contains a name property of the logger name. e.g. a class
+ * whose logger can be initialized by --log:fields, should be
+ * annotated @Logger(name="fields"). Multiple classes can have
+ * the same annotation, which will make them use the same logger
+ * object. Usually a class with this annotation is also a Loggable,
+ * but it is not a hard demand
+ *
+ * @see Loggable
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Logger {
+    /**
+     * Get the name of the logger
+     * @return logger name
+     */
+    public String name() default "";
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java b/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
index bbf1620..aee6caf 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/KeyValueOption.java
@@ -36,7 +36,7 @@
  *
  * {@code --log=module1:level1,module2:level2... }
  */
-public final class KeyValueOption extends Option<String> {
+public class KeyValueOption extends Option<String> {
     /**
      * Map of keys given
      */
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java b/nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java
new file mode 100644
index 0000000..e1d9ced
--- /dev/null
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/LoggingOption.java
@@ -0,0 +1,133 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.runtime.options;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.logging.Level;
+
+/**
+ * Class that collects logging options like --log=compiler:finest,fields,recompile:fine into
+ * a map form that can be used to instantiate loggers in the Global object on demand
+ */
+public class LoggingOption extends KeyValueOption {
+
+    /**
+     * Logging info. Basically a logger name maps to this,
+     * which is a tuple of log level and the "is quiet" flag,
+     * which is a special log level used to collect RuntimeEvents
+     * only, but not output anything
+     */
+    public static class LoggerInfo {
+        private final Level level;
+        private final boolean isQuiet;
+
+        LoggerInfo(final Level level, final boolean isQuiet) {
+            this.level = level;
+            this.isQuiet = isQuiet;
+        }
+
+        /**
+         * Get the log level
+         * @return log level
+         */
+        public Level getLevel() {
+            return level;
+        }
+
+        /**
+         * Get the quiet flag
+         * @return true if quiet flag is set
+         */
+        public boolean isQuiet() {
+            return isQuiet;
+        }
+    }
+
+    private final Map<String, LoggerInfo> loggers = new HashMap<>();
+
+    LoggingOption(final String value) {
+        super(value);
+        initialize(getValues());
+    }
+
+    /**
+     * Return the logger info collected from this command line option
+     *
+     * @return map of logger name to logger info
+     */
+    public Map<String, LoggerInfo> getLoggers() {
+        return Collections.unmodifiableMap(loggers);
+    }
+
+    /**
+     * Initialization function that is called to instantiate the logging system. It takes
+     * logger names (keys) and logging labels respectively
+     *
+     * @param map a map where the key is a logger name and the value a logging level
+     * @throws IllegalArgumentException if level or names cannot be parsed
+     */
+    private void initialize(final Map<String, String> logMap) throws IllegalArgumentException {
+        try {
+            for (final Entry<String, String> entry : logMap.entrySet()) {
+                Level level;
+                final String name        = lastPart(entry.getKey());
+                final String levelString = entry.getValue().toUpperCase(Locale.ENGLISH);
+                final boolean isQuiet;
+
+                if ("".equals(levelString)) {
+                    level = Level.INFO;
+                    isQuiet = false;
+                } else if ("QUIET".equals(levelString)) {
+                    level = Level.INFO;
+                    isQuiet = true;
+                } else {
+                    level = Level.parse(levelString);
+                    isQuiet = false;
+                }
+
+                loggers.put(name, new LoggerInfo(level, isQuiet));
+            }
+        } catch (final IllegalArgumentException | SecurityException e) {
+            throw e;
+        }
+    }
+
+
+
+    private static String lastPart(final String packageName) {
+        final String[] parts = packageName.split("\\.");
+        if (parts.length == 0) {
+            return packageName;
+        }
+        return parts[parts.length - 1];
+    }
+
+
+}
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
index cd774bb..ed39fa9 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/options/Options.java
@@ -48,7 +48,6 @@
 import java.util.TimeZone;
 import java.util.TreeMap;
 import java.util.TreeSet;
-import jdk.nashorn.internal.runtime.Logging;
 import jdk.nashorn.internal.runtime.QuotedStringTokenizer;
 
 /**
@@ -79,7 +78,10 @@
     /** The options map of enabled options */
     private final TreeMap<String, Option<?>> options;
 
-    /** System property that can be used for command line option propagation */
+    /** System property that can be used to prepend options to the explicitly specified command line. */
+    private static final String NASHORN_ARGS_PREPEND_PROPERTY = "nashorn.args.prepend";
+
+    /** System property that can be used to append options to the explicitly specified command line. */
     private static final String NASHORN_ARGS_PROPERTY = "nashorn.args";
 
     /**
@@ -137,9 +139,10 @@
      * Convenience function for getting system properties in a safe way
 
      * @param name of boolean property
-     * @return true if set to true, false if unset or set to false
+     * @param defValue default value of boolean property
+     * @return true if set to true, default value if unset or set to false
      */
-    public static boolean getBooleanProperty(final String name) {
+    public static boolean getBooleanProperty(final String name, final Boolean defValue) {
         name.getClass(); // null check
         if (!name.startsWith("nashorn.")) {
             throw new IllegalArgumentException(name);
@@ -151,6 +154,9 @@
                     public Boolean run() {
                         try {
                             final String property = System.getProperty(name);
+                            if (property == null && defValue != null) {
+                                return defValue;
+                            }
                             return property != null && !"false".equalsIgnoreCase(property);
                         } catch (final SecurityException e) {
                             // if no permission to read, assume false
@@ -162,6 +168,16 @@
 
     /**
      * Convenience function for getting system properties in a safe way
+
+     * @param name of boolean property
+     * @return true if set to true, false if unset or set to false
+     */
+    public static boolean getBooleanProperty(final String name) {
+        return getBooleanProperty(name, null);
+    }
+
+    /**
+     * Convenience function for getting system properties in a safe way
      *
      * @param name of string property
      * @param defValue the default value if unset
@@ -406,15 +422,9 @@
      */
     public void process(final String[] args) {
         final LinkedList<String> argList = new LinkedList<>();
+        addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, argList);
         Collections.addAll(argList, args);
-
-        final String extra = getStringProperty(NASHORN_ARGS_PROPERTY, null);
-        if (extra != null) {
-            final StringTokenizer st = new StringTokenizer(extra);
-            while (st.hasMoreTokens()) {
-                argList.add(st.nextToken());
-            }
-        }
+        addSystemProperties(NASHORN_ARGS_PROPERTY, argList);
 
         while (!argList.isEmpty()) {
             final String arg = argList.remove(0);
@@ -496,6 +506,16 @@
         }
     }
 
+    private static void addSystemProperties(final String sysPropName, final List<String> argList) {
+        final String sysArgs = getStringProperty(sysPropName, null);
+        if (sysArgs != null) {
+            final StringTokenizer st = new StringTokenizer(sysArgs);
+            while (st.hasMoreTokens()) {
+                argList.add(st.nextToken());
+            }
+        }
+    }
+
     private static OptionTemplate getOptionTemplate(final String key) {
         for (final OptionTemplate t : Options.validOptions) {
             if (t.matches(key)) {
@@ -518,14 +538,12 @@
         case "keyvalues":
             return new KeyValueOption(value);
         case "log":
-            final KeyValueOption kv = new KeyValueOption(value);
-            Logging.initialize(kv.getValues());
-            return kv;
+            return new LoggingOption(value);
         case "boolean":
             return new Option<>(value != null && Boolean.parseBoolean(value));
         case "integer":
             try {
-                return new Option<>((value == null) ? 0 : Integer.parseInt(value));
+                return new Option<>(value == null ? 0 : Integer.parseInt(value));
             } catch (final NumberFormatException nfe) {
                 throw new IllegalOptionException(t);
             }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
index f515802..525a2a5 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JdkRegExp.java
@@ -25,8 +25,6 @@
 
 package jdk.nashorn.internal.runtime.regexp;
 
-import jdk.nashorn.internal.runtime.ParserException;
-
 import static java.util.regex.Pattern.CASE_INSENSITIVE;
 import static java.util.regex.Pattern.MULTILINE;
 import static java.util.regex.Pattern.UNICODE_CASE;
@@ -34,6 +32,7 @@
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
+import jdk.nashorn.internal.runtime.ParserException;
 
 /**
  * Default regular expression implementation based on java.util.regex package.
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
index 47dbd7c..a602338 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/JoniRegExp.java
@@ -25,6 +25,8 @@
 
 package jdk.nashorn.internal.runtime.regexp;
 
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
 import jdk.nashorn.internal.runtime.ParserException;
 import jdk.nashorn.internal.runtime.regexp.joni.Matcher;
 import jdk.nashorn.internal.runtime.regexp.joni.Option;
@@ -33,9 +35,6 @@
 import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
 import jdk.nashorn.internal.runtime.regexp.joni.exception.JOniException;
 
-import java.util.regex.Pattern;
-import java.util.regex.PatternSyntaxException;
-
 /**
  * Regular expression implementation based on the Joni engine from the JRuby project.
  */
@@ -77,7 +76,7 @@
             }
 
             if (parsed != null) {
-                char[] javaPattern = parsed.getJavaPattern().toCharArray();
+                final char[] javaPattern = parsed.getJavaPattern().toCharArray();
                 this.regex = new Regex(javaPattern, 0, javaPattern.length, option, Syntax.JAVASCRIPT);
                 this.groupsInNegativeLookahead = parsed.getGroupsInNegativeLookahead();
             }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java
index 65c944e..ac57c9f 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExp.java
@@ -25,12 +25,11 @@
 
 package jdk.nashorn.internal.runtime.regexp;
 
+import java.util.regex.MatchResult;
 import jdk.nashorn.internal.runtime.BitVector;
 import jdk.nashorn.internal.runtime.ECMAErrors;
 import jdk.nashorn.internal.runtime.ParserException;
 
-import java.util.regex.MatchResult;
-
 /**
  * This is the base class for representing a parsed regular expression.
  *
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java
index f4edecc..88b023a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java
@@ -31,7 +31,6 @@
 import java.util.List;
 import java.util.Map;
 import java.util.regex.PatternSyntaxException;
-
 import jdk.nashorn.internal.parser.Lexer;
 import jdk.nashorn.internal.parser.Scanner;
 import jdk.nashorn.internal.runtime.BitVector;
@@ -101,7 +100,7 @@
 
     private void processForwardReferences() {
 
-        Iterator<Integer> iterator = forwardReferences.descendingIterator();
+        final Iterator<Integer> iterator = forwardReferences.descendingIterator();
         while (iterator.hasNext()) {
             final int pos = iterator.next();
             final int num = iterator.next();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
index eb612cd..6a9ebc1 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Analyser.java
@@ -29,7 +29,6 @@
 import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.isRepeatInfinite;
 
 import java.util.HashSet;
-
 import jdk.nashorn.internal.runtime.regexp.joni.ast.AnchorNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.BackRefNode;
 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
@@ -50,7 +49,7 @@
 
 final class Analyser extends Parser {
 
-    protected Analyser(ScanEnvironment env, char[] chars, int p, int end) {
+    protected Analyser(final ScanEnvironment env, final char[] chars, final int p, final int end) {
         super(env, chars, p, end);
     }
 
@@ -117,7 +116,7 @@
         } // DEBUG_COMPILE
     }
 
-    private void swap(Node a, Node b) {
+    private void swap(final Node a, final Node b) {
         a.swap(b);
 
         if (root == b) {
@@ -128,7 +127,7 @@
     }
 
     // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
-    private int quantifiersMemoryInfo(Node node) {
+    private int quantifiersMemoryInfo(final Node node) {
         int info = 0;
 
         switch(node.getType()) {
@@ -136,20 +135,20 @@
         case NodeType.ALT:
             ConsAltNode can = (ConsAltNode)node;
             do {
-                int v = quantifiersMemoryInfo(can.car);
+                final int v = quantifiersMemoryInfo(can.car);
                 if (v > info) info = v;
             } while ((can = can.cdr) != null);
             break;
 
         case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             if (qn.upper != 0) {
                 info = quantifiersMemoryInfo(qn.target);
             }
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.MEMORY:
                 return TargetInfo.IS_EMPTY_MEM;
@@ -177,12 +176,12 @@
         return info;
     }
 
-    private int getMinMatchLength(Node node) {
+    private int getMinMatchLength(final Node node) {
         int min = 0;
 
         switch (node.getType()) {
         case NodeType.BREF:
-            BackRefNode br = (BackRefNode)node;
+            final BackRefNode br = (BackRefNode)node;
             if (br.isRecursion()) break;
 
             if (br.backRef > env.numMem) {
@@ -202,8 +201,8 @@
         case NodeType.ALT:
             ConsAltNode y = (ConsAltNode)node;
             do {
-                Node x = y.car;
-                int tmin = getMinMatchLength(x);
+                final Node x = y.car;
+                final int tmin = getMinMatchLength(x);
                 if (y == node) {
                     min = tmin;
                 } else if (min > tmin) {
@@ -226,7 +225,7 @@
             break;
 
         case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             if (qn.lower > 0) {
                 min = getMinMatchLength(qn.target);
                 min = MinMaxLen.distanceMultiply(min, qn.lower);
@@ -234,7 +233,7 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.MEMORY:
                 if (en.isMinFixed()) {
@@ -261,14 +260,14 @@
         return min;
     }
 
-    private int getMaxMatchLength(Node node) {
+    private int getMaxMatchLength(final Node node) {
         int max = 0;
 
         switch (node.getType()) {
         case NodeType.LIST:
             ConsAltNode ln = (ConsAltNode)node;
             do {
-                int tmax = getMaxMatchLength(ln.car);
+                final int tmax = getMaxMatchLength(ln.car);
                 max = MinMaxLen.distanceAdd(max, tmax);
             } while ((ln = ln.cdr) != null);
             break;
@@ -276,7 +275,7 @@
         case NodeType.ALT:
             ConsAltNode an = (ConsAltNode)node;
             do {
-                int tmax = getMaxMatchLength(an.car);
+                final int tmax = getMaxMatchLength(an.car);
                 if (max < tmax) max = tmax;
             } while ((an = an.cdr) != null);
             break;
@@ -295,7 +294,7 @@
             break;
 
         case NodeType.BREF:
-            BackRefNode br = (BackRefNode)node;
+            final BackRefNode br = (BackRefNode)node;
             if (br.isRecursion()) {
                 max = MinMaxLen.INFINITE_DISTANCE;
                 break;
@@ -304,12 +303,12 @@
             if (br.backRef > env.numMem) {
                 throw new ValueException(ERR_INVALID_BACKREF);
             }
-            int tmax = getMaxMatchLength(env.memNodes[br.backRef]);
+            final int tmax = getMaxMatchLength(env.memNodes[br.backRef]);
             if (max < tmax) max = tmax;
             break;
 
         case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             if (qn.upper != 0) {
                 max = getMaxMatchLength(qn.target);
                 if (max != 0) {
@@ -323,7 +322,7 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.MEMORY:
                 if (en.isMaxFixed()) {
@@ -352,11 +351,11 @@
 
     private static final int GET_CHAR_LEN_VARLEN            = -1;
     private static final int GET_CHAR_LEN_TOP_ALT_VARLEN    = -2;
-    protected final int getCharLengthTree(Node node) {
+    protected final int getCharLengthTree(final Node node) {
         return getCharLengthTree(node, 0);
     }
 
-    private int getCharLengthTree(Node node, int level) {
+    private int getCharLengthTree(final Node node, int level) {
         level++;
 
         int len = 0;
@@ -366,7 +365,7 @@
         case NodeType.LIST:
             ConsAltNode ln = (ConsAltNode)node;
             do {
-                int tlen = getCharLengthTree(ln.car, level);
+                final int tlen = getCharLengthTree(ln.car, level);
                 if (returnCode == 0) len = MinMaxLen.distanceAdd(len, tlen);
             } while (returnCode == 0 && (ln = ln.cdr) != null);
             break;
@@ -377,7 +376,7 @@
 
             int tlen = getCharLengthTree(an.car, level);
             while (returnCode == 0 && (an = an.cdr) != null) {
-                int tlen2 = getCharLengthTree(an.car, level);
+                final int tlen2 = getCharLengthTree(an.car, level);
                 if (returnCode == 0) {
                     if (tlen != tlen2) varLen = true;
                 }
@@ -397,12 +396,12 @@
             break;
 
         case NodeType.STR:
-            StringNode sn = (StringNode)node;
+            final StringNode sn = (StringNode)node;
             len = sn.length();
             break;
 
         case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             if (qn.lower == qn.upper) {
                 tlen = getCharLengthTree(qn.target, level);
                 if (returnCode == 0) len = MinMaxLen.distanceMultiply(tlen, qn.lower);
@@ -418,7 +417,7 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             switch(en.type) {
             case EncloseType.MEMORY:
                 if (en.isCLenFixed()) {
@@ -455,7 +454,7 @@
         // !retry:!
         retry: while(true) {
 
-        int yType = y.getType();
+        final int yType = y.getType();
 
         switch(x.getType()) {
         case NodeType.CTYPE:
@@ -482,12 +481,12 @@
             break;
 
         case NodeType.CCLASS:
-            CClassNode xc = (CClassNode)x;
+            final CClassNode xc = (CClassNode)x;
 
             switch(yType) {
 
             case NodeType.CCLASS:
-                CClassNode yc = (CClassNode)y;
+                final CClassNode yc = (CClassNode)y;
 
                 for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
                     boolean v = xc.bs.at(i);
@@ -514,18 +513,18 @@
             break; // case NodeType.CCLASS
 
         case NodeType.STR:
-            StringNode xs = (StringNode)x;
+            final StringNode xs = (StringNode)x;
             if (xs.length() == 0) break;
 
             switch (yType) {
 
             case NodeType.CCLASS:
-                CClassNode cc = (CClassNode)y;
-                int code = xs.chars[xs.p];
+                final CClassNode cc = (CClassNode)y;
+                final int code = xs.chars[xs.p];
                 return !cc.isCodeInCC(code);
 
             case NodeType.STR:
-                StringNode ys = (StringNode)y;
+                final StringNode ys = (StringNode)y;
                 int len = xs.length();
                 if (len > ys.length()) len = ys.length();
                 if (xs.isAmbig() || ys.isAmbig()) {
@@ -551,7 +550,7 @@
         return false;
     }
 
-    private Node getHeadValueNode(Node node, boolean exact) {
+    private Node getHeadValueNode(final Node node, final boolean exact) {
         Node n = null;
 
         switch(node.getType()) {
@@ -570,7 +569,7 @@
             break;
 
         case NodeType.STR:
-            StringNode sn = (StringNode)node;
+            final StringNode sn = (StringNode)node;
             if (sn.end <= sn.p) break; // ???
 
             if (exact && !sn.isRaw() && isIgnoreCase(regex.options)){
@@ -581,7 +580,7 @@
             break;
 
         case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             if (qn.lower > 0) {
                 if (qn.headExact != null) {
                     n = qn.headExact;
@@ -592,11 +591,11 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
 
             switch (en.type) {
             case EncloseType.OPTION:
-                int options = regex.options;
+                final int options = regex.options;
                 regex.options = en.option;
                 n = getHeadValueNode(en.target, exact);
                 regex.options = options;
@@ -610,7 +609,7 @@
             break;
 
         case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
+            final AnchorNode an = (AnchorNode)node;
             if (an.type == AnchorType.PREC_READ) n = getHeadValueNode(an.target, exact);
             break;
 
@@ -622,7 +621,7 @@
     }
 
     // true: invalid
-    private boolean checkTypeTree(Node node, int typeMask, int encloseMask, int anchorMask) {
+    private boolean checkTypeTree(final Node node, final int typeMask, final int encloseMask, final int anchorMask) {
         if ((node.getType2Bit() & typeMask) == 0) return true;
 
         boolean invalid = false;
@@ -641,13 +640,13 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             if ((en.type & encloseMask) == 0) return true;
             invalid = checkTypeTree(en.target, typeMask, encloseMask, anchorMask);
             break;
 
         case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
+            final AnchorNode an = (AnchorNode)node;
             if ((an.type & anchorMask) == 0) return true;
 
             if (an.target != null) invalid = checkTypeTree(an.target, typeMask, encloseMask, anchorMask);
@@ -666,14 +665,14 @@
     (?<!A|B) ==> (?<!A)(?<!B)
      */
     private Node divideLookBehindAlternatives(Node node) {
-        AnchorNode an = (AnchorNode)node;
-        int anchorType = an.type;
+        final AnchorNode an = (AnchorNode)node;
+        final int anchorType = an.type;
         Node head = an.target;
         Node np = ((ConsAltNode)head).car;
 
         swap(node, head);
 
-        Node tmp = node;
+        final Node tmp = node;
         node = head;
         head = tmp;
 
@@ -682,7 +681,7 @@
         np = node;
 
         while ((np = ((ConsAltNode)np).cdr) != null) {
-            AnchorNode insert = new AnchorNode(anchorType);
+            final AnchorNode insert = new AnchorNode(anchorType);
             insert.setTarget(((ConsAltNode)np).car);
             ((ConsAltNode)np).setCar(insert);
         }
@@ -697,9 +696,9 @@
         return node;
     }
 
-    private Node setupLookBehind(Node node) {
-        AnchorNode an = (AnchorNode)node;
-        int len = getCharLengthTree(an.target);
+    private Node setupLookBehind(final Node node) {
+        final AnchorNode an = (AnchorNode)node;
+        final int len = getCharLengthTree(an.target);
         switch(returnCode) {
         case 0:
             an.charLength = len;
@@ -716,16 +715,16 @@
         return node;
     }
 
-    private void nextSetup(Node node, Node nextNode) {
+    private void nextSetup(Node node, final Node nextNode) {
         // retry:
         retry: while(true) {
 
-        int type = node.getType();
+        final int type = node.getType();
         if (type == NodeType.QTFR) {
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             if (qn.greedy && isRepeatInfinite(qn.upper)) {
                 if (Config.USE_QTFR_PEEK_NEXT) {
-                    StringNode n = (StringNode)getHeadValueNode(nextNode, true);
+                    final StringNode n = (StringNode)getHeadValueNode(nextNode, true);
                     /* '\0': for UTF-16BE etc... */
                     if (n != null && n.chars[n.p] != 0) { // ?????????
                         qn.nextHeadExact = n;
@@ -734,11 +733,11 @@
                 /* automatic posseivation a*b ==> (?>a*)b */
                 if (qn.lower <= 1) {
                     if (qn.target.isSimple()) {
-                        Node x = getHeadValueNode(qn.target, false);
+                        final Node x = getHeadValueNode(qn.target, false);
                         if (x != null) {
-                            Node y = getHeadValueNode(nextNode, false);
+                            final Node y = getHeadValueNode(nextNode, false);
                             if (y != null && isNotIncluded(x, y)) {
-                                EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); //onig_node_new_enclose
+                                final EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); //onig_node_new_enclose
                                 en.setStopBtSimpleRepeat();
                                 //en.setTarget(qn.target); // optimize it ??
                                 swap(node, en);
@@ -750,7 +749,7 @@
                 }
             }
         } else if (type == NodeType.ENCLOSE) {
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             if (en.isMemory()) {
                 node = en.target;
                 // !goto retry;!
@@ -762,15 +761,15 @@
         } // while
     }
 
-    private void updateStringNodeCaseFoldMultiByte(StringNode sn) {
-        char[] chars = sn.chars;
-        int end = sn.end;
+    private void updateStringNodeCaseFoldMultiByte(final StringNode sn) {
+        final char[] chars = sn.chars;
+        final int end = sn.end;
         value = sn.p;
         int sp = 0;
         char buf;
 
         while (value < end) {
-            int ovalue = value;
+            final int ovalue = value;
             buf = EncodingHelper.toLowerCase(chars[value++]);
 
             if (chars[ovalue] != buf) {
@@ -781,7 +780,7 @@
                 while (value < end) {
                     buf = EncodingHelper.toLowerCase(chars[value++]);
                     if (sp >= sbuf.length) {
-                        char[]tmp = new char[sbuf.length << 1];
+                        final char[]tmp = new char[sbuf.length << 1];
                         System.arraycopy(sbuf, 0, tmp, 0, sbuf.length);
                         sbuf = tmp;
                     }
@@ -794,13 +793,13 @@
         }
     }
 
-    private void updateStringNodeCaseFold(Node node) {
-        StringNode sn = (StringNode)node;
+    private void updateStringNodeCaseFold(final Node node) {
+        final StringNode sn = (StringNode)node;
         updateStringNodeCaseFoldMultiByte(sn);
     }
 
-    private Node expandCaseFoldMakeRemString(char[] chars, int p, int end) {
-        StringNode node = new StringNode(chars, p, end);
+    private Node expandCaseFoldMakeRemString(final char[] chars, final int p, final int end) {
+        final StringNode node = new StringNode(chars, p, end);
 
         updateStringNodeCaseFold(node);
         node.setAmbig();
@@ -808,8 +807,8 @@
         return node;
     }
 
-    private boolean expandCaseFoldStringAlt(int itemNum, char[] items,
-                                              char[] chars, int p, int slen, int end, ObjPtr<Node> node) {
+    private boolean expandCaseFoldStringAlt(final int itemNum, final char[] items,
+                                              final char[] chars, final int p, final int slen, final int end, final ObjPtr<Node> node) {
 
         ConsAltNode altNode;
         node.p = altNode = newAltNode(null, null);
@@ -822,7 +821,7 @@
 
             snode.catCode(items[i]);
 
-            ConsAltNode an = newAltNode(null, null);
+            final ConsAltNode an = newAltNode(null, null);
             an.setCar(snode);
             altNode.setCdr(an);
             altNode = an;
@@ -831,22 +830,22 @@
     }
 
     private static final int THRESHOLD_CASE_FOLD_ALT_FOR_EXPANSION = 8;
-    private Node expandCaseFoldString(Node node) {
-        StringNode sn = (StringNode)node;
+    private Node expandCaseFoldString(final Node node) {
+        final StringNode sn = (StringNode)node;
 
         if (sn.isAmbig() || sn.length() <= 0) return node;
 
-        char[] chars = sn.chars;
+        final char[] chars = sn.chars;
         int p = sn.p;
-        int end = sn.end;
+        final int end = sn.end;
         int altNum = 1;
 
         ConsAltNode topRoot = null, root = null;
-        ObjPtr<Node> prevNode = new ObjPtr<Node>();
+        final ObjPtr<Node> prevNode = new ObjPtr<Node>();
         StringNode stringNode = null;
 
         while (p < end) {
-            char[] items = EncodingHelper.caseFoldCodesByString(regex.caseFoldFlag, chars[p]);
+            final char[] items = EncodingHelper.caseFoldCodesByString(regex.caseFoldFlag, chars[p]);
 
             if (items.length == 0) {
                 if (stringNode == null) {
@@ -877,7 +876,7 @@
         }
 
         if (p < end) {
-            Node srem = expandCaseFoldMakeRemString(chars, p, end);
+            final Node srem = expandCaseFoldMakeRemString(chars, p, end);
 
             if (prevNode.p != null && root == null) {
                 topRoot = root = ConsAltNode.listAdd(null, prevNode.p);
@@ -890,7 +889,7 @@
             }
         }
         /* ending */
-        Node xnode = topRoot != null ? topRoot : prevNode.p;
+        final Node xnode = topRoot != null ? topRoot : prevNode.p;
 
         swap(node, xnode);
         return xnode;
@@ -946,7 +945,7 @@
             break;
 
         case NodeType.BREF:
-            BackRefNode br = (BackRefNode)node;
+            final BackRefNode br = (BackRefNode)node;
             if (br.backRef > env.numMem) {
                 throw new ValueException(ERR_INVALID_BACKREF);
             }
@@ -956,17 +955,17 @@
             break;
 
         case NodeType.QTFR:
-            QuantifierNode qn = (QuantifierNode)node;
+            final QuantifierNode qn = (QuantifierNode)node;
             Node target = qn.target;
 
             if ((state & IN_REPEAT) != 0) qn.setInRepeat();
 
             if (isRepeatInfinite(qn.upper) || qn.lower >= 1) {
-                int d = getMinMatchLength(target);
+                final int d = getMinMatchLength(target);
                 if (d == 0) {
                     qn.targetEmptyInfo = TargetInfo.IS_EMPTY;
                     if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) {
-                        int info = quantifiersMemoryInfo(target);
+                        final int info = quantifiersMemoryInfo(target);
                         if (info > 0) qn.targetEmptyInfo = info;
                     } // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
                     // strange stuff here (turned off)
@@ -982,12 +981,12 @@
             if (target.getType() == NodeType.STR) {
                 if (!isRepeatInfinite(qn.lower) && qn.lower == qn.upper &&
                     qn.lower > 1 && qn.lower <= EXPAND_STRING_MAX_LENGTH) {
-                    StringNode sn = (StringNode)target;
-                    int len = sn.length();
+                    final StringNode sn = (StringNode)target;
+                    final int len = sn.length();
 
                     if (len * qn.lower <= EXPAND_STRING_MAX_LENGTH) {
-                        StringNode str = qn.convertToString(sn.flag);
-                        int n = qn.lower;
+                        final StringNode str = qn.convertToString(sn.flag);
+                        final int n = qn.lower;
                         for (int i = 0; i < n; i++) {
                             str.cat(sn.chars, sn.p, sn.end);
                         }
@@ -999,7 +998,7 @@
             if (Config.USE_OP_PUSH_OR_JUMP_EXACT) {
                 if (qn.greedy && qn.targetEmptyInfo != 0) {
                     if (target.getType() == NodeType.QTFR) {
-                        QuantifierNode tqn = (QuantifierNode)target;
+                        final QuantifierNode tqn = (QuantifierNode)target;
                         if (tqn.headExact != null) {
                             qn.headExact = tqn.headExact;
                             tqn.headExact = null;
@@ -1012,10 +1011,10 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.OPTION:
-                int options = regex.options;
+                final int options = regex.options;
                 regex.options = en.option;
                 setupTree(en.target, state);
                 regex.options = options;
@@ -1033,7 +1032,7 @@
             case EncloseType.STOP_BACKTRACK:
                 setupTree(en.target, state);
                 if (en.target.getType() == NodeType.QTFR) {
-                    QuantifierNode tqn = (QuantifierNode)en.target;
+                    final QuantifierNode tqn = (QuantifierNode)en.target;
                     if (isRepeatInfinite(tqn.upper) && tqn.lower <= 1 && tqn.greedy) {
                         /* (?>a*), a*+ etc... */
                         if (tqn.target.isSimple()) en.setStopBtSimpleRepeat();
@@ -1045,7 +1044,7 @@
             break;
 
         case NodeType.ANCHOR:
-            AnchorNode an = (AnchorNode)node;
+            final AnchorNode an = (AnchorNode)node;
             switch (an.type) {
             case AnchorType.PREC_READ:
                 setupTree(an.target, state);
@@ -1081,14 +1080,14 @@
     }
 
     private static final int MAX_NODE_OPT_INFO_REF_COUNT   = 5;
-    private void optimizeNodeLeft(Node node, NodeOptInfo opt, OptEnvironment oenv) { // oenv remove, pass mmd
+    private void optimizeNodeLeft(final Node node, final NodeOptInfo opt, final OptEnvironment oenv) { // oenv remove, pass mmd
         opt.clear();
         opt.setBoundNode(oenv.mmd);
 
         switch (node.getType()) {
         case NodeType.LIST: {
-            OptEnvironment nenv = new OptEnvironment();
-            NodeOptInfo nopt = new NodeOptInfo();
+            final OptEnvironment nenv = new OptEnvironment();
+            final NodeOptInfo nopt = new NodeOptInfo();
             nenv.copy(oenv);
             ConsAltNode lin = (ConsAltNode)node;
             do {
@@ -1100,7 +1099,7 @@
         }
 
         case NodeType.ALT: {
-            NodeOptInfo nopt = new NodeOptInfo();
+            final NodeOptInfo nopt = new NodeOptInfo();
             ConsAltNode aln = (ConsAltNode)node;
             do {
                 optimizeNodeLeft(aln.car, nopt, oenv);
@@ -1114,9 +1113,9 @@
         }
 
         case NodeType.STR: {
-            StringNode sn = (StringNode)node;
+            final StringNode sn = (StringNode)node;
 
-            int slen = sn.length();
+            final int slen = sn.length();
 
             if (!sn.isAmbig()) {
                 opt.exb.concatStr(sn.chars, sn.p, sn.end, sn.isRaw());
@@ -1150,13 +1149,13 @@
         }
 
         case NodeType.CCLASS: {
-            CClassNode cc = (CClassNode)node;
+            final CClassNode cc = (CClassNode)node;
             /* no need to check ignore case. (setted in setup_tree()) */
             if (cc.mbuf != null || cc.isNot()) {
                 opt.length.set(1, 1);
             } else {
                 for (int i=0; i<BitSet.SINGLE_BYTE_SIZE; i++) {
-                    boolean z = cc.bs.at(i);
+                    final boolean z = cc.bs.at(i);
                     if ((z && !cc.isNot()) || (!z && cc.isNot())) {
                         opt.map.addChar(i);
                     }
@@ -1172,7 +1171,7 @@
         }
 
         case NodeType.ANCHOR: {
-            AnchorNode an = (AnchorNode)node;
+            final AnchorNode an = (AnchorNode)node;
             switch (an.type) {
             case AnchorType.BEGIN_BUF:
             case AnchorType.BEGIN_POSITION:
@@ -1184,7 +1183,7 @@
                 break;
 
             case AnchorType.PREC_READ:
-                NodeOptInfo nopt = new NodeOptInfo();
+                final NodeOptInfo nopt = new NodeOptInfo();
                 optimizeNodeLeft(an.target, nopt, oenv);
                 if (nopt.exb.length > 0) {
                     opt.expr.copy(nopt.exb);
@@ -1205,17 +1204,17 @@
         }
 
         case NodeType.BREF: {
-            BackRefNode br = (BackRefNode)node;
+            final BackRefNode br = (BackRefNode)node;
 
             if (br.isRecursion()) {
                 opt.length.set(0, MinMaxLen.INFINITE_DISTANCE);
                 break;
             }
 
-            Node[]nodes = oenv.scanEnv.memNodes;
+            final Node[]nodes = oenv.scanEnv.memNodes;
 
-            int min = getMinMatchLength(nodes[br.backRef]);
-            int max = getMaxMatchLength(nodes[br.backRef]);
+            final int min = getMinMatchLength(nodes[br.backRef]);
+            final int max = getMaxMatchLength(nodes[br.backRef]);
 
             opt.length.set(min, max);
             break;
@@ -1223,8 +1222,8 @@
 
 
         case NodeType.QTFR: {
-            NodeOptInfo nopt = new NodeOptInfo();
-            QuantifierNode qn = (QuantifierNode)node;
+            final NodeOptInfo nopt = new NodeOptInfo();
+            final QuantifierNode qn = (QuantifierNode)node;
             optimizeNodeLeft(qn.target, nopt, oenv);
             if (qn.lower == 0 && isRepeatInfinite(qn.upper)) {
                 if (oenv.mmd.max == 0 && qn.target.getType() == NodeType.CANY && qn.greedy) {
@@ -1258,7 +1257,7 @@
 
                 }
             }
-            int min = MinMaxLen.distanceMultiply(nopt.length.min, qn.lower);
+            final int min = MinMaxLen.distanceMultiply(nopt.length.min, qn.lower);
             int max;
             if (isRepeatInfinite(qn.upper)) {
                 max = nopt.length.max > 0 ? MinMaxLen.INFINITE_DISTANCE : 0;
@@ -1270,10 +1269,10 @@
         }
 
         case NodeType.ENCLOSE: {
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             switch (en.type) {
             case EncloseType.OPTION:
-                int save = oenv.options;
+                final int save = oenv.options;
                 oenv.options = en.option;
                 optimizeNodeLeft(en.target, opt, oenv);
                 oenv.options = save;
@@ -1308,9 +1307,9 @@
         } // switch
     }
 
-    protected final void setOptimizedInfoFromTree(Node node) {
-        NodeOptInfo opt = new NodeOptInfo();
-        OptEnvironment oenv = new OptEnvironment();
+    protected final void setOptimizedInfoFromTree(final Node node) {
+        final NodeOptInfo opt = new NodeOptInfo();
+        final OptEnvironment oenv = new OptEnvironment();
 
         oenv.options = regex.options;
         oenv.caseFoldFlag = regex.caseFoldFlag;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java
index dda5b73..0a6d4b0 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFold.java
@@ -24,14 +24,14 @@
 final class ApplyCaseFold {
 
     // i_apply_case_fold
-    public void apply(int from, int to, Object o) {
-        ApplyCaseFoldArg arg = (ApplyCaseFoldArg)o;
+    public void apply(final int from, final int to, final Object o) {
+        final ApplyCaseFoldArg arg = (ApplyCaseFoldArg)o;
 
-        ScanEnvironment env = arg.env;
-        CClassNode cc = arg.cc;
-        BitSet bs = cc.bs;
+        final ScanEnvironment env = arg.env;
+        final CClassNode cc = arg.cc;
+        final BitSet bs = cc.bs;
 
-        boolean inCC = cc.isCodeInCC(from);
+        final boolean inCC = cc.isCodeInCC(from);
 
         if (Config.CASE_FOLD_IS_APPLIED_INSIDE_NEGATIVE_CCLASS) {
             if ((inCC && !cc.isNot()) || (!inCC && cc.isNot())) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java
index e991aed..c199bea 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ApplyCaseFoldArg.java
@@ -28,7 +28,7 @@
     ConsAltNode altRoot;
     ConsAltNode tail;
 
-    public ApplyCaseFoldArg(ScanEnvironment env, CClassNode cc) {
+    public ApplyCaseFoldArg(final ScanEnvironment env, final CClassNode cc) {
         this.env = env;
         this.cc = cc;
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
index 33d56c1..294113e 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ArrayCompiler.java
@@ -47,13 +47,13 @@
     private char[][] templates;
     private int templateNum;
 
-    ArrayCompiler(Analyser analyser) {
+    ArrayCompiler(final Analyser analyser) {
         super(analyser);
     }
 
     @Override
     protected final void prepare() {
-        int codeSize = Config.USE_STRING_TEMPLATES ? 8 : ((analyser.getEnd() - analyser.getBegin()) * 2 + 2);
+        final int codeSize = Config.USE_STRING_TEMPLATES ? 8 : ((analyser.getEnd() - analyser.getBegin()) * 2 + 2);
         code = new int[codeSize];
         codeLength = 0;
     }
@@ -71,7 +71,7 @@
     }
 
     @Override
-    protected void compileAltNode(ConsAltNode node) {
+    protected void compileAltNode(final ConsAltNode node) {
         ConsAltNode aln = node;
         int len = 0;
 
@@ -82,7 +82,7 @@
             }
         } while ((aln = aln.cdr) != null);
 
-        int pos = codeLength + len;  /* goal position */
+        final int pos = codeLength + len;  /* goal position */
 
         aln = node;
         do {
@@ -98,15 +98,15 @@
         } while ((aln = aln.cdr) != null);
     }
 
-    private boolean isNeedStrLenOpExact(int op) {
+    private boolean isNeedStrLenOpExact(final int op) {
         return  op == OPCode.EXACTN || op == OPCode.EXACTN_IC;
     }
 
-    private boolean opTemplated(int op) {
+    private boolean opTemplated(final int op) {
         return isNeedStrLenOpExact(op);
     }
 
-    private int selectStrOpcode(int strLength, boolean ignoreCase) {
+    private int selectStrOpcode(final int strLength, final boolean ignoreCase) {
         int op;
 
         if (ignoreCase) {
@@ -127,8 +127,8 @@
         return op;
     }
 
-    private void compileTreeEmptyCheck(Node node, int emptyInfo) {
-        int savedNumNullCheck = regex.numNullCheck;
+    private void compileTreeEmptyCheck(final Node node, final int emptyInfo) {
+        final int savedNumNullCheck = regex.numNullCheck;
 
         if (emptyInfo != 0) {
             addOpcode(OPCode.NULL_CHECK_START);
@@ -155,8 +155,8 @@
         }
     }
 
-    private int addCompileStringlength(char[] chars, int p, int strLength, boolean ignoreCase) {
-        int op = selectStrOpcode(strLength, ignoreCase);
+    private int addCompileStringlength(final char[] chars, final int p, final int strLength, final boolean ignoreCase) {
+        final int op = selectStrOpcode(strLength, ignoreCase);
         int len = OPSize.OPCODE;
 
         if (Config.USE_STRING_TEMPLATES && opTemplated(op)) {
@@ -170,8 +170,8 @@
     }
 
     @Override
-    protected final void addCompileString(char[] chars, int p, int strLength, boolean ignoreCase) {
-        int op = selectStrOpcode(strLength, ignoreCase);
+    protected final void addCompileString(final char[] chars, final int p, final int strLength, final boolean ignoreCase) {
+        final int op = selectStrOpcode(strLength, ignoreCase);
         addOpcode(op);
 
         if (isNeedStrLenOpExact(op)) {
@@ -187,15 +187,15 @@
         }
     }
 
-    private int compileLengthStringNode(Node node) {
-        StringNode sn = (StringNode)node;
+    private int compileLengthStringNode(final Node node) {
+        final StringNode sn = (StringNode)node;
         if (sn.length() <= 0) return 0;
-        boolean ambig = sn.isAmbig();
+        final boolean ambig = sn.isAmbig();
 
         int p, prev;
         p = prev = sn.p;
-        int end = sn.end;
-        char[] chars = sn.chars;
+        final int end = sn.end;
+        final char[] chars = sn.chars;
         p++;
 
         int slen = 1;
@@ -205,22 +205,22 @@
             slen++;
             p++;
         }
-        int r = addCompileStringlength(chars, prev, slen, ambig);
+        final int r = addCompileStringlength(chars, prev, slen, ambig);
         rlen += r;
         return rlen;
     }
 
-    private int compileLengthStringRawNode(StringNode sn) {
+    private int compileLengthStringRawNode(final StringNode sn) {
         if (sn.length() <= 0) return 0;
         return addCompileStringlength(sn.chars, sn.p, sn.length(), false);
     }
 
-    private void addMultiByteCClass(CodeRangeBuffer mbuf) {
+    private void addMultiByteCClass(final CodeRangeBuffer mbuf) {
         addLength(mbuf.used);
         addInts(mbuf.p, mbuf.used);
     }
 
-    private int compileLengthCClassNode(CClassNode cc) {
+    private int compileLengthCClassNode(final CClassNode cc) {
         if (cc.isShare()) return OPSize.OPCODE + OPSize.POINTER;
 
         int len;
@@ -239,7 +239,7 @@
     }
 
     @Override
-    protected void compileCClassNode(CClassNode cc) {
+    protected void compileCClassNode(final CClassNode cc) {
         if (cc.isShare()) { // shared char class
             addOpcode(OPCode.CCLASS_NODE);
             addPointer(cc);
@@ -284,7 +284,7 @@
     }
 
     @Override
-    protected void compileBackrefNode(BackRefNode node) {
+    protected void compileBackrefNode(final BackRefNode node) {
         if (isIgnoreCase(regex.options)) {
             addOpcode(OPCode.BACKREFN_IC);
             addMemNum(node.backRef);
@@ -305,7 +305,7 @@
     }
 
     private static final int REPEAT_RANGE_ALLOC = 8;
-    private void entryRepeatRange(int id, int lower, int upper) {
+    private void entryRepeatRange(final int id, final int lower, final int upper) {
         if (regex.repeatRangeLo == null) {
             regex.repeatRangeLo = new int[REPEAT_RANGE_ALLOC];
             regex.repeatRangeHi = new int[REPEAT_RANGE_ALLOC];
@@ -322,8 +322,8 @@
         regex.repeatRangeHi[id] = isRepeatInfinite(upper) ? 0x7fffffff : upper;
     }
 
-    private void compileRangeRepeatNode(QuantifierNode qn, int targetLen, int emptyInfo) {
-        int numRepeat = regex.numRepeat;
+    private void compileRangeRepeatNode(final QuantifierNode qn, final int targetLen, final int emptyInfo) {
+        final int numRepeat = regex.numRepeat;
         addOpcode(qn.greedy ? OPCode.REPEAT : OPCode.REPEAT_NG);
         addMemNum(numRepeat); /* OP_REPEAT ID */
         regex.numRepeat++;
@@ -345,15 +345,15 @@
     private static final int QUANTIFIER_EXPAND_LIMIT_SIZE   = 50; // was 50
 
     @SuppressWarnings("unused")
-    private static boolean cknOn(int ckn) {
+    private static boolean cknOn(final int ckn) {
         return ckn > 0;
     }
 
-    private int compileNonCECLengthQuantifierNode(QuantifierNode qn) {
-        boolean infinite = isRepeatInfinite(qn.upper);
-        int emptyInfo = qn.targetEmptyInfo;
+    private int compileNonCECLengthQuantifierNode(final QuantifierNode qn) {
+        final boolean infinite = isRepeatInfinite(qn.upper);
+        final int emptyInfo = qn.targetEmptyInfo;
 
-        int tlen = compileLengthTree(qn.target);
+        final int tlen = compileLengthTree(qn.target);
 
         /* anychar repeat */
         if (qn.target.getType() == NodeType.CANY) {
@@ -408,11 +408,11 @@
     }
 
     @Override
-    protected void compileNonCECQuantifierNode(QuantifierNode qn) {
-        boolean infinite = isRepeatInfinite(qn.upper);
-        int emptyInfo = qn.targetEmptyInfo;
+    protected void compileNonCECQuantifierNode(final QuantifierNode qn) {
+        final boolean infinite = isRepeatInfinite(qn.upper);
+        final int emptyInfo = qn.targetEmptyInfo;
 
-        int tlen = compileLengthTree(qn.target);
+        final int tlen = compileLengthTree(qn.target);
 
         if (qn.isAnyCharStar()) {
             compileTreeNTimes(qn.target, qn.lower);
@@ -422,7 +422,7 @@
                 } else {
                     addOpcode(OPCode.ANYCHAR_STAR_PEEK_NEXT);
                 }
-                StringNode sn = (StringNode)qn.nextHeadExact;
+                final StringNode sn = (StringNode)qn.nextHeadExact;
                 addChars(sn.chars, sn.p, 1);
                 return;
             } else {
@@ -461,13 +461,13 @@
             if (qn.greedy) {
                 if (qn.headExact != null) {
                     addOpcodeRelAddr(OPCode.PUSH_OR_JUMP_EXACT1, modTLen + OPSize.JUMP);
-                    StringNode sn = (StringNode)qn.headExact;
+                    final StringNode sn = (StringNode)qn.headExact;
                     addChars(sn.chars, sn.p, 1);
                     compileTreeEmptyCheck(qn.target, emptyInfo);
                     addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + OPSize.PUSH_OR_JUMP_EXACT1));
                 } else if (qn.nextHeadExact != null) {
                     addOpcodeRelAddr(OPCode.PUSH_IF_PEEK_NEXT, modTLen + OPSize.JUMP);
-                    StringNode sn = (StringNode)qn.nextHeadExact;
+                    final StringNode sn = (StringNode)qn.nextHeadExact;
                     addChars(sn.chars, sn.p, 1);
                     compileTreeEmptyCheck(qn.target, emptyInfo);
                     addOpcodeRelAddr(OPCode.JUMP, -(modTLen + OPSize.JUMP + OPSize.PUSH_IF_PEEK_NEXT));
@@ -486,7 +486,7 @@
             compileTree(qn.target);
         } else if (!infinite && qn.greedy &&
                   (qn.upper == 1 || (tlen + OPSize.PUSH) * qn.upper <= QUANTIFIER_EXPAND_LIMIT_SIZE)) {
-            int n = qn.upper - qn.lower;
+            final int n = qn.upper - qn.lower;
             compileTreeNTimes(qn.target, qn.lower);
 
             for (int i=0; i<n; i++) {
@@ -502,10 +502,10 @@
         }
     }
 
-    private int compileLengthOptionNode(EncloseNode node) {
-        int prev = regex.options;
+    private int compileLengthOptionNode(final EncloseNode node) {
+        final int prev = regex.options;
         regex.options = node.option;
-        int tlen = compileLengthTree(node.target);
+        final int tlen = compileLengthTree(node.target);
         regex.options = prev;
 
         if (isDynamic(prev ^ node.option)) {
@@ -516,8 +516,8 @@
     }
 
     @Override
-    protected void compileOptionNode(EncloseNode node) {
-        int prev = regex.options;
+    protected void compileOptionNode(final EncloseNode node) {
+        final int prev = regex.options;
 
         if (isDynamic(prev ^ node.option)) {
             addOpcodeOption(OPCode.SET_OPTION_PUSH, node.option);
@@ -534,7 +534,7 @@
         }
     }
 
-    private int compileLengthEncloseNode(EncloseNode node) {
+    private int compileLengthEncloseNode(final EncloseNode node) {
         if (node.isOption()) {
             return compileLengthOptionNode(node);
         }
@@ -559,7 +559,7 @@
 
         case EncloseType.STOP_BACKTRACK:
             if (node.isStopBtSimpleRepeat()) {
-                QuantifierNode qn = (QuantifierNode)node.target;
+                final QuantifierNode qn = (QuantifierNode)node.target;
                 tlen = compileLengthTree(qn.target);
                 len = tlen * qn.lower + OPSize.PUSH + tlen + OPSize.POP + OPSize.JUMP;
             } else {
@@ -575,7 +575,7 @@
     }
 
     @Override
-    protected void compileEncloseNode(EncloseNode node) {
+    protected void compileEncloseNode(final EncloseNode node) {
         int len;
         switch (node.type) {
         case EncloseType.MEMORY:
@@ -598,7 +598,7 @@
 
         case EncloseType.STOP_BACKTRACK:
             if (node.isStopBtSimpleRepeat()) {
-                QuantifierNode qn = (QuantifierNode)node.target;
+                final QuantifierNode qn = (QuantifierNode)node.target;
 
                 compileTreeNTimes(qn.target, qn.lower);
 
@@ -620,7 +620,7 @@
         } // switch
     }
 
-    private int compileLengthAnchorNode(AnchorNode node) {
+    private int compileLengthAnchorNode(final AnchorNode node) {
         int tlen;
         if (node.target != null) {
             tlen = compileLengthTree(node.target);
@@ -654,7 +654,7 @@
     }
 
     @Override
-    protected void compileAnchorNode(AnchorNode node) {
+    protected void compileAnchorNode(final AnchorNode node) {
         int len;
         int n;
 
@@ -728,7 +728,7 @@
         } // switch
     }
 
-    private int compileLengthTree(Node node) {
+    private int compileLengthTree(final Node node) {
         int len = 0;
 
         switch (node.getType()) {
@@ -750,7 +750,7 @@
             break;
 
         case NodeType.STR:
-            StringNode sn = (StringNode)node;
+            final StringNode sn = (StringNode)node;
             if (sn.isRaw()) {
                 len = compileLengthStringRawNode(sn);
             } else {
@@ -768,7 +768,7 @@
             break;
 
         case NodeType.BREF:
-            BackRefNode br = (BackRefNode)node;
+            final BackRefNode br = (BackRefNode)node;
 
             len = ((!isIgnoreCase(regex.options) && br.backRef <= 2)
                     ? OPSize.OPCODE : (OPSize.OPCODE + OPSize.MEMNUM));
@@ -793,35 +793,35 @@
         return len;
     }
 
-    private void ensure(int size) {
+    private void ensure(final int size) {
         if (size >= code.length) {
             int length = code.length << 1;
             while (length <= size) length <<= 1;
-            int[]tmp = new int[length];
+            final int[]tmp = new int[length];
             System.arraycopy(code, 0, tmp, 0, code.length);
             code = tmp;
         }
     }
 
-    private void addInt(int i) {
+    private void addInt(final int i) {
         if (codeLength >= code.length) {
-            int[]tmp = new int[code.length << 1];
+            final int[]tmp = new int[code.length << 1];
             System.arraycopy(code, 0, tmp, 0, code.length);
             code = tmp;
         }
         code[codeLength++] = i;
     }
 
-    void setInt(int i, int offset) {
+    void setInt(final int i, final int offset) {
         ensure(offset);
         regex.code[offset] = i;
     }
 
-    private void addObject(Object o) {
+    private void addObject(final Object o) {
         if (regex.operands == null) {
             regex.operands = new Object[4];
         } else if (regex.operandLength >= regex.operands.length) {
-            Object[]tmp = new Object[regex.operands.length << 1];
+            final Object[]tmp = new Object[regex.operands.length << 1];
             System.arraycopy(regex.operands, 0, tmp, 0, regex.operands.length);
             regex.operands = tmp;
         }
@@ -829,20 +829,20 @@
         regex.operands[regex.operandLength++] = o;
     }
 
-    private void addChars(char[] chars, int p ,int length) {
+    private void addChars(final char[] chars, int p ,final int length) {
         ensure(codeLength + length);
-        int end = p + length;
+        final int end = p + length;
 
         while (p < end) code[codeLength++] = chars[p++];
     }
 
-    private void addInts(int[]ints, int length) {
+    private void addInts(final int[]ints, final int length) {
         ensure(codeLength + length);
         System.arraycopy(ints, 0, code, codeLength, length);
         codeLength += length;
     }
 
-    private void addOpcode(int opcode) {
+    private void addOpcode(final int opcode) {
         addInt(opcode);
 
         switch(opcode) {
@@ -880,50 +880,50 @@
     }
 
     @SuppressWarnings("unused")
-    private void addStateCheckNum(int num) {
+    private void addStateCheckNum(final int num) {
         addInt(num);
     }
 
-    private void addRelAddr(int addr) {
+    private void addRelAddr(final int addr) {
         addInt(addr);
     }
 
     @SuppressWarnings("unused")
-    private void addAbsAddr(int addr) {
+    private void addAbsAddr(final int addr) {
         addInt(addr);
     }
 
-    private void addLength(int length) {
+    private void addLength(final int length) {
         addInt(length);
     }
 
-    private void addMemNum(int num) {
+    private void addMemNum(final int num) {
         addInt(num);
     }
 
-    private void addPointer(Object o) {
+    private void addPointer(final Object o) {
         addObject(o);
     }
 
-    private void addOption(int option) {
+    private void addOption(final int option) {
         addInt(option);
     }
 
-    private void addOpcodeRelAddr(int opcode, int addr) {
+    private void addOpcodeRelAddr(final int opcode, final int addr) {
         addOpcode(opcode);
         addRelAddr(addr);
     }
 
-    private void addOpcodeOption(int opcode, int option) {
+    private void addOpcodeOption(final int opcode, final int option) {
         addOpcode(opcode);
         addOption(option);
     }
 
-    private void addTemplate(char[] chars) {
+    private void addTemplate(final char[] chars) {
         if (templateNum == 0) {
             templates = new char[2][];
         } else if (templateNum == templates.length) {
-            char[][] tmp = new char[templateNum * 2][];
+            final char[][] tmp = new char[templateNum * 2][];
             System.arraycopy(templates, 0, tmp, 0, templateNum);
             templates = tmp;
         }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
index 58ec56d..2aac96a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitSet.java
@@ -31,7 +31,7 @@
     private static final int BITS_TO_STRING_WRAP = 4;
     @Override
     public String toString() {
-        StringBuilder buffer = new StringBuilder();
+        final StringBuilder buffer = new StringBuilder();
         buffer.append("BitSet");
         for (int i=0; i<SINGLE_BYTE_SIZE; i++) {
             if ((i % (SINGLE_BYTE_SIZE / BITS_TO_STRING_WRAP)) == 0) buffer.append("\n  ");
@@ -40,15 +40,15 @@
         return buffer.toString();
     }
 
-    public boolean at(int pos) {
+    public boolean at(final int pos) {
         return (bits[pos >>> ROOM_SHIFT] & bit(pos)) != 0;
     }
 
-    public void set(int pos) {
+    public void set(final int pos) {
         bits[pos >>> ROOM_SHIFT] |= bit(pos);
     }
 
-    public void clear(int pos) {
+    public void clear(final int pos) {
         bits[pos >>> ROOM_SHIFT] &= ~bit(pos);
     }
 
@@ -63,7 +63,7 @@
         return true;
     }
 
-    public void setRange(int from, int to) {
+    public void setRange(final int from, final int to) {
         for (int i=from; i<=to && i < SINGLE_BYTE_SIZE; i++) set(i);
     }
 
@@ -71,19 +71,19 @@
         for (int i=0; i<BITSET_SIZE; i++) bits[i] = ~bits[i];
     }
 
-    public void invertTo(BitSet to) {
+    public void invertTo(final BitSet to) {
         for (int i=0; i<BITSET_SIZE; i++) to.bits[i] = ~bits[i];
     }
 
-    public void and(BitSet other) {
+    public void and(final BitSet other) {
         for (int i=0; i<BITSET_SIZE; i++) bits[i] &= other.bits[i];
     }
 
-    public void or(BitSet other) {
+    public void or(final BitSet other) {
         for (int i=0; i<BITSET_SIZE; i++) bits[i] |= other.bits[i];
     }
 
-    public void copy(BitSet other) {
+    public void copy(final BitSet other) {
         for (int i=0; i<BITSET_SIZE; i++) bits[i] = other.bits[i];
     }
 
@@ -95,7 +95,7 @@
         return num;
     }
 
-    static int bit(int pos){
+    static int bit(final int pos){
         return 1 << (pos % SINGLE_BYTE_SIZE);
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java
index 3052859..25806a5 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/BitStatus.java
@@ -30,11 +30,11 @@
         return -1;
     }
 
-    public static boolean bsAt(int stats, int n) {
+    public static boolean bsAt(final int stats, final int n) {
         return (n < BIT_STATUS_BITS_NUM ? stats & (1 << n) : (stats & 1)) != 0;
     }
 
-    public static int bsOnAt(int stats, int n) {
+    public static int bsOnAt(int stats, final int n) {
         if (n < BIT_STATUS_BITS_NUM) {
             stats |= (1 << n);
         } else {
@@ -43,7 +43,7 @@
         return stats;
     }
 
-    public static int bsOnOff(int v, int f, boolean negative) {
+    public static int bsOnOff(int v, final int f, final boolean negative) {
         if (negative) {
             v &= ~f;
         } else {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
index b897a8c..ab28f93 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodeMachine.java
@@ -20,13 +20,13 @@
 package jdk.nashorn.internal.runtime.regexp.joni;
 
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
+import static jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper.isNewLine;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindCondition;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindLongest;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isFindNotEmpty;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotBol;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isNotEol;
 import static jdk.nashorn.internal.runtime.regexp.joni.Option.isPosixRegion;
-import static jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper.isNewLine;
 
 import jdk.nashorn.internal.runtime.regexp.joni.ast.CClassNode;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.OPCode;
@@ -47,19 +47,19 @@
     private final int[] code;       // byte code
     private int ip;                 // instruction pointer
 
-    ByteCodeMachine(Regex regex, char[] chars, int p, int end) {
+    ByteCodeMachine(final Regex regex, final char[] chars, final int p, final int end) {
         super(regex, chars, p, end);
         this.code = regex.code;
     }
 
-    private boolean stringCmpIC(int caseFlodFlag, int s1, IntHolder ps2, int mbLen, int textEnd) {
+    private boolean stringCmpIC(final int caseFlodFlag, int s1, final IntHolder ps2, final int mbLen, final int textEnd) {
 
         int s2 = ps2.value;
-        int end1 = s1 + mbLen;
+        final int end1 = s1 + mbLen;
 
         while (s1 < end1) {
-            char c1 = EncodingHelper.toLowerCase(chars[s1++]);
-            char c2 = EncodingHelper.toLowerCase(chars[s2++]);
+            final char c1 = EncodingHelper.toLowerCase(chars[s1++]);
+            final char c2 = EncodingHelper.toLowerCase(chars[s2++]);
 
             if (c1 != c2) {
                 return false;
@@ -85,18 +85,18 @@
             for (i=0, q=s; i<7 && q<end && s>=0; i++) {
                 if (q < end) Config.log.print(new String(new char[]{chars[q++]}));
             }
-            String str = q < end ? "...\"" : "\"";
+            final String str = q < end ? "...\"" : "\"";
             q += str.length();
             Config.log.print(str);
             for (i=0; i<20-(q-s);i++) Config.log.print(" ");
-            StringBuilder sb = new StringBuilder();
+            final StringBuilder sb = new StringBuilder();
             new ByteCodePrinter(regex).compiledByteCodeToString(sb, ip);
             Config.log.println(sb.toString());
         }
     }
 
     @Override
-    protected final int matchAt(int range, int sstart, int sprev) {
+    protected final int matchAt(final int range, final int sstart, final int sprev) {
         this.range = range;
         this.sstart = sstart;
         this.sprev = sprev;
@@ -215,7 +215,7 @@
     }
 
     private boolean opEnd() {
-        int n = s - sstart;
+        final int n = s - sstart;
 
         if (n > bestLen) {
             if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
@@ -259,7 +259,7 @@
                 msaEnd   = s      - str;
             }
         } else {
-            Region region = msaRegion;
+            final Region region = msaRegion;
             if (Config.USE_POSIX_API_REGION_OPTION) {
                 if (!isPosixRegion(regex.options)) {
                     if (region != null) {
@@ -355,7 +355,7 @@
         if (s + tlen > range) {opFail(); return;}
 
         if (Config.USE_STRING_TEMPLATES) {
-            char[] bs = regex.templates[code[ip++]];
+            final char[] bs = regex.templates[code[ip++]];
             int ps = code[ip++];
 
             while (tlen-- > 0) if (bs[ps++] != chars[s++]) {opFail(); return;}
@@ -377,7 +377,7 @@
         if (s + tlen > range) {opFail(); return;}
 
         if (Config.USE_STRING_TEMPLATES) {
-            char[] bs = regex.templates[code[ip++]];
+            final char[] bs = regex.templates[code[ip++]];
             int ps = code[ip++];
 
             while (tlen-- > 0) if (bs[ps++] != EncodingHelper.toLowerCase(chars[s++])) {opFail(); return;}
@@ -389,7 +389,7 @@
     }
 
     private boolean isInBitSet() {
-        int c = chars[s];
+        final int c = chars[s];
         return (c <= 0xff && (code[ip + (c >>> BitSet.ROOM_SHIFT)] & (1 << c)) != 0);
     }
 
@@ -401,11 +401,11 @@
     }
 
     private boolean isInClassMB() {
-        int tlen = code[ip++];
+        final int tlen = code[ip++];
         if (s >= range) return false;
-        int ss = s;
+        final int ss = s;
         s++;
-        int c = chars[ss];
+        final int c = chars[ss];
         if (!EncodingHelper.isInCodeRange(code, ip, c)) return false;
         ip += tlen;
         return true;
@@ -426,7 +426,7 @@
         } else {
             if (!isInBitSet()) {opFail(); return;}
             ip += BitSet.BITSET_SIZE;
-            int tlen = code[ip++]; // by code range length
+            final int tlen = code[ip++]; // by code range length
             ip += tlen;
             s++;
         }
@@ -441,7 +441,7 @@
     }
 
     private boolean isNotInClassMB() {
-        int tlen = code[ip++];
+        final int tlen = code[ip++];
 
         if (!(s + 1 <= range)) {
             if (s >= range) return false;
@@ -450,9 +450,9 @@
             return true;
         }
 
-        int ss = s;
+        final int ss = s;
         s++;
-        int c = chars[ss];
+        final int c = chars[ss];
 
         if (EncodingHelper.isInCodeRange(code, ip, c)) return false;
         ip += tlen;
@@ -463,7 +463,7 @@
         if (s >= range) {opFail(); return;}
         if (chars[s] <= 0xff) {
             s++;
-            int tlen = code[ip++];
+            final int tlen = code[ip++];
             ip += tlen;
             sprev = sbegin; // break;
             return;
@@ -480,7 +480,7 @@
         } else {
             if (isInBitSet()) {opFail(); return;}
             ip += BitSet.BITSET_SIZE;
-            int tlen = code[ip++];
+            final int tlen = code[ip++];
             ip += tlen;
             s++;
         }
@@ -489,10 +489,10 @@
 
     private void opCClassNode() {
         if (s >= range) {opFail(); return;}
-        CClassNode cc = (CClassNode)regex.operands[code[ip++]];
-        int ss = s;
+        final CClassNode cc = (CClassNode)regex.operands[code[ip++]];
+        final int ss = s;
         s++;
-        int c = chars[ss];
+        final int c = chars[ss];
         if (!cc.isCodeInCCLength(c)) {opFail(); return;}
         sprev = sbegin; // break;
     }
@@ -535,7 +535,7 @@
         final char[] chars = this.chars;
 
         while (s < range) {
-            char b = chars[s];
+            final char b = chars[s];
             if (c == b) pushAlt(ip + 1, s, sprev);
             if (isNewLine(b)) {opFail(); return;}
             sprev = s;
@@ -661,36 +661,36 @@
     }
 
     private void opMemoryStartPush() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         pushMemStart(mem, s);
     }
 
     private void opMemoryStart() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         repeatStk[memStartStk + mem] = s;
     }
 
     private void opMemoryEndPush() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         pushMemEnd(mem, s);
     }
 
     private void opMemoryEnd() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         repeatStk[memEndStk + mem] = s;
     }
 
     private void opMemoryEndPushRec() {
-        int mem = code[ip++];
-        int stkp = getMemStart(mem); /* should be before push mem-end. */
+        final int mem = code[ip++];
+        final int stkp = getMemStart(mem); /* should be before push mem-end. */
         pushMemEnd(mem, s);
         repeatStk[memStartStk + mem] = stkp;
     }
 
     private void opMemoryEndRec() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         repeatStk[memEndStk + mem] = s;
-        int stkp = getMemStart(mem);
+        final int stkp = getMemStart(mem);
 
         if (BitStatus.bsAt(regex.btMemStart, mem)) {
             repeatStk[memStartStk + mem] = stkp;
@@ -701,25 +701,25 @@
         pushMemEndMark(mem);
     }
 
-    private boolean backrefInvalid(int mem) {
+    private boolean backrefInvalid(final int mem) {
         return repeatStk[memEndStk + mem] == INVALID_INDEX || repeatStk[memStartStk + mem] == INVALID_INDEX;
     }
 
-    private int backrefStart(int mem) {
+    private int backrefStart(final int mem) {
         return bsAt(regex.btMemStart, mem) ? stack[repeatStk[memStartStk + mem]].getMemPStr() : repeatStk[memStartStk + mem];
     }
 
-    private int backrefEnd(int mem) {
+    private int backrefEnd(final int mem) {
         return bsAt(regex.btMemEnd, mem) ? stack[repeatStk[memEndStk + mem]].getMemPStr() : repeatStk[memEndStk + mem];
     }
 
-    private void backref(int mem) {
+    private void backref(final int mem) {
         /* if you want to remove following line,
         you should check in parse and compile time. (numMem) */
         if (mem > regex.numMem || backrefInvalid(mem)) {opFail(); return;}
 
         int pstart = backrefStart(mem);
-        int pend = backrefEnd(mem);
+        final int pend = backrefEnd(mem);
 
         int n = pend - pstart;
         if (s + n > range) {opFail(); return;}
@@ -747,15 +747,15 @@
     }
 
     private void opBackRefNIC() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         /* if you want to remove following line,
         you should check in parse and compile time. (numMem) */
         if (mem > regex.numMem || backrefInvalid(mem)) {opFail(); return;}
 
-        int pstart = backrefStart(mem);
-        int pend = backrefEnd(mem);
+        final int pstart = backrefStart(mem);
+        final int pend = backrefEnd(mem);
 
-        int n = pend - pstart;
+        final int n = pend - pstart;
         if (s + n > range) {opFail(); return;}
         sprev = s;
 
@@ -768,15 +768,15 @@
     }
 
     private void opBackRefMulti() {
-        int tlen = code[ip++];
+        final int tlen = code[ip++];
 
         int i;
         loop:for (i=0; i<tlen; i++) {
-            int mem = code[ip++];
+            final int mem = code[ip++];
             if (backrefInvalid(mem)) continue;
 
             int pstart = backrefStart(mem);
-            int pend = backrefEnd(mem);
+            final int pend = backrefEnd(mem);
 
             int n = pend - pstart;
             if (s + n > range) {opFail(); return;}
@@ -802,17 +802,17 @@
     }
 
     private void opBackRefMultiIC() {
-        int tlen = code[ip++];
+        final int tlen = code[ip++];
 
         int i;
         loop:for (i=0; i<tlen; i++) {
-            int mem = code[ip++];
+            final int mem = code[ip++];
             if (backrefInvalid(mem)) continue;
 
-            int pstart = backrefStart(mem);
-            int pend = backrefEnd(mem);
+            final int pstart = backrefStart(mem);
+            final int pend = backrefEnd(mem);
 
-            int n = pend - pstart;
+            final int n = pend - pstart;
             if (s + n > range) {opFail(); return;}
 
             sprev = s;
@@ -830,23 +830,23 @@
         if (i == tlen) {opFail(); return;}
     }
 
-    private boolean memIsInMemp(int mem, int num, int memp) {
+    private boolean memIsInMemp(final int mem, final int num, int memp) {
         for (int i=0; i<num; i++) {
-            int m = code[memp++];
+            final int m = code[memp++];
             if (mem == m) return true;
         }
         return false;
     }
 
     // USE_BACKREF_AT_LEVEL // (s) and (end) implicit
-    private boolean backrefMatchAtNestedLevel(boolean ignoreCase, int caseFoldFlag,
-                                              int nest, int memNum, int memp) {
+    private boolean backrefMatchAtNestedLevel(final boolean ignoreCase, final int caseFoldFlag,
+                                              final int nest, final int memNum, final int memp) {
         int pend = -1;
         int level = 0;
         int k = stk - 1;
 
         while (k >= 0) {
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
 
             if (e.type == CALL_FRAME) {
                 level--;
@@ -855,7 +855,7 @@
             } else if (level == nest) {
                 if (e.type == MEM_START) {
                     if (memIsInMemp(e.getMemNum(), memNum, memp)) {
-                        int pstart = e.getMemPStr();
+                        final int pstart = e.getMemPStr();
                         if (pend != -1) {
                             if (pend - pstart > end - s) return false; /* or goto next_mem; */
                             int p = pstart;
@@ -887,9 +887,9 @@
     }
 
     private void opBackRefAtLevel() {
-        int ic      = code[ip++];
-        int level   = code[ip++];
-        int tlen    = code[ip++];
+        final int ic      = code[ip++];
+        final int level   = code[ip++];
+        final int tlen    = code[ip++];
 
         sprev = s;
         if (backrefMatchAtNestedLevel(ic != 0, regex.caseFoldFlag, level, tlen, ip)) { // (s) and (end) implicit
@@ -912,7 +912,7 @@
     }
 
     private void opNullCheckStart() {
-        int mem = code[ip++];
+        final int mem = code[ip++];
         pushNullCheckStart(mem, s);
     }
 
@@ -936,8 +936,8 @@
     }
 
     private void opNullCheckEnd() {
-        int mem = code[ip++];
-        int isNull = nullCheck(mem, s); /* mem: null check id */
+        final int mem = code[ip++];
+        final int isNull = nullCheck(mem, s); /* mem: null check id */
 
         if (isNull != 0) {
             if (Config.DEBUG_MATCH) {
@@ -950,8 +950,8 @@
 
     // USE_INFINITE_REPEAT_MONOMANIAC_MEM_STATUS_CHECK
     private void opNullCheckEndMemST() {
-        int mem = code[ip++];   /* mem: null check id */
-        int isNull = nullCheckMemSt(mem, s);
+        final int mem = code[ip++];   /* mem: null check id */
+        final int isNull = nullCheckMemSt(mem, s);
 
         if (isNull != 0) {
             if (Config.DEBUG_MATCH) {
@@ -965,7 +965,7 @@
 
     // USE_SUBEXP_CALL
     private void opNullCheckEndMemSTPush() {
-        int mem = code[ip++];   /* mem: null check id */
+        final int mem = code[ip++];   /* mem: null check id */
 
         int isNull;
         if (Config.USE_MONOMANIAC_CHECK_CAPTURES_IN_ENDLESS_REPEAT) {
@@ -991,7 +991,7 @@
     }
 
     private void opPush() {
-        int addr = code[ip++];
+        final int addr = code[ip++];
         pushAlt(ip + addr, s, sprev);
     }
 
@@ -1000,7 +1000,7 @@
     }
 
     private void opPushOrJumpExact1() {
-        int addr = code[ip++];
+        final int addr = code[ip++];
         // beyond string check
         if (s < range && code[ip] == chars[s]) {
             ip++;
@@ -1011,7 +1011,7 @@
     }
 
     private void opPushIfPeekNext() {
-        int addr = code[ip++];
+        final int addr = code[ip++];
         // beyond string check
         if (s < range && code[ip] == chars[s]) {
             ip++;
@@ -1022,8 +1022,8 @@
     }
 
     private void opRepeat() {
-        int mem = code[ip++];   /* mem: OP_REPEAT ID */
-        int addr= code[ip++];
+        final int mem = code[ip++];   /* mem: OP_REPEAT ID */
+        final int addr= code[ip++];
 
         // ensure1();
         repeatStk[mem] = stk;
@@ -1035,8 +1035,8 @@
     }
 
     private void opRepeatNG() {
-        int mem = code[ip++];   /* mem: OP_REPEAT ID */
-        int addr= code[ip++];
+        final int mem = code[ip++];   /* mem: OP_REPEAT ID */
+        final int addr= code[ip++];
 
         // ensure1();
         repeatStk[mem] = stk;
@@ -1048,8 +1048,8 @@
         }
     }
 
-    private void repeatInc(int mem, int si) {
-        StackEntry e = stack[si];
+    private void repeatInc(final int mem, final int si) {
+        final StackEntry e = stack[si];
 
         e.increaseRepeatCount();
 
@@ -1065,25 +1065,25 @@
     }
 
     private void opRepeatInc() {
-        int mem = code[ip++];   /* mem: OP_REPEAT ID */
-        int si = repeatStk[mem];
+        final int mem = code[ip++];   /* mem: OP_REPEAT ID */
+        final int si = repeatStk[mem];
         repeatInc(mem, si);
     }
 
     private void opRepeatIncSG() {
-        int mem = code[ip++];   /* mem: OP_REPEAT ID */
-        int si = getRepeat(mem);
+        final int mem = code[ip++];   /* mem: OP_REPEAT ID */
+        final int si = getRepeat(mem);
         repeatInc(mem, si);
     }
 
-    private void repeatIncNG(int mem, int si) {
-        StackEntry e = stack[si];
+    private void repeatIncNG(final int mem, final int si) {
+        final StackEntry e = stack[si];
 
         e.increaseRepeatCount();
 
         if (e.getRepeatCount() < regex.repeatRangeHi[mem]) {
             if (e.getRepeatCount() >= regex.repeatRangeLo[mem]) {
-                int pcode = e.getRepeatPCode();
+                final int pcode = e.getRepeatPCode();
                 pushRepeatInc(si);
                 pushAlt(pcode, s, sprev);
             } else {
@@ -1096,14 +1096,14 @@
     }
 
     private void opRepeatIncNG() {
-        int mem = code[ip++];
-        int si = repeatStk[mem];
+        final int mem = code[ip++];
+        final int si = repeatStk[mem];
         repeatIncNG(mem, si);
     }
 
     private void opRepeatIncNGSG() {
-        int mem = code[ip++];
-        int si = getRepeat(mem);
+        final int mem = code[ip++];
+        final int si = getRepeat(mem);
         repeatIncNG(mem, si);
     }
 
@@ -1112,13 +1112,13 @@
     }
 
     private void opPopPos() {
-        StackEntry e = stack[posEnd()];
+        final StackEntry e = stack[posEnd()];
         s    = e.getStatePStr();
         sprev= e.getStatePStrPrev();
     }
 
     private void opPushPosNot() {
-        int addr = code[ip++];
+        final int addr = code[ip++];
         pushPosNot(ip + addr, s, sprev);
     }
 
@@ -1136,23 +1136,23 @@
     }
 
     private void opLookBehind() {
-        int tlen = code[ip++];
+        final int tlen = code[ip++];
         s = EncodingHelper.stepBack(str, s, tlen);
         if (s == -1) {opFail(); return;}
         sprev = EncodingHelper.prevCharHead(str, s);
     }
 
     private void opLookBehindSb() {
-        int tlen = code[ip++];
+        final int tlen = code[ip++];
         s -= tlen;
         if (s < str) {opFail(); return;}
         sprev = s == str ? -1 : s - 1;
     }
 
     private void opPushLookBehindNot() {
-        int addr = code[ip++];
-        int tlen = code[ip++];
-        int q = EncodingHelper.stepBack(str, s, tlen);
+        final int addr = code[ip++];
+        final int tlen = code[ip++];
+        final int q = EncodingHelper.stepBack(str, s, tlen);
         if (q == -1) {
             /* too short case -> success. ex. /(?<!XXX)a/.match("a")
             If you want to change to fail, replace following line. */
@@ -1177,7 +1177,7 @@
         }
 
 
-        StackEntry e = pop();
+        final StackEntry e = pop();
         ip    = e.getStatePCode();
         s     = e.getStatePStr();
         sprev = e.getStatePStrPrev();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
index a01e414..46ee261 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ByteCodePrinter.java
@@ -214,7 +214,7 @@
             Arguments.OPTION, /*OP_SET_OPTION*/
     };
 
-    public ByteCodePrinter(Regex regex) {
+    public ByteCodePrinter(final Regex regex) {
         code = regex.code;
         codeLength = regex.codeLength;
         operands = regex.operands;
@@ -226,30 +226,30 @@
         return compiledByteCodeListToString();
     }
 
-    private void pString(StringBuilder sb, int len, int s) {
+    private void pString(final StringBuilder sb, final int len, final int s) {
         sb.append(":");
         sb.append(new String(code, s, len));
     }
 
-    private void pLenString(StringBuilder sb, int len, int s) {
+    private void pLenString(final StringBuilder sb, final int len, final int s) {
         sb.append(":").append(len).append(":");
         sb.append(new String(code, s, len));
     }
 
-    private void pLenStringFromTemplate(StringBuilder sb, int len, char[] tm, int idx) {
+    private void pLenStringFromTemplate(final StringBuilder sb, final int len, final char[] tm, final int idx) {
         sb.append(":T:").append(len).append(":");
         sb.append(tm, idx, len);
     }
 
-    public int compiledByteCodeToString(StringBuilder sb, int bp) {
+    public int compiledByteCodeToString(final StringBuilder sb, int bp) {
         int len, n, mem, addr, scn, cod;
         BitSet bs;
         CClassNode cc;
         int tm, idx;
 
         sb.append("[").append(OpCodeNames[code[bp]]);
-        int argType = OpCodeArgTypes[code[bp]];
-        int ip = bp;
+        final int argType = OpCodeArgTypes[code[bp]];
+        final int ip = bp;
         if (argType != Arguments.SPECIAL) {
             bp++;
             switch (argType) {
@@ -416,10 +416,10 @@
                 break;
 
             case OPCode.BACKREF_WITH_LEVEL: {
-                int option = code[bp];
+                final int option = code[bp];
                 bp += OPSize.OPTION;
                 sb.append(":").append(option);
-                int level = code[bp];
+                final int level = code[bp];
                 bp += OPSize.LENGTH;
                 sb.append(":").append(level);
                 sb.append(" ");
@@ -491,12 +491,12 @@
     }
 
     private String compiledByteCodeListToString() {
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append("code length: ").append(codeLength).append("\n");
 
         int ncode = 0;
         int bp = 0;
-        int end = codeLength;
+        final int end = codeLength;
 
         while (bp < end) {
             ncode++;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java
index 260be2a..96c6080 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/CodeRangeBuffer.java
@@ -36,13 +36,13 @@
     }
 
     // CodeRange.isInCodeRange
-    public boolean isInCodeRange(int code) {
+    public boolean isInCodeRange(final int code) {
         int low = 0;
-        int n = p[0];
+        final int n = p[0];
         int high = n;
 
         while (low < high) {
-            int x = (low + high) >> 1;
+            final int x = (low + high) >> 1;
             if (code > p[(x << 1) + 2]) {
                 low = x + 1;
             } else {
@@ -52,7 +52,7 @@
         return low < n && code >= p[(low << 1) + 1];
     }
 
-    private CodeRangeBuffer(CodeRangeBuffer orig) {
+    private CodeRangeBuffer(final CodeRangeBuffer orig) {
         p = new int[orig.p.length];
         System.arraycopy(orig.p, 0, p, 0, p.length);
         used = orig.used;
@@ -60,7 +60,7 @@
 
     @Override
     public String toString() {
-        StringBuilder buf = new StringBuilder();
+        final StringBuilder buf = new StringBuilder();
         buf.append("CodeRange");
         buf.append("\n  used: ").append(used);
         buf.append("\n  code point: ").append(p[0]);
@@ -74,45 +74,45 @@
         return buf.toString();
     }
 
-    private static String rangeNumToString(int num){
+    private static String rangeNumToString(final int num){
         return "0x" + Integer.toString(num, 16);
     }
 
-    public void expand(int low) {
+    public void expand(final int low) {
         int length = p.length;
         do { length <<= 1; } while (length < low);
-        int[]tmp = new int[length];
+        final int[]tmp = new int[length];
         System.arraycopy(p, 0, tmp, 0, used);
         p = tmp;
     }
 
-    public void ensureSize(int size) {
+    public void ensureSize(final int size) {
         int length = p.length;
         while (length < size ) { length <<= 1; }
         if (p.length != length) {
-            int[]tmp = new int[length];
+            final int[]tmp = new int[length];
             System.arraycopy(p, 0, tmp, 0, used);
             p = tmp;
         }
     }
 
-    private void moveRight(int from, int to, int n) {
+    private void moveRight(final int from, final int to, final int n) {
         if (to + n > p.length) expand(to + n);
         System.arraycopy(p, from, p, to, n);
         if (to + n > used) used = to + n;
     }
 
-    protected void moveLeft(int from, int to, int n) {
+    protected void moveLeft(final int from, final int to, final int n) {
         System.arraycopy(p, from, p, to, n);
     }
 
-    private void moveLeftAndReduce(int from, int to) {
+    private void moveLeftAndReduce(final int from, final int to) {
         System.arraycopy(p, from, p, to, used - from);
         used -= from - to;
     }
 
-    public void writeCodePoint(int pos, int b) {
-        int u = pos + 1;
+    public void writeCodePoint(final int pos, final int b) {
+        final int u = pos + 1;
         if (p.length < u) expand(u);
         p[pos] = b;
         if (used < u) used = u;
@@ -127,21 +127,21 @@
     // add_code_range_to_buf
     public static CodeRangeBuffer addCodeRangeToBuff(CodeRangeBuffer pbuf, int from, int to) {
         if (from > to) {
-            int n = from;
+            final int n = from;
             from = to;
             to = n;
         }
 
         if (pbuf == null) pbuf = new CodeRangeBuffer(); // move to CClassNode
 
-        int[]p = pbuf.p;
+        final int[]p = pbuf.p;
         int n = p[0];
 
         int low = 0;
         int bound = n;
 
         while (low < bound) {
-            int x = (low + bound) >>> 1;
+            final int x = (low + bound) >>> 1;
             if (from > p[x * 2 + 2]) {
                 low = x + 1;
             } else {
@@ -153,7 +153,7 @@
         bound = n;
 
         while (high < bound) {
-            int x = (high + bound) >>> 1;
+            final int x = (high + bound) >>> 1;
             if (to >= p[x * 2 + 1] - 1) {
                 high = x + 1;
             } else {
@@ -161,7 +161,7 @@
             }
         }
 
-        int incN = low + 1 - high;
+        final int incN = low + 1 - high;
 
         if (n + incN > Config.MAX_MULTI_BYTE_RANGES_NUM) throw new ValueException(ErrorMessages.ERR_TOO_MANY_MULTI_BYTE_RANGES);
 
@@ -171,9 +171,9 @@
         }
 
         if (incN != 0 && high < n) {
-            int fromPos = 1 + high * 2;
-            int toPos = 1 + (low + 1) * 2;
-            int size = (n - high) * 2;
+            final int fromPos = 1 + high * 2;
+            final int toPos = 1 + (low + 1) * 2;
+            final int size = (n - high) * 2;
 
             if (incN > 0) {
                 pbuf.moveRight(fromPos, toPos, size);
@@ -182,7 +182,7 @@
             }
         }
 
-        int pos = 1 + low * 2;
+        final int pos = 1 + low * 2;
         // pbuf.ensureSize(pos + 2);
         pbuf.writeCodePoint(pos, from);
         pbuf.writeCodePoint(pos + 1, to);
@@ -193,7 +193,7 @@
     }
 
     // add_code_range, be aware of it returning null!
-    public static CodeRangeBuffer addCodeRange(CodeRangeBuffer pbuf, ScanEnvironment env, int from, int to) {
+    public static CodeRangeBuffer addCodeRange(final CodeRangeBuffer pbuf, final ScanEnvironment env, final int from, final int to) {
         if (from > to) {
             if (env.syntax.allowEmptyRangeInCC()) {
                 return pbuf;
@@ -205,23 +205,23 @@
     }
 
     // SET_ALL_MULTI_BYTE_RANGE
-    protected static CodeRangeBuffer setAllMultiByteRange(CodeRangeBuffer pbuf) {
+    protected static CodeRangeBuffer setAllMultiByteRange(final CodeRangeBuffer pbuf) {
         return addCodeRangeToBuff(pbuf, EncodingHelper.mbcodeStartPosition(), ALL_MULTI_BYTE_RANGE);
     }
 
     // ADD_ALL_MULTI_BYTE_RANGE
-    public static CodeRangeBuffer addAllMultiByteRange(CodeRangeBuffer pbuf) {
+    public static CodeRangeBuffer addAllMultiByteRange(final CodeRangeBuffer pbuf) {
         return setAllMultiByteRange(pbuf);
     }
 
     // not_code_range_buf
-    public static CodeRangeBuffer notCodeRangeBuff(CodeRangeBuffer bbuf) {
+    public static CodeRangeBuffer notCodeRangeBuff(final CodeRangeBuffer bbuf) {
         CodeRangeBuffer pbuf = null;
 
         if (bbuf == null) return setAllMultiByteRange(pbuf);
 
-        int[]p = bbuf.p;
-        int n = p[0];
+        final int[]p = bbuf.p;
+        final int n = p[0];
 
         if (n <= 0) return setAllMultiByteRange(pbuf);
 
@@ -289,12 +289,12 @@
             pbuf = notCodeRangeBuff(bbuf2);
         }
 
-        int[]p1 = bbuf1.p;
-        int n1 = p1[0];
+        final int[]p1 = bbuf1.p;
+        final int n1 = p1[0];
 
         for (int i=0; i<n1; i++) {
-            int from = p1[i * 2 + 1];
-            int to = p1[i * 2 + 2];
+            final int from = p1[i * 2 + 1];
+            final int to = p1[i * 2 + 2];
             pbuf = addCodeRangeToBuff(pbuf, from, to);
         }
 
@@ -302,10 +302,10 @@
     }
 
     // and_code_range1
-    public static CodeRangeBuffer andCodeRange1(CodeRangeBuffer pbuf, int from1, int to1, int[]data, int n) {
+    public static CodeRangeBuffer andCodeRange1(CodeRangeBuffer pbuf, int from1, int to1, final int[]data, final int n) {
         for (int i=0; i<n; i++) {
-            int from2 = data[i * 2 + 1];
-            int to2 = data[i * 2 + 2];
+            final int from2 = data[i * 2 + 1];
+            final int to2 = data[i * 2 + 2];
             if (from2 < from1) {
                 if (to2 < from1) {
                     continue;
@@ -355,31 +355,31 @@
             tbuf = bbuf1; bbuf1 = bbuf2; bbuf2 = tbuf;
         }
 
-        int[]p1 = bbuf1.p;
-        int n1 = p1[0];
-        int[]p2 = bbuf2.p;
-        int n2 = p2[0];
+        final int[]p1 = bbuf1.p;
+        final int n1 = p1[0];
+        final int[]p2 = bbuf2.p;
+        final int n2 = p2[0];
 
         if (!not2 && !not1) { /* 1 AND 2 */
             for (int i=0; i<n1; i++) {
-                int from1 = p1[i * 2 + 1];
-                int to1 = p1[i * 2 + 2];
+                final int from1 = p1[i * 2 + 1];
+                final int to1 = p1[i * 2 + 2];
 
                 for (int j=0; j<n2; j++) {
-                    int from2 = p2[j * 2 + 1];
-                    int to2 = p2[j * 2 + 2];
+                    final int from2 = p2[j * 2 + 1];
+                    final int to2 = p2[j * 2 + 2];
 
                     if (from2 > to1) break;
                     if (to2 < from1) continue;
-                    int from = from1 > from2 ? from1 : from2;
-                    int to = to1 < to2 ? to1 : to2;
+                    final int from = from1 > from2 ? from1 : from2;
+                    final int to = to1 < to2 ? to1 : to2;
                     pbuf = addCodeRangeToBuff(pbuf, from, to);
                 }
             }
         } else if (!not1) { /* 1 AND (not 2) */
             for (int i=0; i<n1; i++) {
-                int from1 = p1[i * 2 + 1];
-                int to1 = p1[i * 2 + 2];
+                final int from1 = p1[i * 2 + 1];
+                final int to1 = p1[i * 2 + 2];
                 pbuf = andCodeRange1(pbuf, from1, to1, p2, n2);
             }
         }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java
index c3356ad..86ef062 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Compiler.java
@@ -36,7 +36,7 @@
     protected final Analyser analyser;
     protected final Regex regex;
 
-    protected Compiler(Analyser analyser) {
+    protected Compiler(final Analyser analyser) {
         this.analyser = analyser;
         this.regex = analyser.regex;
     }
@@ -52,21 +52,21 @@
 
     protected abstract void compileAltNode(ConsAltNode node);
 
-    private void compileStringRawNode(StringNode sn) {
+    private void compileStringRawNode(final StringNode sn) {
         if (sn.length() <= 0) return;
         addCompileString(sn.chars, sn.p, sn.length(), false);
     }
 
-    private void compileStringNode(StringNode node) {
-        StringNode sn = node;
+    private void compileStringNode(final StringNode node) {
+        final StringNode sn = node;
         if (sn.length() <= 0) return;
 
-        boolean ambig = sn.isAmbig();
+        final boolean ambig = sn.isAmbig();
 
         int p, prev;
         p = prev = sn.p;
-        int end = sn.end;
-        char[] chars = sn.chars;
+        final int end = sn.end;
+        final char[] chars = sn.chars;
         p++;
         int slen = 1;
 
@@ -87,7 +87,7 @@
     protected abstract void compileEncloseNode(EncloseNode node);
     protected abstract void compileAnchorNode(AnchorNode node);
 
-    protected final void compileTree(Node node) {
+    protected final void compileTree(final Node node) {
         switch (node.getType()) {
         case NodeType.LIST:
             ConsAltNode lin = (ConsAltNode)node;
@@ -101,7 +101,7 @@
             break;
 
         case NodeType.STR:
-            StringNode sn = (StringNode)node;
+            final StringNode sn = (StringNode)node;
             if (sn.isRaw()) {
                 compileStringRawNode(sn);
             } else {
@@ -126,7 +126,7 @@
             break;
 
         case NodeType.ENCLOSE:
-            EncloseNode enode = (EncloseNode)node;
+            final EncloseNode enode = (EncloseNode)node;
             if (enode.isOption()) {
                 compileOptionNode(enode);
             } else {
@@ -144,15 +144,15 @@
         } // switch
     }
 
-    protected final void compileTreeNTimes(Node node, int n) {
+    protected final void compileTreeNTimes(final Node node, final int n) {
         for (int i=0; i<n; i++) compileTree(node);
     }
 
-    protected void newSyntaxException(String message) {
+    protected void newSyntaxException(final String message) {
         throw new SyntaxException(message);
     }
 
-    protected void newInternalException(String message) {
+    protected void newInternalException(final String message) {
         throw new InternalException(message);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
index 0c9c8ab..24f217c 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/EncodingHelper.java
@@ -19,11 +19,10 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni;
 
+import java.util.Arrays;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.IntHolder;
 
-import java.util.Arrays;
-
 public final class EncodingHelper {
 
     final static int NEW_LINE            = 0x000a;
@@ -34,19 +33,19 @@
     final static char[] EMPTYCHARS = new char[0];
     final static int[][] codeRanges = new int[15][];
 
-    public static int digitVal(int code) {
+    public static int digitVal(final int code) {
         return code - '0';
     }
 
-    public static int odigitVal(int code) {
+    public static int odigitVal(final int code) {
         return digitVal(code);
     }
 
-    public static boolean isXDigit(int code) {
+    public static boolean isXDigit(final int code) {
         return Character.isDigit(code) || (code >= 'a' && code <= 'f') || (code >= 'A' && code <= 'F');
     }
 
-    public static int xdigitVal(int code) {
+    public static int xdigitVal(final int code) {
         if (Character.isDigit(code)) {
             return code - '0';
         } else if (code >= 'a' && code <= 'f') {
@@ -56,36 +55,36 @@
         }
     }
 
-    public static boolean isDigit(int code) {
+    public static boolean isDigit(final int code) {
         return code >= '0' && code <= '9';
     }
 
-    public static boolean isWord(int code) {
+    public static boolean isWord(final int code) {
         // letter, digit, or '_'
         return (1 << Character.getType(code) & CharacterType.WORD_MASK) != 0;
     }
 
-    public static boolean isNewLine(int code) {
+    public static boolean isNewLine(final int code) {
         return code == NEW_LINE || code == RETURN || code == LINE_SEPARATOR || code == PARAGRAPH_SEPARATOR;
     }
 
-    public static boolean isNewLine(char[] chars, int p, int end) {
+    public static boolean isNewLine(final char[] chars, final int p, final int end) {
         return p < end && isNewLine(chars[p]);
     }
 
     // Encoding.prevCharHead
-    public static int prevCharHead(int p, int s) {
+    public static int prevCharHead(final int p, final int s) {
         return s <= p ? -1 : s - 1;
     }
 
     /* onigenc_get_right_adjust_char_head_with_prev */
-    public static int rightAdjustCharHeadWithPrev(int s, IntHolder prev) {
+    public static int rightAdjustCharHeadWithPrev(final int s, final IntHolder prev) {
         if (prev != null) prev.value = -1; /* Sorry */
         return s;
     }
 
     // Encoding.stepBack
-    public static int stepBack(int p, int s, int n) {
+    public static int stepBack(final int p, int s, int n) {
        while (s != -1 && n-- > 0) {
            if (s <= p) return -1;
            s--;
@@ -97,7 +96,7 @@
         return 0x80;
     }
 
-    public static char[] caseFoldCodesByString(int flag, char c) {
+    public static char[] caseFoldCodesByString(final int flag, final char c) {
         char[] codes = EMPTYCHARS;
         final char upper = toUpperCase(c);
 
@@ -117,7 +116,7 @@
         return codes;
     }
 
-    public static void applyAllCaseFold(int flag, ApplyCaseFold fun, Object arg) {
+    public static void applyAllCaseFold(final int flag, final ApplyCaseFold fun, final Object arg) {
         for (int c = 0; c < 0xffff; c++) {
             if (Character.isLowerCase(c)) {
                 final int upper = toUpperCase(c);
@@ -140,34 +139,34 @@
         }
     }
 
-    public static char toLowerCase(char c) {
+    public static char toLowerCase(final char c) {
         return (char)toLowerCase((int)c);
     }
 
-    public static int toLowerCase(int c) {
+    public static int toLowerCase(final int c) {
         if (c < 128) {
             return ('A' <= c && c <= 'Z') ? (c + ('a' - 'A')) : c;
         }
         // Do not convert non-ASCII upper case character to ASCII lower case.
-        int lower = Character.toLowerCase(c);
+        final int lower = Character.toLowerCase(c);
         return (lower < 128) ? c : lower;
 
     }
 
-    public static char toUpperCase(char c) {
+    public static char toUpperCase(final char c) {
         return (char)toUpperCase((int)c);
     }
 
-    public static int toUpperCase(int c) {
+    public static int toUpperCase(final int c) {
         if (c < 128) {
             return ('a' <= c && c <= 'z') ? c + ('A' - 'a') : c;
         }
         // Do not convert non-ASCII lower case character to ASCII upper case.
-        int upper = Character.toUpperCase(c);
+        final int upper = Character.toUpperCase(c);
         return (upper < 128) ? c : upper;
     }
 
-    public static int[] ctypeCodeRange(int ctype, IntHolder sbOut) {
+    public static int[] ctypeCodeRange(final int ctype, final IntHolder sbOut) {
         sbOut.value = 0x100; // use bitset for codes smaller than 256
         int[] range = null;
 
@@ -206,13 +205,13 @@
     }
 
     // CodeRange.isInCodeRange
-    public static boolean isInCodeRange(int[] p, int offset, int code) {
+    public static boolean isInCodeRange(final int[] p, final int offset, final int code) {
         int low = 0;
-        int n = p[offset];
+        final int n = p[offset];
         int high = n ;
 
         while (low < high) {
-            int x = (low + high) >> 1;
+            final int x = (low + high) >> 1;
             if (code > p[(x << 1) + 2 + offset]) {
                 low = x + 1;
             } else {
@@ -225,7 +224,7 @@
     /**
      * @see <a href="http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt">http://www.geocities.jp/kosako3/oniguruma/doc/RE.txt</a>
      */
-    public static boolean isCodeCType(int code, int ctype) {
+    public static boolean isCodeCType(final int code, final int ctype) {
         int type;
         switch (ctype) {
             case CharacterType.NEWLINE:
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
index c4dcac2..61127a0 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Lexer.java
@@ -36,7 +36,7 @@
     protected final Syntax syntax;              // fast access to syntax
     protected final Token token = new Token();  // current token
 
-    protected Lexer(ScanEnvironment env, char[] chars, int p, int end) {
+    protected Lexer(final ScanEnvironment env, final char[] chars, final int p, final int end) {
         super(chars, p, end);
         this.env = env;
         this.syntax = env.syntax;
@@ -48,7 +48,7 @@
      */
     private int fetchRangeQuantifier() {
         mark();
-        boolean synAllow = syntax.allowInvalidInterval();
+        final boolean synAllow = syntax.allowInvalidInterval();
 
         if (!left()) {
             if (synAllow) {
@@ -89,7 +89,7 @@
         int up;
         int ret = 0;
         if (c == ',') {
-            int prev = p; // ??? last
+            final int prev = p; // ??? last
             up = scanUnsignedNumber();
             if (up < 0) {
                 throw new ValueException(ERR_TOO_BIG_NUMBER_FOR_REPEAT_RANGE);
@@ -130,7 +130,7 @@
         return ret; /* 0: normal {n,m}, 2: fixed {n} */
     }
 
-    private int invalidRangeQuantifier(boolean synAllow) {
+    private int invalidRangeQuantifier(final boolean synAllow) {
         if (synAllow) {
             restore();
             return 1;
@@ -218,7 +218,7 @@
         }
     }
 
-    private int nameEndCodePoint(int start) {
+    private int nameEndCodePoint(final int start) {
         switch(start) {
         case '<':
             return '>';
@@ -229,7 +229,7 @@
         }
     }
 
-    private void fetchTokenInCCFor_charType(boolean flag, int type) {
+    private void fetchTokenInCCFor_charType(final boolean flag, final int type) {
         token.type = TokenType.CHAR_TYPE;
         token.setPropCType(type);
         token.setPropNot(flag);
@@ -237,16 +237,16 @@
 
     private void fetchTokenInCCFor_x() {
         if (!left()) return;
-        int last = p;
+        final int last = p;
 
         if (peekIs('{') && syntax.opEscXBraceHex8()) {
             inc();
-            int num = scanUnsignedHexadecimalNumber(8);
+            final int num = scanUnsignedHexadecimalNumber(8);
             if (num < 0) {
                 throw new ValueException(ERR_TOO_BIG_WIDE_CHAR_VALUE);
             }
             if (left()) {
-                int c2 = peek();
+                final int c2 = peek();
                 if (EncodingHelper.isXDigit(c2)) {
                     throw new ValueException(ERR_TOO_LONG_WIDE_CHAR_VALUE);
                 }
@@ -275,7 +275,7 @@
 
     private void fetchTokenInCCFor_u() {
         if (!left()) return;
-        int last = p;
+        final int last = p;
 
         if (syntax.op2EscUHex4()) {
             int num = scanUnsignedHexadecimalNumber(4);
@@ -293,7 +293,7 @@
     private void fetchTokenInCCFor_digit() {
         if (syntax.opEscOctal3()) {
             unfetch();
-            int last = p;
+            final int last = p;
             int num = scanUnsignedOctalNumber(3);
             if (num < 0) {
                 throw new ValueException(ERR_TOO_BIG_NUMBER);
@@ -381,7 +381,7 @@
 
             default:
                 unfetch();
-                int num = fetchEscapedValue();
+                final int num = fetchEscapedValue();
                 if (token.getC() != num) {
                     token.setCode(num);
                     token.type = TokenType.CODE_POINT;
@@ -395,7 +395,7 @@
         return token.type;
     }
 
-    private void fetchTokenFor_repeat(int lower, int upper) {
+    private void fetchTokenFor_repeat(final int lower, final int upper) {
         token.type = TokenType.OP_REPEAT;
         token.setRepeatLower(lower);
         token.setRepeatUpper(upper);
@@ -418,7 +418,7 @@
         } // inner switch
     }
 
-    private void fetchTokenFor_anchor(int subType) {
+    private void fetchTokenFor_anchor(final int subType) {
         token.type = TokenType.ANCHOR;
         token.setAnchor(subType);
     }
@@ -426,10 +426,10 @@
     private void fetchTokenFor_xBrace() {
         if (!left()) return;
 
-        int last = p;
+        final int last = p;
         if (peekIs('{') && syntax.opEscXBraceHex8()) {
             inc();
-            int num = scanUnsignedHexadecimalNumber(8);
+            final int num = scanUnsignedHexadecimalNumber(8);
             if (num < 0) {
                 throw new ValueException(ERR_TOO_BIG_WIDE_CHAR_VALUE);
             }
@@ -462,7 +462,7 @@
 
     private void fetchTokenFor_uHex() {
         if (!left()) return;
-        int last = p;
+        final int last = p;
 
         if (syntax.op2EscUHex4()) {
             int num = scanUnsignedHexadecimalNumber(4);
@@ -479,8 +479,8 @@
 
     private void fetchTokenFor_digit() {
         unfetch();
-        int last = p;
-        int num = scanUnsignedNumber();
+        final int last = p;
+        final int num = scanUnsignedNumber();
         if (num < 0 || num > Config.MAX_BACKREF_NUM) { // goto skip_backref
         } else if (syntax.opDecimalBackref() && (num <= env.numMem || num <= 9)) { /* This spec. from GNU regex */
             if (syntax.strictCheckBackref()) {
@@ -505,7 +505,7 @@
 
     private void fetchTokenFor_zero() {
         if (syntax.opEscOctal3()) {
-            int last = p;
+            final int last = p;
             int num = scanUnsignedOctalNumber(c == '0' ? 2 : 3);
             if (num < 0) {
                 throw new ValueException(ERR_TOO_BIG_NUMBER);
@@ -659,7 +659,7 @@
 
                 default:
                     unfetch();
-                    int num = fetchEscapedValue();
+                    final int num = fetchEscapedValue();
 
                     /* set_raw: */
                     if (token.getC() != num) {
@@ -798,11 +798,11 @@
         }
     }
 
-    protected final void syntaxWarn(String message, char c) {
+    protected final void syntaxWarn(final String message, final char c) {
         syntaxWarn(message.replace("<%n>", Character.toString(c)));
     }
 
-    protected final void syntaxWarn(String message) {
+    protected final void syntaxWarn(final String message) {
         if (Config.USE_WARN) {
             env.reg.warnings.warn(message + ": /" + new String(chars, getBegin(), getEnd()) + "/");
         }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
index 7605873..3d2af29 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Matcher.java
@@ -41,11 +41,11 @@
     protected int msaBegin;
     protected int msaEnd;
 
-    public Matcher(Regex regex, char[] chars) {
+    public Matcher(final Regex regex, final char[] chars) {
         this(regex, chars, 0, chars.length);
     }
 
-    public Matcher(Regex regex, char[] chars, int p, int end) {
+    public Matcher(final Regex regex, final char[] chars, final int p, final int end) {
         this.regex = regex;
 
         this.chars = chars;
@@ -70,16 +70,16 @@
         return msaEnd;
     }
 
-    protected final void msaInit(int option, int start) {
+    protected final void msaInit(final int option, final int start) {
         msaOptions = option;
         msaStart = start;
         if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) msaBestLen = -1;
     }
 
-    public final int match(int at, int range, int option) {
+    public final int match(final int at, final int range, final int option) {
         msaInit(option, at);
 
-        int prev = EncodingHelper.prevCharHead(str, at);
+        final int prev = EncodingHelper.prevCharHead(str, at);
 
         if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
             return matchAt(end /*range*/, at, prev);
@@ -89,7 +89,7 @@
     }
 
     int low, high; // these are the return values
-    private boolean forwardSearchRange(char[] chars, int str, int end, int s, int range, IntHolder lowPrev) {
+    private boolean forwardSearchRange(final char[] chars, final int str, final int end, final int s, final int range, final IntHolder lowPrev) {
         int pprev = -1;
         int p = s;
 
@@ -120,7 +120,7 @@
                     switch (regex.subAnchor) {
                     case AnchorType.BEGIN_LINE:
                         if (p != str) {
-                            int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
+                            final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
                             if (!EncodingHelper.isNewLine(chars, prev, end)) {
                                 // goto retry_gate;
                                 pprev = p;
@@ -133,7 +133,7 @@
                     case AnchorType.END_LINE:
                         if (p == end) {
                             if (!Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) {
-                                int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
+                                final int prev = EncodingHelper.prevCharHead((pprev != -1) ? pprev : str, p);
                                 if (prev != -1 && EncodingHelper.isNewLine(chars, prev, end)) {
                                     // goto retry_gate;
                                     pprev = p;
@@ -196,7 +196,7 @@
     }
 
     // low, high
-    private boolean backwardSearchRange(char[] chars, int str, int end, int s, int range, int adjrange) {
+    private boolean backwardSearchRange(final char[] chars, final int str, final int end, final int s, int range, final int adjrange) {
         range += regex.dMin;
         int p = s;
 
@@ -208,7 +208,7 @@
                     switch (regex.subAnchor) {
                     case AnchorType.BEGIN_LINE:
                         if (p != str) {
-                            int prev = EncodingHelper.prevCharHead(str, p);
+                            final int prev = EncodingHelper.prevCharHead(str, p);
                             if (!EncodingHelper.isNewLine(chars, prev, end)) {
                                 p = prev;
                                 continue retry;
@@ -219,7 +219,7 @@
                     case AnchorType.END_LINE:
                         if (p == end) {
                             if (!Config.USE_NEWLINE_AT_END_OF_STRING_HAS_EMPTY_LINE) {
-                                int prev = EncodingHelper.prevCharHead(adjrange, p);
+                                final int prev = EncodingHelper.prevCharHead(adjrange, p);
                                 if (prev == -1) return false;
                                 if (EncodingHelper.isNewLine(chars, prev, end)) {
                                     p = prev;
@@ -256,7 +256,7 @@
     }
 
     // MATCH_AND_RETURN_CHECK
-    private boolean matchCheck(int upperRange, int s, int prev) {
+    private boolean matchCheck(final int upperRange, final int s, final int prev) {
         if (Config.USE_MATCH_RANGE_MUST_BE_INSIDE_OF_SPECIFIED_RANGE) {
             if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
                 //range = upperRange;
@@ -281,10 +281,10 @@
         return false;
     }
 
-    public final int search(int start, int range, int option) {
+    public final int search(int start, int range, final int option) {
         int s, prev;
         int origStart = start;
-        int origRange = range;
+        final int origRange = range;
 
         if (Config.DEBUG_SEARCH) {
             Config.log.println("onig_search (entry point): "+
@@ -326,7 +326,7 @@
                 // !end_buf:!
                 if (endBuf(start, range, minSemiEnd, maxSemiEnd)) return -1; // mismatch_no_msa;
             } else if ((regex.anchor & AnchorType.SEMI_END_BUF) != 0) {
-                int preEnd = EncodingHelper.stepBack(str, end, 1);
+                final int preEnd = EncodingHelper.stepBack(str, end, 1);
                 maxSemiEnd = end;
                 if (EncodingHelper.isNewLine(chars, preEnd, end)) {
                     minSemiEnd = preEnd;
@@ -488,7 +488,7 @@
         return mismatch();
     }
 
-    private boolean endBuf(int start, int range, int minSemiEnd, int maxSemiEnd) {
+    private boolean endBuf(int start, int range, final int minSemiEnd, final int maxSemiEnd) {
         if ((maxSemiEnd - str) < regex.anchorDmin) return true; // mismatch_no_msa;
 
         if (range > start) {
@@ -515,14 +515,14 @@
         return false;
     }
 
-    private int match(int s) {
+    private int match(final int s) {
         return s - str; // sstart ???
     }
 
     private int mismatch() {
         if (Config.USE_FIND_LONGEST_SEARCH_ALL_OF_RANGE) {
             if (msaBestLen >= 0) {
-                int s = msaBestS;
+                final int s = msaBestS;
                 return match(s);
             }
         }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java
index f507018..df7167b 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MatcherFactory.java
@@ -24,7 +24,7 @@
 
     static final MatcherFactory DEFAULT = new MatcherFactory() {
         @Override
-        public Matcher create(Regex regex, char[] chars, int p, int end) {
+        public Matcher create(final Regex regex, final char[] chars, final int p, final int end) {
             return new ByteCodeMachine(regex, chars, p, end);
         }
     };
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java
index 388c0c5..6990f35 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/MinMaxLen.java
@@ -26,7 +26,7 @@
     MinMaxLen() {
     }
 
-    MinMaxLen(int min, int max) {
+    MinMaxLen(final int min, final int max) {
         this.min = min;
         this.max = max;
     }
@@ -47,12 +47,12 @@
 
     int distanceValue() {
         if (max == INFINITE_DISTANCE) return 0;
-        int d = max - min;
+        final int d = max - min;
         /* return dist_vals[d] * 16 / (mm->min + 12); */
         return d < distValues.length ? distValues[d] : 1;
     }
 
-    int compareDistanceValue(MinMaxLen other, int v1, int v2) {
+    int compareDistanceValue(final MinMaxLen other, int v1, int v2) {
         if (v2 <= 0) return -1;
         if (v1 <= 0) return 1;
 
@@ -67,11 +67,11 @@
         return 0;
     }
 
-    boolean equal(MinMaxLen other) {
+    boolean equal(final MinMaxLen other) {
         return min == other.min && max == other.max;
     }
 
-    void set(int min, int max) {
+    void set(final int min, final int max) {
         this.min = min;
         this.max = max;
     }
@@ -80,28 +80,28 @@
         min = max = 0;
     }
 
-    void copy(MinMaxLen other) {
+    void copy(final MinMaxLen other) {
         min = other.min;
         max = other.max;
     }
 
-    void add(MinMaxLen other) {
+    void add(final MinMaxLen other) {
         min = distanceAdd(min, other.min);
         max = distanceAdd(max, other.max);
     }
 
-    void addLength(int len) {
+    void addLength(final int len) {
         min = distanceAdd(min, len);
         max = distanceAdd(max, len);
     }
 
-    void altMerge(MinMaxLen other) {
+    void altMerge(final MinMaxLen other) {
         if (min > other.min) min = other.min;
         if (max < other.max) max = other.max;
     }
 
     static final int INFINITE_DISTANCE = 0x7FFFFFFF;
-    static int distanceAdd(int d1, int d2) {
+    static int distanceAdd(final int d1, final int d2) {
         if (d1 == INFINITE_DISTANCE || d2 == INFINITE_DISTANCE) {
             return INFINITE_DISTANCE;
         } else {
@@ -110,7 +110,7 @@
         }
     }
 
-    static int distanceMultiply(int d, int m) {
+    static int distanceMultiply(final int d, final int m) {
         if (m == 0) return 0;
         if (d < INFINITE_DISTANCE / m) {
             return d * m;
@@ -119,7 +119,7 @@
         }
     }
 
-    static String distanceRangeToString(int a, int b) {
+    static String distanceRangeToString(final int a, final int b) {
         String s = "";
         if (a == INFINITE_DISTANCE) {
             s += "inf";
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java
index 76b1d5f..e072641 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/NodeOptInfo.java
@@ -27,7 +27,7 @@
     final OptExactInfo expr = new OptExactInfo();           /* prec read (?=...) */
     final OptMapInfo map = new OptMapInfo();                /* boundary */
 
-    public void setBoundNode(MinMaxLen mmd) {
+    public void setBoundNode(final MinMaxLen mmd) {
         exb.mmd.copy(mmd);
         expr.mmd.copy(mmd);
         map.mmd.copy(mmd);
@@ -42,7 +42,7 @@
         map.clear();
     }
 
-    public void copy(NodeOptInfo other) {
+    public void copy(final NodeOptInfo other) {
         length.copy(other.length);
         anchor.copy(other.anchor);
         exb.copy(other.exb);
@@ -51,8 +51,8 @@
         map.copy(other.map);
     }
 
-    public void concatLeftNode(NodeOptInfo other) {
-        OptAnchorInfo tanchor = new OptAnchorInfo(); // remove it somehow ?
+    public void concatLeftNode(final NodeOptInfo other) {
+        final OptAnchorInfo tanchor = new OptAnchorInfo(); // remove it somehow ?
         tanchor.concat(anchor, other.anchor, length.max, other.length.max);
         anchor.copy(tanchor);
 
@@ -67,8 +67,8 @@
             }
         }
 
-        boolean exbReach = exb.reachEnd;
-        boolean exmReach = exm.reachEnd;
+        final boolean exbReach = exb.reachEnd;
+        final boolean exmReach = exm.reachEnd;
 
         if (other.length.max != 0) {
             exb.reachEnd = exm.reachEnd = false;
@@ -107,7 +107,7 @@
         length.add(other.length);
     }
 
-    public void altMerge(NodeOptInfo other, OptEnvironment env) {
+    public void altMerge(final NodeOptInfo other, final OptEnvironment env) {
         anchor.altMerge(other.anchor);
         exb.altMerge(other.exb, env);
         exm.altMerge(other.exm, env);
@@ -116,7 +116,7 @@
         length.altMerge(other.length);
     }
 
-    public void setBound(MinMaxLen mmd) {
+    public void setBound(final MinMaxLen mmd) {
         exb.mmd.copy(mmd);
         expr.mmd.copy(mmd);
         map.mmd.copy(mmd);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java
index 4ed24e0..599c023 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptAnchorInfo.java
@@ -29,12 +29,12 @@
         leftAnchor = rightAnchor = 0;
     }
 
-    void copy(OptAnchorInfo other) {
+    void copy(final OptAnchorInfo other) {
         leftAnchor = other.leftAnchor;
         rightAnchor = other.rightAnchor;
     }
 
-    void concat(OptAnchorInfo left, OptAnchorInfo right, int leftLength, int rightLength) {
+    void concat(final OptAnchorInfo left, final OptAnchorInfo right, final int leftLength, final int rightLength) {
         leftAnchor = left.leftAnchor;
         if (leftLength == 0) leftAnchor |= right.leftAnchor;
 
@@ -42,12 +42,12 @@
         if (rightLength == 0) rightAnchor |= left.rightAnchor;
     }
 
-    boolean isSet(int anchor) {
+    boolean isSet(final int anchor) {
         if ((leftAnchor & anchor) != 0) return true;
         return (rightAnchor & anchor) != 0;
     }
 
-    void add(int anchor) {
+    void add(final int anchor) {
         if (isLeftAnchor(anchor)) {
             leftAnchor |= anchor;
         } else {
@@ -55,7 +55,7 @@
         }
     }
 
-    void remove(int anchor) {
+    void remove(final int anchor) {
         if (isLeftAnchor(anchor)) {
             leftAnchor &= ~anchor;
         } else {
@@ -63,19 +63,19 @@
         }
     }
 
-    void altMerge(OptAnchorInfo other) {
+    void altMerge(final OptAnchorInfo other) {
         leftAnchor &= other.leftAnchor;
         rightAnchor &= other.rightAnchor;
     }
 
-    static boolean isLeftAnchor(int anchor) { // make a mask for it ?
+    static boolean isLeftAnchor(final int anchor) { // make a mask for it ?
         return !(anchor == END_BUF || anchor == SEMI_END_BUF ||
                  anchor == END_LINE || anchor == PREC_READ ||
                  anchor == PREC_READ_NOT);
     }
 
-    static String anchorToString(int anchor) {
-        StringBuffer s = new StringBuffer("[");
+    static String anchorToString(final int anchor) {
+        final StringBuffer s = new StringBuffer("[");
 
         if ((anchor & AnchorType.BEGIN_BUF) !=0 ) s.append("begin-buf ");
         if ((anchor & AnchorType.BEGIN_LINE) !=0 ) s.append("begin-line ");
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java
index 8c75e03..ba1eb13 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptEnvironment.java
@@ -26,7 +26,7 @@
     int caseFoldFlag;
     ScanEnvironment scanEnv;
 
-    void copy(OptEnvironment other) {
+    void copy(final OptEnvironment other) {
         mmd.copy(other.mmd);
         options = other.options;
         caseFoldFlag = other.caseFoldFlag;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java
index f7992a3..2fa91a3 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptExactInfo.java
@@ -44,7 +44,7 @@
         length = 0;
     }
 
-    void copy(OptExactInfo other) {
+    void copy(final OptExactInfo other) {
         mmd.copy(other.mmd);
         anchor.copy(other.anchor);
         reachEnd = other.reachEnd;
@@ -54,14 +54,14 @@
         System.arraycopy(other.chars, 0, chars, 0, OPT_EXACT_MAXLEN);
     }
 
-    void concat(OptExactInfo other) {
+    void concat(final OptExactInfo other) {
         if (!ignoreCase && other.ignoreCase) {
             if (length >= other.length) return; /* avoid */
             ignoreCase = true;
         }
 
         int p = 0; // add->s;
-        int end = p + other.length;
+        final int end = p + other.length;
 
         int i;
         for (i = length; p < end;) {
@@ -72,14 +72,14 @@
         length = i;
         reachEnd = (p == end ? other.reachEnd : false);
 
-        OptAnchorInfo tmp = new OptAnchorInfo();
+        final OptAnchorInfo tmp = new OptAnchorInfo();
         tmp.concat(anchor, other.anchor, 1, 1);
         if (!other.reachEnd) tmp.rightAnchor = 0;
         anchor.copy(tmp);
     }
 
     // ?? raw is not used here
-    void concatStr(char[] lchars, int p, int end, boolean raw) {
+    void concatStr(final char[] lchars, int p, final int end, final boolean raw) {
         int i;
         for (i = length; p < end && i < OPT_EXACT_MAXLEN;) {
             if (i + 1 > OPT_EXACT_MAXLEN) break;
@@ -89,7 +89,7 @@
         length = i;
     }
 
-    void altMerge(OptExactInfo other, OptEnvironment env) {
+    void altMerge(final OptExactInfo other, final OptEnvironment env) {
         if (other.length == 0 || length == 0) {
             clear();
             return;
@@ -116,7 +116,7 @@
     }
 
 
-    void select(OptExactInfo alt) {
+    void select(final OptExactInfo alt) {
         int v1 = length;
         int v2 = alt.length;
 
@@ -142,11 +142,11 @@
 
     // comp_opt_exact_or_map_info
     private static final int COMP_EM_BASE   = 20;
-    int compare(OptMapInfo m) {
+    int compare(final OptMapInfo m) {
         if (m.value <= 0) return -1;
 
-        int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
-        int vm = COMP_EM_BASE * 5 * 2 / m.value;
+        final int ve = COMP_EM_BASE * length * (ignoreCase ? 1 : 2);
+        final int vm = COMP_EM_BASE * 5 * 2 / m.value;
 
         return mmd.compareDistanceValue(m.mmd, ve, vm);
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java
index 9cf6a50..c4fd183 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/OptMapInfo.java
@@ -34,7 +34,7 @@
         for (int i=0; i<map.length; i++) map[i] = 0;
     }
 
-    void copy(OptMapInfo other) {
+    void copy(final OptMapInfo other) {
         mmd.copy(other.mmd);
         anchor.copy(other.anchor);
         value = other.value;
@@ -42,19 +42,19 @@
         System.arraycopy(other.map, 0, map, 0, other.map.length);
     }
 
-    void addChar(int c) {
-        int c_ = c & 0xff;
+    void addChar(final int c) {
+        final int c_ = c & 0xff;
         if (map[c_] == 0) {
             map[c_] = 1;
             value += positionValue(c_);
         }
     }
 
-    void addCharAmb(char[] chars, int p, int end, int caseFoldFlag) {
+    void addCharAmb(final char[] chars, final int p, final int end, int caseFoldFlag) {
         addChar(chars[p]);
 
         caseFoldFlag &= ~Config.INTERNAL_ENC_CASE_FOLD_MULTI_CHAR;
-        char[]items = EncodingHelper.caseFoldCodesByString(caseFoldFlag, chars[p]);
+        final char[]items = EncodingHelper.caseFoldCodesByString(caseFoldFlag, chars[p]);
 
         for (int i=0; i<items.length; i++) {
             addChar(items[i]);
@@ -63,21 +63,21 @@
 
     // select_opt_map_info
     private static final int z = 1<<15; /* 32768: something big value */
-    void select(OptMapInfo alt) {
+    void select(final OptMapInfo alt) {
         if (alt.value == 0) return;
         if (value == 0) {
             copy(alt);
             return;
         }
 
-        int v1 = z / value;
-        int v2 = z /alt.value;
+        final int v1 = z / value;
+        final int v2 = z /alt.value;
 
         if (mmd.compareDistanceValue(alt.mmd, v1, v2) > 0) copy(alt);
     }
 
     // alt_merge_opt_map_info
-    void altMerge(OptMapInfo other) {
+    void altMerge(final OptMapInfo other) {
         /* if (! is_equal_mml(&to->mmd, &add->mmd)) return ; */
         if (value == 0) return;
         if (other.value == 0 || mmd.max < other.mmd.max) {
@@ -109,7 +109,7 @@
      };
 
     // map_position_value
-    static int positionValue(int i) {
+    static int positionValue(final int i) {
         if (i < ByteValTable.length) {
             return ByteValTable[i];
         } else {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java
index 26f3e56..d6c76c0 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Option.java
@@ -41,7 +41,7 @@
 
     public static final int DEFAULT              = NONE;
 
-    public static String toString(int option) {
+    public static String toString(final int option) {
         String options = "";
         if (isIgnoreCase(option)) options += "IGNORECASE ";
         if (isExtend(option)) options += "EXTEND ";
@@ -60,55 +60,55 @@
         return options;
     }
 
-    public static boolean isIgnoreCase(int option) {
+    public static boolean isIgnoreCase(final int option) {
         return (option & IGNORECASE) != 0;
     }
 
-    public static boolean isExtend(int option) {
+    public static boolean isExtend(final int option) {
         return (option & EXTEND) != 0;
     }
 
-    public static boolean isSingleline(int option) {
+    public static boolean isSingleline(final int option) {
         return (option & SINGLELINE) != 0;
     }
 
-    public static boolean isMultiline(int option) {
+    public static boolean isMultiline(final int option) {
         return (option & MULTILINE) != 0;
     }
 
-    public static boolean isFindLongest(int option) {
+    public static boolean isFindLongest(final int option) {
         return (option & FIND_LONGEST) != 0;
     }
 
-    public static boolean isFindNotEmpty(int option) {
+    public static boolean isFindNotEmpty(final int option) {
         return (option & FIND_NOT_EMPTY) != 0;
     }
 
-    public static boolean isFindCondition(int option) {
+    public static boolean isFindCondition(final int option) {
         return (option & (FIND_LONGEST | FIND_NOT_EMPTY)) != 0;
     }
 
-    public static boolean isNegateSingleline(int option) {
+    public static boolean isNegateSingleline(final int option) {
         return (option & NEGATE_SINGLELINE) != 0;
     }
 
-    public static boolean isDontCaptureGroup(int option) {
+    public static boolean isDontCaptureGroup(final int option) {
         return (option & DONT_CAPTURE_GROUP) != 0;
     }
 
-    public static boolean isCaptureGroup(int option) {
+    public static boolean isCaptureGroup(final int option) {
         return (option & CAPTURE_GROUP) != 0;
     }
 
-    public static boolean isNotBol(int option) {
+    public static boolean isNotBol(final int option) {
         return (option & NOTBOL) != 0;
     }
 
-    public static boolean isNotEol(int option) {
+    public static boolean isNotEol(final int option) {
         return (option & NOTEOL) != 0;
     }
 
-    public static boolean isPosixRegion(int option) {
+    public static boolean isPosixRegion(final int option) {
         return (option & POSIX_REGION) != 0;
     }
 
@@ -116,7 +116,7 @@
     //    public static boolean isDynamic(int option) {
     //        return (option & (MULTILINE | IGNORECASE)) != 0;
     //    }
-    public static boolean isDynamic(int option) {
+    public static boolean isDynamic(final int option) {
         return false;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
index 2cbd0fc..c61bdc2 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Parser.java
@@ -52,7 +52,7 @@
     protected int returnCode; // return code used by parser methods (they itself return parsed nodes)
                               // this approach will not affect recursive calls
 
-    protected Parser(ScanEnvironment env, char[] chars, int p, int end) {
+    protected Parser(final ScanEnvironment env, final char[] chars, final int p, final int end) {
         super(env, chars, p, end);
         regex = env.reg;
     }
@@ -64,7 +64,7 @@
         return root;
     }
 
-    private boolean codeExistCheck(int code, boolean ignoreEscaped) {
+    private boolean codeExistCheck(final int code, final boolean ignoreEscaped) {
         mark();
 
         boolean inEsc = false;
@@ -108,7 +108,7 @@
         CClassNode prevCC = null;
         CClassNode workCC = null;
 
-        CCStateArg arg = new CCStateArg();
+        final CCStateArg arg = new CCStateArg();
 
         boolean andStart = false;
         arg.state = CCSTATE.START;
@@ -197,7 +197,7 @@
                 break;
 
             case CC_CC_OPEN: /* [ */
-                CClassNode acc = parseCharClass();
+                final CClassNode acc = parseCharClass();
                 cc.or(acc);
                 break;
 
@@ -260,29 +260,29 @@
         return cc;
     }
 
-    private void parseCharClassSbChar(CClassNode cc, CCStateArg arg) {
+    private void parseCharClassSbChar(final CClassNode cc, final CCStateArg arg) {
         arg.inType = CCVALTYPE.SB;
         arg.v = token.getC();
         arg.vIsRaw = false;
         parseCharClassValEntry2(cc, arg); // goto val_entry2
     }
 
-    private void parseCharClassRangeEndVal(CClassNode cc, CCStateArg arg) {
+    private void parseCharClassRangeEndVal(final CClassNode cc, final CCStateArg arg) {
         arg.v = '-';
         arg.vIsRaw = false;
         parseCharClassValEntry(cc, arg); // goto val_entry
     }
 
-    private void parseCharClassValEntry(CClassNode cc, CCStateArg arg) {
+    private void parseCharClassValEntry(final CClassNode cc, final CCStateArg arg) {
         arg.inType = arg.v <= 0xff ? CCVALTYPE.SB : CCVALTYPE.CODE_POINT;
         parseCharClassValEntry2(cc, arg); // val_entry2:
     }
 
-    private void parseCharClassValEntry2(CClassNode cc, CCStateArg arg) {
+    private void parseCharClassValEntry2(final CClassNode cc, final CCStateArg arg) {
         cc.nextStateValue(arg, env);
     }
 
-    private Node parseEnclose(TokenType term) {
+    private Node parseEnclose(final TokenType term) {
         Node node = null;
 
         if (!left()) {
@@ -327,8 +327,8 @@
                 break;
             case '@':
                 if (syntax.op2AtMarkCaptureHistory()) {
-                    EncloseNode en = new EncloseNode(); // node_new_enclose_memory
-                    int num = env.addMemEntry();
+                    final EncloseNode en = new EncloseNode(); // node_new_enclose_memory
+                    final int num = env.addMemEntry();
                     if (num >= BitStatus.BIT_STATUS_BITS_NUM) {
                         throw new ValueException(ERR_GROUP_NUMBER_OVER_FOR_CAPTURE_HISTORY);
                     }
@@ -385,17 +385,17 @@
                     } // switch
 
                     if (c == ')') {
-                        EncloseNode en = new EncloseNode(option, 0); // node_new_option
+                        final EncloseNode en = new EncloseNode(option, 0); // node_new_option
                         node = en;
                         returnCode = 2; /* option only */
                         return node;
                     } else if (c == ':') {
-                        int prev = env.option;
+                        final int prev = env.option;
                         env.option = option;
                         fetchToken();
-                        Node target = parseSubExp(term);
+                        final Node target = parseSubExp(term);
                         env.option = prev;
-                        EncloseNode en = new EncloseNode(option, 0); // node_new_option
+                        final EncloseNode en = new EncloseNode(option, 0); // node_new_option
                         en.setTarget(target);
                         node = en;
                         returnCode = 0;
@@ -418,20 +418,20 @@
                 returnCode = 1; /* group */
                 return node;
             }
-            EncloseNode en = new EncloseNode(); // node_new_enclose_memory
-            int num = env.addMemEntry();
+            final EncloseNode en = new EncloseNode(); // node_new_enclose_memory
+            final int num = env.addMemEntry();
             en.regNum = num;
             node = en;
         }
 
         fetchToken();
-        Node target = parseSubExp(term);
+        final Node target = parseSubExp(term);
 
         if (node.getType() == NodeType.ANCHOR) {
-            AnchorNode an = (AnchorNode) node;
+            final AnchorNode an = (AnchorNode) node;
             an.setTarget(target);
         } else {
-            EncloseNode en = (EncloseNode)node;
+            final EncloseNode en = (EncloseNode)node;
             en.setTarget(target);
             if (en.type == EncloseType.MEMORY) {
                 /* Don't move this to previous of parse_subexp() */
@@ -442,7 +442,7 @@
         return node; // ??
     }
 
-    private Node parseExp(TokenType term) {
+    private Node parseExp(final TokenType term) {
         if (token.type == term) return StringNode.EMPTY; // goto end_of_token
 
         Node node = null;
@@ -458,11 +458,11 @@
             if (returnCode == 1) {
                 group = true;
             } else if (returnCode == 2) { /* option only */
-                int prev = env.option;
-                EncloseNode en = (EncloseNode)node;
+                final int prev = env.option;
+                final EncloseNode en = (EncloseNode)node;
                 env.option = en.option;
                 fetchToken();
-                Node target = parseSubExp(term);
+                final Node target = parseSubExp(term);
                 env.option = prev;
                 en.setTarget(target);
                 return node;
@@ -483,7 +483,7 @@
         case RAW_BYTE:
             return parseExpTkRawByte(group); // tk_raw_byte:
         case CODE_POINT:
-            char[] buf = new char[] {(char)token.getCode()};
+            final char[] buf = new char[] {(char)token.getCode()};
             // #ifdef NUMBERED_CHAR_IS_NOT_CASE_AMBIG ... // setRaw() #else
             node = new StringNode(buf, 0, 1);
             break;
@@ -494,7 +494,7 @@
             case CharacterType.S:
             case CharacterType.W:
                 if (Config.NON_UNICODE_SDW) {
-                    CClassNode cc = new CClassNode();
+                    final CClassNode cc = new CClassNode();
                     cc.addCType(token.getPropCType(), false, env, this);
                     if (token.getPropNot()) cc.setNot();
                     node = cc;
@@ -505,7 +505,7 @@
             case CharacterType.DIGIT:
             case CharacterType.XDIGIT:
                 // #ifdef USE_SHARED_CCLASS_TABLE ... #endif
-                CClassNode ccn = new CClassNode();
+                final CClassNode ccn = new CClassNode();
                 ccn.addCType(token.getPropCType(), false, env, this);
                 if (token.getPropNot()) ccn.setNot();
                 node = ccn;
@@ -518,10 +518,10 @@
             break;
 
         case CC_CC_OPEN:
-            CClassNode cc = parseCharClass();
+            final CClassNode cc = parseCharClass();
             node = cc;
             if (isIgnoreCase(env.option)) {
-                ApplyCaseFoldArg arg = new ApplyCaseFoldArg(env, cc);
+                final ApplyCaseFoldArg arg = new ApplyCaseFoldArg(env, cc);
                 EncodingHelper.applyAllCaseFold(env.caseFoldFlag, ApplyCaseFold.INSTANCE, arg);
 
                 if (arg.altRoot != null) {
@@ -536,13 +536,13 @@
 
         case ANYCHAR_ANYTIME:
             node = new AnyCharNode();
-            QuantifierNode qn = new QuantifierNode(0, QuantifierNode.REPEAT_INFINITE, false);
+            final QuantifierNode qn = new QuantifierNode(0, QuantifierNode.REPEAT_INFINITE, false);
             qn.setTarget(node);
             node = qn;
             break;
 
         case BACKREF:
-            int backRef = token.getBackrefRef();
+            final int backRef = token.getBackrefRef();
             node = new BackRefNode(backRef, env);
             break;
 
@@ -574,8 +574,8 @@
         return parseExpRepeat(node, group); // repeat:
     }
 
-    private Node parseExpTkByte(boolean group) {
-        StringNode node = new StringNode(chars, token.backP, p); // tk_byte:
+    private Node parseExpTkByte(final boolean group) {
+        final StringNode node = new StringNode(chars, token.backP, p); // tk_byte:
         while (true) {
             fetchToken();
             if (token.type != TokenType.STRING) break;
@@ -590,13 +590,13 @@
         return parseExpRepeat(node, group); // string_end:, goto repeat
     }
 
-    private Node parseExpTkRawByte(boolean group) {
+    private Node parseExpTkRawByte(final boolean group) {
         // tk_raw_byte:
 
         // important: we don't use 0xff mask here neither in the compiler
         // (in the template string) so we won't have to mask target
         // strings when comparing against them in the matcher
-        StringNode node = new StringNode((char)token.getC());
+        final StringNode node = new StringNode((char)token.getC());
         node.setRaw();
 
         fetchToken();
@@ -605,22 +605,22 @@
         return parseExpRepeat(node, group);
     }
 
-    private Node parseExpRepeat(Node target, boolean group) {
+    private Node parseExpRepeat(Node target, final boolean group) {
         while (token.type == TokenType.OP_REPEAT || token.type == TokenType.INTERVAL) { // repeat:
             if (target.isInvalidQuantifier()) {
                 throw new SyntaxException(ERR_TARGET_OF_REPEAT_OPERATOR_INVALID);
             }
 
-            QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
+            final QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
                                                      token.getRepeatUpper(),
                                                      token.type == TokenType.INTERVAL);
 
             qtfr.greedy = token.getRepeatGreedy();
-            int ret = qtfr.setQuantifier(target, group, env, chars, getBegin(), getEnd());
+            final int ret = qtfr.setQuantifier(target, group, env, chars, getBegin(), getEnd());
             Node qn = qtfr;
 
             if (token.getRepeatPossessive()) {
-                EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
+                final EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
                 en.setTarget(qn);
                 qn = en;
             }
@@ -629,7 +629,7 @@
                 target = qn;
             } else if (ret == 2) { /* split case: /abc+/ */
                 target = ConsAltNode.newListNode(target, null);
-                ConsAltNode tmp = ((ConsAltNode)target).setCdr(ConsAltNode.newListNode(qn, null));
+                final ConsAltNode tmp = ((ConsAltNode)target).setCdr(ConsAltNode.newListNode(qn, null));
 
                 fetchToken();
                 return parseExpRepeatForCar(target, tmp, group);
@@ -639,22 +639,22 @@
         return target;
     }
 
-    private Node parseExpRepeatForCar(Node top, ConsAltNode target, boolean group) {
+    private Node parseExpRepeatForCar(final Node top, final ConsAltNode target, final boolean group) {
         while (token.type == TokenType.OP_REPEAT || token.type == TokenType.INTERVAL) { // repeat:
             if (target.car.isInvalidQuantifier()) {
                 throw new SyntaxException(ERR_TARGET_OF_REPEAT_OPERATOR_INVALID);
             }
 
-            QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
+            final QuantifierNode qtfr = new QuantifierNode(token.getRepeatLower(),
                                                      token.getRepeatUpper(),
                                                      token.type == TokenType.INTERVAL);
 
             qtfr.greedy = token.getRepeatGreedy();
-            int ret = qtfr.setQuantifier(target.car, group, env, chars, getBegin(), getEnd());
+            final int ret = qtfr.setQuantifier(target.car, group, env, chars, getBegin(), getEnd());
             Node qn = qtfr;
 
             if (token.getRepeatPossessive()) {
-                EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
+                final EncloseNode en = new EncloseNode(EncloseType.STOP_BACKTRACK); // node_new_enclose
                 en.setTarget(qn);
                 qn = en;
             }
@@ -669,13 +669,13 @@
         return top;
     }
 
-    private Node parseBranch(TokenType term) {
+    private Node parseBranch(final TokenType term) {
         Node node = parseExp(term);
 
         if (token.type == TokenType.EOT || token.type == term || token.type == TokenType.ALT) {
             return node;
         } else {
-            ConsAltNode top = ConsAltNode.newListNode(node, null);
+            final ConsAltNode top = ConsAltNode.newListNode(node, null);
             ConsAltNode t = top;
 
             while (token.type != TokenType.EOT && token.type != term && token.type != TokenType.ALT) {
@@ -695,13 +695,13 @@
     }
 
     /* term_tok: TK_EOT or TK_SUBEXP_CLOSE */
-    private Node parseSubExp(TokenType term) {
+    private Node parseSubExp(final TokenType term) {
         Node node = parseBranch(term);
 
         if (token.type == term) {
             return node;
         } else if (token.type == TokenType.ALT) {
-            ConsAltNode top = ConsAltNode.newAltNode(node, null);
+            final ConsAltNode top = ConsAltNode.newAltNode(node, null);
             ConsAltNode t = top;
             while (token.type == TokenType.ALT) {
                 fetchToken();
@@ -719,7 +719,7 @@
         }
     }
 
-    private void parseSubExpError(TokenType term) {
+    private void parseSubExpError(final TokenType term) {
         if (term == TokenType.SUBEXP_CLOSE) {
             throw new SyntaxException(ERR_END_PATTERN_WITH_UNMATCHED_PARENTHESIS);
         } else {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
index 91117d1..8859fc6 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Regex.java
@@ -72,42 +72,42 @@
     char[][] templates;
     int templateNum;
 
-    public Regex(CharSequence cs) {
+    public Regex(final CharSequence cs) {
         this(cs.toString());
     }
 
-    public Regex(String str) {
+    public Regex(final String str) {
         this(str.toCharArray(), 0, str.length(), 0);
     }
 
-    public Regex(char[] chars) {
+    public Regex(final char[] chars) {
         this(chars, 0, chars.length, 0);
     }
 
-    public Regex(char[] chars, int p, int end) {
+    public Regex(final char[] chars, final int p, final int end) {
         this(chars, p, end, 0);
     }
 
-    public Regex(char[] chars, int p, int end, int option) {
+    public Regex(final char[] chars, final int p, final int end, final int option) {
         this(chars, p, end, option, Syntax.RUBY, WarnCallback.DEFAULT);
     }
 
     // onig_new
-    public Regex(char[] chars, int p, int end, int option, Syntax syntax) {
+    public Regex(final char[] chars, final int p, final int end, final int option, final Syntax syntax) {
         this(chars, p, end, option, Config.ENC_CASE_FOLD_DEFAULT, syntax, WarnCallback.DEFAULT);
     }
 
-    public Regex(char[]chars, int p, int end, int option, WarnCallback warnings) {
+    public Regex(final char[]chars, final int p, final int end, final int option, final WarnCallback warnings) {
         this(chars, p, end, option, Syntax.RUBY, warnings);
     }
 
     // onig_new
-    public Regex(char[] chars, int p, int end, int option, Syntax syntax, WarnCallback warnings) {
+    public Regex(final char[] chars, final int p, final int end, final int option, final Syntax syntax, final WarnCallback warnings) {
         this(chars, p, end, option, Config.ENC_CASE_FOLD_DEFAULT, syntax, warnings);
     }
 
     // onig_alloc_init
-    public Regex(char[] chars, int p, int end, int option, int caseFoldFlag, Syntax syntax, WarnCallback warnings) {
+    public Regex(final char[] chars, final int p, final int end, int option, final int caseFoldFlag, final Syntax syntax, final WarnCallback warnings) {
 
         if ((option & (Option.DONT_CAPTURE_GROUP | Option.CAPTURE_GROUP)) ==
             (Option.DONT_CAPTURE_GROUP | Option.CAPTURE_GROUP)) {
@@ -140,11 +140,11 @@
         return factory;
     }
 
-    public Matcher matcher(char[] chars) {
+    public Matcher matcher(final char[] chars) {
         return matcher(chars, 0, chars.length);
     }
 
-    public Matcher matcher(char[] chars, int p, int end) {
+    public Matcher matcher(final char[] chars, final int p, final int end) {
         MatcherFactory matcherFactory = factory;
         if (matcherFactory == null) {
             matcherFactory = compile();
@@ -162,10 +162,10 @@
 
     /* set skip map for Boyer-Moor search */
     void setupBMSkipMap() {
-        char[] chars = exact;
-        int p = exactP;
-        int end = exactEnd;
-        int len = end - p;
+        final char[] chars = exact;
+        final int p = exactP;
+        final int end = exactEnd;
+        final int len = end - p;
 
         if (len < Config.CHAR_TABLE_SIZE) {
             // map/skip
@@ -180,7 +180,7 @@
         }
     }
 
-    void setExactInfo(OptExactInfo e) {
+    void setExactInfo(final OptExactInfo e) {
         if (e.length == 0) return;
 
         // shall we copy that ?
@@ -207,7 +207,7 @@
         }
     }
 
-    void setOptimizeMapInfo(OptMapInfo m) {
+    void setOptimizeMapInfo(final OptMapInfo m) {
         map = m.map;
 
         searchAlgorithm = SearchAlgorithm.MAP;
@@ -219,7 +219,7 @@
         }
     }
 
-    void setSubAnchor(OptAnchorInfo anc) {
+    void setSubAnchor(final OptAnchorInfo anc) {
         subAnchor |= anc.leftAnchor & AnchorType.BEGIN_LINE;
         subAnchor |= anc.rightAnchor & AnchorType.END_LINE;
     }
@@ -236,7 +236,7 @@
     }
 
     public String optimizeInfoToString() {
-        StringBuilder s = new StringBuilder();
+        final StringBuilder s = new StringBuilder();
         s.append("optimize: ").append(searchAlgorithm.getName()).append("\n");
         s.append("  anchor:     ").append(OptAnchorInfo.anchorToString(anchor));
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
index 9281954..ee3dc61 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Region.java
@@ -26,7 +26,7 @@
     public final int[]beg;
     public final int[]end;
 
-    public Region(int num) {
+    public Region(final int num) {
         this.numRegs = num;
         this.beg = new int[num];
         this.end = new int[num];
@@ -34,7 +34,7 @@
 
     @Override
     public String toString() {
-        StringBuilder sb = new StringBuilder();
+        final StringBuilder sb = new StringBuilder();
         sb.append("Region: \n");
         for (int i=0; i<beg.length; i++) sb.append(" " + i + ": (" + beg[i] + "-" + end[i] + ")");
         return sb.toString();
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java
index adecb1d..923c243 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScanEnvironment.java
@@ -44,7 +44,7 @@
     public Node memNodes[];
 
 
-    public ScanEnvironment(Regex regex, Syntax syntax) {
+    public ScanEnvironment(final Regex regex, final Syntax syntax) {
         this.reg = regex;
         option = regex.options;
         caseFoldFlag = regex.caseFoldFlag;
@@ -65,7 +65,7 @@
         if (numMem++ == 0) {
             memNodes = new Node[SCANENV_MEMNODES_SIZE];
         } else if (numMem >= memNodes.length) {
-            Node[]tmp = new Node[memNodes.length << 1];
+            final Node[]tmp = new Node[memNodes.length << 1];
             System.arraycopy(memNodes, 0, tmp, 0, memNodes.length);
             memNodes = tmp;
         }
@@ -73,7 +73,7 @@
         return numMem;
     }
 
-    public void setMemNode(int num, Node node) {
+    public void setMemNode(final int num, final Node node) {
         if (numMem >= num) {
             memNodes[num] = node;
         } else {
@@ -81,7 +81,7 @@
         }
     }
 
-    public int convertBackslashValue(int c) {
+    public int convertBackslashValue(final int c) {
         if (syntax.opEscControlChars()) {
             switch (c) {
             case 'n': return '\n';
@@ -101,7 +101,7 @@
         return c;
     }
 
-    void ccEscWarn(String s) {
+    void ccEscWarn(final String s) {
         if (Config.USE_WARN) {
             if (syntax.warnCCOpNotEscaped() && syntax.backSlashEscapeInCC()) {
                 reg.warnings.warn("character class has '" + s + "' without escape");
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java
index ad4aaaf..200e769 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ScannerSupport.java
@@ -36,7 +36,7 @@
 
     private final static int INT_SIGN_BIT = 1 << 31;
 
-    protected ScannerSupport(char[] chars, int p, int end) {
+    protected ScannerSupport(final char[] chars, final int p, final int end) {
         this.chars = chars;
         this.begin = p;
         this.end = end;
@@ -53,12 +53,12 @@
     }
 
     protected final int scanUnsignedNumber() {
-        int last = c;
+        final int last = c;
         int num = 0; // long ???
         while(left()) {
             fetch();
             if (Character.isDigit(c)) {
-                int onum = num;
+                final int onum = num;
                 num = num * 10 + EncodingHelper.digitVal(c);
                 if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
             } else {
@@ -71,13 +71,13 @@
     }
 
     protected final int scanUnsignedHexadecimalNumber(int maxLength) {
-        int last = c;
+        final int last = c;
         int num = 0;
         while(left() && maxLength-- != 0) {
             fetch();
             if (EncodingHelper.isXDigit(c)) {
-                int onum = num;
-                int val = EncodingHelper.xdigitVal(c);
+                final int onum = num;
+                final int val = EncodingHelper.xdigitVal(c);
                 num = (num << 4) + val;
                 if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
             } else {
@@ -90,13 +90,13 @@
     }
 
     protected final int scanUnsignedOctalNumber(int maxLength) {
-        int last = c;
+        final int last = c;
         int num = 0;
         while(left() && maxLength-- != 0) {
             fetch();
             if (Character.isDigit(c) && c < '8') {
-                int onum = num;
-                int val = EncodingHelper.odigitVal(c);
+                final int onum = num;
+                final int val = EncodingHelper.odigitVal(c);
                 num = (num << 3) + val;
                 if (((onum ^ num) & INT_SIGN_BIT) != 0) return -1;
             } else {
@@ -144,7 +144,7 @@
         return p < stop ? chars[p] : 0;
     }
 
-    protected final boolean peekIs(int c) {
+    protected final boolean peekIs(final int c) {
         return peek() == c;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java
index 5b2eac9..0d672c4 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/SearchAlgorithm.java
@@ -34,12 +34,12 @@
         }
 
         @Override
-        public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
+        public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
             return textP;
         }
 
         @Override
-        public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
+        public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
             return textP;
         }
 
@@ -53,10 +53,10 @@
         }
 
         @Override
-        public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
-            char[] target = regex.exact;
-            int targetP = regex.exactP;
-            int targetEnd = regex.exactEnd;
+        public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+            final char[] target = regex.exact;
+            final int targetP = regex.exactP;
+            final int targetEnd = regex.exactEnd;
 
 
             int end = textEnd;
@@ -84,10 +84,10 @@
         }
 
         @Override
-        public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
-            char[] target = regex.exact;
-            int targetP = regex.exactP;
-            int targetEnd = regex.exactEnd;
+        public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+            final char[] target = regex.exact;
+            final int targetP = regex.exactP;
+            final int targetEnd = regex.exactEnd;
 
             int s = textEnd;
             s -= targetEnd - targetP;
@@ -116,7 +116,7 @@
     public static final class SLOW_IC extends SearchAlgorithm {
         private final int caseFoldFlag;
 
-        public SLOW_IC(Regex regex) {
+        public SLOW_IC(final Regex regex) {
             this.caseFoldFlag = regex.caseFoldFlag;
         }
 
@@ -126,10 +126,10 @@
         }
 
         @Override
-        public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
-            char[] target = regex.exact;
-            int targetP = regex.exactP;
-            int targetEnd = regex.exactEnd;
+        public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+            final char[] target = regex.exact;
+            final int targetP = regex.exactP;
+            final int targetEnd = regex.exactEnd;
 
             int end = textEnd;
             end -= targetEnd - targetP - 1;
@@ -145,10 +145,10 @@
         }
 
         @Override
-        public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
-            char[] target = regex.exact;
-            int targetP = regex.exactP;
-            int targetEnd = regex.exactEnd;
+        public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+            final char[] target = regex.exact;
+            final int targetP = regex.exactP;
+            final int targetEnd = regex.exactEnd;
 
             int s = textEnd;
             s -= targetEnd - targetP;
@@ -164,8 +164,8 @@
             return -1;
         }
 
-        private boolean lowerCaseMatch(char[] t, int tP, int tEnd,
-                                       char[] chars, int p, int end) {
+        private boolean lowerCaseMatch(final char[] t, int tP, final int tEnd,
+                                       final char[] chars, int p, final int end) {
 
             while (tP < tEnd) {
                 if (t[tP++] != EncodingHelper.toLowerCase(chars[p++])) return false;
@@ -182,15 +182,15 @@
         }
 
         @Override
-        public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
-            char[] target = regex.exact;
-            int targetP = regex.exactP;
-            int targetEnd = regex.exactEnd;
+        public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+            final char[] target = regex.exact;
+            final int targetP = regex.exactP;
+            final int targetEnd = regex.exactEnd;
 
             int end = textRange + (targetEnd - targetP) - 1;
             if (end > textEnd) end = textEnd;
 
-            int tail = targetEnd - 1;
+            final int tail = targetEnd - 1;
             int s = textP + (targetEnd - targetP) - 1;
 
             if (regex.intMap == null) {
@@ -224,10 +224,10 @@
         private static final int BM_BACKWARD_SEARCH_LENGTH_THRESHOLD = 100;
 
         @Override
-        public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
-            char[] target = regex.exact;
-            int targetP = regex.exactP;
-            int targetEnd = regex.exactEnd;
+        public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+            final char[] target = regex.exact;
+            final int targetP = regex.exactP;
+            final int targetEnd = regex.exactEnd;
 
             if (regex.intMapBackward == null) {
                 if (s_ - range_ < BM_BACKWARD_SEARCH_LENGTH_THRESHOLD) {
@@ -257,7 +257,7 @@
         }
 
 
-        private void setBmBackwardSkip(Regex regex, char[] chars, int p, int end) {
+        private void setBmBackwardSkip(final Regex regex, final char[] chars, final int p, final int end) {
             int[] skip;
             if (regex.intMapBackward == null) {
                 skip = new int[Config.CHAR_TABLE_SIZE];
@@ -266,7 +266,7 @@
                 skip = regex.intMapBackward;
             }
 
-            int len = end - p;
+            final int len = end - p;
 
             for (int i=0; i<Config.CHAR_TABLE_SIZE; i++) skip[i] = len;
             for (int i=len-1; i>0; i--) skip[chars[i] & 0xff] = i;
@@ -281,8 +281,8 @@
         }
 
         @Override
-        public final int search(Regex regex, char[] text, int textP, int textEnd, int textRange) {
-            byte[] map = regex.map;
+        public final int search(final Regex regex, final char[] text, final int textP, final int textEnd, final int textRange) {
+            final byte[] map = regex.map;
             int s = textP;
 
             while (s < textRange) {
@@ -293,8 +293,8 @@
         }
 
         @Override
-        public final int searchBackward(Regex regex, char[] text, int textP, int adjustText, int textEnd, int textStart, int s_, int range_) {
-            byte[] map = regex.map;
+        public final int searchBackward(final Regex regex, final char[] text, final int textP, final int adjustText, final int textEnd, final int textStart, final int s_, final int range_) {
+            final byte[] map = regex.map;
             int s = textStart;
 
             if (s >= textEnd) s = textEnd - 1;
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java
index 9161336..36a65d6 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackEntry.java
@@ -25,28 +25,28 @@
 
     // first union member
     /* byte code position */
-    void setStatePCode(int pcode) {
+    void setStatePCode(final int pcode) {
         E1 = pcode;
     }
     int getStatePCode() {
         return E1;
     }
     /* string position */
-    void setStatePStr(int pstr) {
+    void setStatePStr(final int pstr) {
         E2 = pstr;
     }
     int getStatePStr() {
         return E2;
     }
     /* previous char position of pstr */
-    void setStatePStrPrev(int pstrPrev) {
+    void setStatePStrPrev(final int pstrPrev) {
         E3 = pstrPrev;
     }
     int getStatePStrPrev() {
         return E3;
     }
 
-    void setStateCheck(int check) {
+    void setStateCheck(final int check) {
         E4 = check;
     }
     int getStateCheck() {
@@ -55,7 +55,7 @@
 
     // second union member
     /* for OP_REPEAT_INC, OP_REPEAT_INC_NG */
-    void setRepeatCount(int count) {
+    void setRepeatCount(final int count) {
         E1 = count;
     }
     int getRepeatCount() {
@@ -68,14 +68,14 @@
         E1++;
     }
     /* byte code position (head of repeated target) */
-    void setRepeatPCode(int pcode) {
+    void setRepeatPCode(final int pcode) {
         E2 = pcode;
     }
     int getRepeatPCode() {
         return E2;
     }
     /* repeat id */
-    void setRepeatNum(int num) {
+    void setRepeatNum(final int num) {
         E3 = num;
     }
     int getRepeatNum() {
@@ -84,7 +84,7 @@
 
     // third union member
     /* index of stack */ /*int repeat_inc struct*/
-    void setSi(int si) {
+    void setSi(final int si) {
         E1 = si;
     }
     int getSi() {
@@ -93,14 +93,14 @@
 
     // fourth union member
     /* memory num */
-    void setMemNum(int num) {
+    void setMemNum(final int num) {
         E1 = num;
     }
     int getMemNum() {
         return E1;
     }
     /* start/end position */
-    void setMemPstr(int pstr) {
+    void setMemPstr(final int pstr) {
         E2 = pstr;
     }
     int getMemPStr() {
@@ -109,14 +109,14 @@
 
     /* Following information is set, if this stack type is MEM-START */
     /* prev. info (for backtrack  "(...)*" ) */
-    void setMemStart(int start) {
+    void setMemStart(final int start) {
         E3 = start;
     }
     int getMemStart() {
         return E3;
     }
     /* prev. info (for backtrack  "(...)*" ) */
-    void setMemEnd(int end) {
+    void setMemEnd(final int end) {
         E4 = end;
     }
     int getMemEnd() {
@@ -125,14 +125,14 @@
 
     // fifth union member
     /* null check id */
-    void setNullCheckNum(int num) {
+    void setNullCheckNum(final int num) {
         E1 = num;
     }
     int getNullCheckNum() {
         return E1;
     }
     /* start position */
-    void setNullCheckPStr(int pstr) {
+    void setNullCheckPStr(final int pstr) {
         E2 = pstr;
     }
     int getNullCheckPStr() {
@@ -141,21 +141,21 @@
 
     // sixth union member
     /* byte code position */
-    void setCallFrameRetAddr(int addr) {
+    void setCallFrameRetAddr(final int addr) {
         E1 = addr;
     }
     int getCallFrameRetAddr() {
         return E1;
     }
     /* null check id */
-    void setCallFrameNum(int num) {
+    void setCallFrameNum(final int num) {
         E2 = num;
     }
     int getCallFrameNum() {
         return E2;
     }
     /* string position */
-    void setCallFramePStr(int pstr) {
+    void setCallFramePStr(final int pstr) {
         E3 = pstr;
     }
     int getCallFramePStr() {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
index cacf318..2ba5cfd 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/StackMachine.java
@@ -22,7 +22,6 @@
 import static jdk.nashorn.internal.runtime.regexp.joni.BitStatus.bsAt;
 
 import java.lang.ref.WeakReference;
-
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackPopLevel;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.StackType;
 
@@ -35,11 +34,11 @@
     protected final int[]repeatStk;
     protected final int memStartStk, memEndStk;
 
-    protected StackMachine(Regex regex, char[] chars, int p , int end) {
+    protected StackMachine(final Regex regex, final char[] chars, final int p , final int end) {
         super(regex, chars, p, end);
 
         this.stack = regex.stackNeeded ? fetchStack() : null;
-        int n = regex.numRepeat + (regex.numMem << 1);
+        final int n = regex.numRepeat + (regex.numMem << 1);
         this.repeatStk = n > 0 ? new int[n] : null;
 
         memStartStk = regex.numRepeat - 1;
@@ -49,13 +48,13 @@
     }
 
     private static StackEntry[] allocateStack() {
-        StackEntry[]stack = new StackEntry[Config.INIT_MATCH_STACK_SIZE];
+        final StackEntry[]stack = new StackEntry[Config.INIT_MATCH_STACK_SIZE];
         stack[0] = new StackEntry();
         return stack;
     }
 
     private void doubleStack() {
-        StackEntry[] newStack = new StackEntry[stack.length << 1];
+        final StackEntry[] newStack = new StackEntry[stack.length << 1];
         System.arraycopy(stack, 0, newStack, 0, stack.length);
         stack = newStack;
     }
@@ -94,13 +93,13 @@
         return e;
     }
 
-    protected final void pushType(int type) {
+    protected final void pushType(final int type) {
         ensure1().type = type;
         stk++;
     }
 
-    private void push(int type, int pat, int s, int prev) {
-        StackEntry e = ensure1();
+    private void push(final int type, final int pat, final int s, final int prev) {
+        final StackEntry e = ensure1();
         e.type = type;
         e.setStatePCode(pat);
         e.setStatePStr(s);
@@ -108,22 +107,22 @@
         stk++;
     }
 
-    protected final void pushEnsured(int type, int pat) {
-        StackEntry e = stack[stk];
+    protected final void pushEnsured(final int type, final int pat) {
+        final StackEntry e = stack[stk];
         e.type = type;
         e.setStatePCode(pat);
         stk++;
     }
 
-    protected final void pushAlt(int pat, int s, int prev) {
+    protected final void pushAlt(final int pat, final int s, final int prev) {
         push(ALT, pat, s, prev);
     }
 
-    protected final void pushPos(int s, int prev) {
+    protected final void pushPos(final int s, final int prev) {
         push(POS, -1 /*NULL_UCHARP*/, s, prev);
     }
 
-    protected final void pushPosNot(int pat, int s, int prev) {
+    protected final void pushPosNot(final int pat, final int s, final int prev) {
         push(POS_NOT, pat, s, prev);
     }
 
@@ -131,12 +130,12 @@
         pushType(STOP_BT);
     }
 
-    protected final void pushLookBehindNot(int pat, int s, int sprev) {
+    protected final void pushLookBehindNot(final int pat, final int s, final int sprev) {
         push(LOOK_BEHIND_NOT, pat, s, sprev);
     }
 
-    protected final void pushRepeat(int id, int pat) {
-        StackEntry e = ensure1();
+    protected final void pushRepeat(final int id, final int pat) {
+        final StackEntry e = ensure1();
         e.type = REPEAT;
         e.setRepeatNum(id);
         e.setRepeatPCode(pat);
@@ -144,15 +143,15 @@
         stk++;
     }
 
-    protected final void pushRepeatInc(int sindex) {
-        StackEntry e = ensure1();
+    protected final void pushRepeatInc(final int sindex) {
+        final StackEntry e = ensure1();
         e.type = REPEAT_INC;
         e.setSi(sindex);
         stk++;
     }
 
-    protected final void pushMemStart(int mnum, int s) {
-        StackEntry e = ensure1();
+    protected final void pushMemStart(final int mnum, final int s) {
+        final StackEntry e = ensure1();
         e.type = MEM_START;
         e.setMemNum(mnum);
         e.setMemPstr(s);
@@ -163,8 +162,8 @@
         stk++;
     }
 
-    protected final void pushMemEnd(int mnum, int s) {
-        StackEntry e = ensure1();
+    protected final void pushMemEnd(final int mnum, final int s) {
+        final StackEntry e = ensure1();
         e.type = MEM_END;
         e.setMemNum(mnum);
         e.setMemPstr(s);
@@ -174,20 +173,20 @@
         stk++;
     }
 
-    protected final void pushMemEndMark(int mnum) {
-        StackEntry e = ensure1();
+    protected final void pushMemEndMark(final int mnum) {
+        final StackEntry e = ensure1();
         e.type = MEM_END_MARK;
         e.setMemNum(mnum);
         stk++;
     }
 
-    protected final int getMemStart(int mnum) {
+    protected final int getMemStart(final int mnum) {
         int level = 0;
         int stkp = stk;
 
         while (stkp > 0) {
             stkp--;
-            StackEntry e = stack[stkp];
+            final StackEntry e = stack[stkp];
             if ((e.type & MASK_MEM_END_OR_MARK) != 0 && e.getMemNum() == mnum) {
                 level++;
             } else if (e.type == MEM_START && e.getMemNum() == mnum) {
@@ -198,16 +197,16 @@
         return stkp;
     }
 
-    protected final void pushNullCheckStart(int cnum, int s) {
-        StackEntry e = ensure1();
+    protected final void pushNullCheckStart(final int cnum, final int s) {
+        final StackEntry e = ensure1();
         e.type = NULL_CHECK_START;
         e.setNullCheckNum(cnum);
         e.setNullCheckPStr(s);
         stk++;
     }
 
-    protected final void pushNullCheckEnd(int cnum) {
-        StackEntry e = ensure1();
+    protected final void pushNullCheckEnd(final int cnum) {
+        final StackEntry e = ensure1();
         e.type = NULL_CHECK_END;
         e.setNullCheckNum(cnum);
         stk++;
@@ -233,7 +232,7 @@
 
     private StackEntry popFree() {
         while (true) {
-            StackEntry e = stack[--stk];
+            final StackEntry e = stack[--stk];
 
             if ((e.type & MASK_POP_USED) != 0) {
                 return e;
@@ -243,7 +242,7 @@
 
     private StackEntry popMemStart() {
         while (true) {
-            StackEntry e = stack[--stk];
+            final StackEntry e = stack[--stk];
 
             if ((e.type & MASK_POP_USED) != 0) {
                 return e;
@@ -256,7 +255,7 @@
 
     private StackEntry popDefault() {
         while (true) {
-            StackEntry e = stack[--stk];
+            final StackEntry e = stack[--stk];
 
             if ((e.type & MASK_POP_USED) != 0) {
                 return e;
@@ -277,7 +276,7 @@
     protected final void popTilPosNot() {
         while (true) {
             stk--;
-            StackEntry e = stack[stk];
+            final StackEntry e = stack[stk];
 
             if (e.type == POS_NOT) {
                 break;
@@ -298,7 +297,7 @@
     protected final void popTilLookBehindNot() {
         while (true) {
             stk--;
-            StackEntry e = stack[stk];
+            final StackEntry e = stack[stk];
 
             if (e.type == LOOK_BEHIND_NOT) {
                 break;
@@ -320,7 +319,7 @@
         int k = stk;
         while (true) {
             k--;
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
             if ((e.type & MASK_TO_VOID_TARGET) != 0) {
                 e.type = VOID;
             } else if (e.type == POS) {
@@ -335,7 +334,7 @@
         int k = stk;
         while (true) {
             k--;
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
 
             if ((e.type & MASK_TO_VOID_TARGET) != 0) {
                 e.type = VOID;
@@ -347,11 +346,11 @@
     }
 
     // int for consistency with other null check routines
-    protected final int nullCheck(int id, int s) {
+    protected final int nullCheck(final int id, final int s) {
         int k = stk;
         while (true) {
             k--;
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
 
             if (e.type == NULL_CHECK_START) {
                 if (e.getNullCheckNum() == id) {
@@ -361,12 +360,12 @@
         }
     }
 
-    protected final int nullCheckRec(int id, int s) {
+    protected final int nullCheckRec(final int id, final int s) {
         int level = 0;
         int k = stk;
         while (true) {
             k--;
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
 
             if (e.type == NULL_CHECK_START) {
                 if (e.getNullCheckNum() == id) {
@@ -382,7 +381,7 @@
         }
     }
 
-    protected final int nullCheckMemSt(int id, int s) {
+    protected final int nullCheckMemSt(final int id, final int s) {
         int k = stk;
         int isNull;
         while (true) {
@@ -426,7 +425,7 @@
         return isNull;
     }
 
-    protected final int nullCheckMemStRec(int id, int s) {
+    protected final int nullCheckMemStRec(final int id, final int s) {
         int level = 0;
         int k = stk;
         int isNull;
@@ -477,12 +476,12 @@
         return isNull;
     }
 
-    protected final int getRepeat(int id) {
+    protected final int getRepeat(final int id) {
         int level = 0;
         int k = stk;
         while (true) {
             k--;
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
 
             if (e.type == REPEAT) {
                 if (level == 0) {
@@ -501,7 +500,7 @@
         int k = stk;
         while (true) {
             k--;
-            StackEntry e = stack[k];
+            final StackEntry e = stack[k];
 
             if (e.type == CALL_FRAME) {
                 if (level == 0) {
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
index 518a416..e20ff02 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Syntax.java
@@ -30,7 +30,7 @@
     public final int options;
     public final MetaCharTable metaCharTable;
 
-    public Syntax(int op, int op2, int behavior, int options, MetaCharTable metaCharTable) {
+    public Syntax(final int op, final int op2, final int behavior, final int options, final MetaCharTable metaCharTable) {
         this.op = op;
         this.op2 = op2;
         this.behavior = behavior;
@@ -46,8 +46,8 @@
         public final int oneOrMoreTime;
         public final int anyCharAnyTime;
 
-        public MetaCharTable(int esc, int anyChar, int anyTime,
-                             int zeroOrOneTime, int oneOrMoreTime, int anyCharAnyTime) {
+        public MetaCharTable(final int esc, final int anyChar, final int anyTime,
+                             final int zeroOrOneTime, final int oneOrMoreTime, final int anyCharAnyTime) {
             this.esc = esc;
             this.anyChar = anyChar;
             this.anyTime = anyTime;
@@ -61,7 +61,7 @@
      * OP
      *
      */
-    protected boolean isOp(int opm) {
+    protected boolean isOp(final int opm) {
         return (op & opm) != 0;
     }
 
@@ -194,7 +194,7 @@
      * OP
      *
      */
-    protected boolean isOp2(int opm) {
+    protected boolean isOp2(final int opm) {
         return (op2 & opm) != 0;
     }
 
@@ -282,7 +282,7 @@
      * BEHAVIOR
      *
      */
-    protected boolean isBehavior(int bvm) {
+    protected boolean isBehavior(final int bvm) {
         return (behavior & bvm) != 0;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java
index 5ac22db..095bb07 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/Token.java
@@ -33,21 +33,21 @@
     int getC() {
         return INT1;
     }
-    void setC(int c) {
+    void setC(final int c) {
         INT1 = c;
     }
 
     int getCode() {
         return INT1;
     }
-    void setCode(int code) {
+    void setCode(final int code) {
         INT1 = code;
     }
 
     int getAnchor() {
         return INT1;
     }
-    void setAnchor(int anchor) {
+    void setAnchor(final int anchor) {
         INT1 = anchor;
     }
 
@@ -55,35 +55,35 @@
     int getRepeatLower() {
         return INT1;
     }
-    void setRepeatLower(int lower) {
+    void setRepeatLower(final int lower) {
         INT1 = lower;
     }
 
     int getRepeatUpper() {
         return INT2;
     }
-    void setRepeatUpper(int upper) {
+    void setRepeatUpper(final int upper) {
         INT2 = upper;
     }
 
     boolean getRepeatGreedy() {
         return INT3 != 0;
     }
-    void setRepeatGreedy(boolean greedy) {
+    void setRepeatGreedy(final boolean greedy) {
         INT3 = greedy ? 1 : 0;
     }
 
     boolean getRepeatPossessive() {
         return INT4 != 0;
     }
-    void setRepeatPossessive(boolean possessive) {
+    void setRepeatPossessive(final boolean possessive) {
         INT4 = possessive ? 1 : 0;
     }
 
     int getBackrefRef() {
         return INT2;
     }
-    void setBackrefRef(int ref1) {
+    void setBackrefRef(final int ref1) {
         INT2 = ref1;
     }
 
@@ -91,14 +91,14 @@
     int getPropCType() {
         return INT1;
     }
-    void setPropCType(int ctype) {
+    void setPropCType(final int ctype) {
         INT1 = ctype;
     }
 
     boolean getPropNot() {
         return INT2 != 0;
     }
-    void setPropNot(boolean not) {
+    void setPropNot(final boolean not) {
         INT2 = not ? 1 : 0;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java
index 91f7f7a..87cb6dc 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/WarnCallback.java
@@ -25,7 +25,7 @@
 public interface WarnCallback {
     WarnCallback DEFAULT = new WarnCallback() {
         @Override
-        public void warn(String message) {
+        public void warn(final String message) {
             System.err.println(message);
         }
     };
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java
index d07a269..f4fd85a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnchorNode.java
@@ -26,7 +26,7 @@
     public Node target;
     public int charLength;
 
-    public AnchorNode(int type) {
+    public AnchorNode(final int type) {
         this.type = type;
         charLength = -1;
     }
@@ -37,7 +37,7 @@
     }
 
     @Override
-    protected void setChild(Node newChild) {
+    protected void setChild(final Node newChild) {
         target = newChild;
     }
 
@@ -46,7 +46,7 @@
         return target;
     }
 
-    public void setTarget(Node tgt) {
+    public void setTarget(final Node tgt) {
         target = tgt;
         tgt.parent = this;
     }
@@ -57,15 +57,15 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder();
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder();
         value.append("\n  type: " + typeToString());
         value.append("\n  target: " + pad(target, level + 1));
         return value.toString();
     }
 
     public String typeToString() {
-        StringBuilder type = new StringBuilder();
+        final StringBuilder type = new StringBuilder();
         if (isType(BEGIN_BUF)) type.append("BEGIN_BUF ");
         if (isType(BEGIN_LINE)) type.append("BEGIN_LINE ");
         if (isType(BEGIN_POSITION)) type.append("BEGIN_POSITION ");
@@ -85,7 +85,7 @@
         return type.toString();
     }
 
-    private boolean isType(int type) {
+    private boolean isType(final int type) {
         return (this.type & type) != 0;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java
index 9558ce2..69659b7 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/AnyCharNode.java
@@ -33,8 +33,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        String value = "";
+    public String toString(final int level) {
+        final String value = "";
         return value;
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java
index 478222f..75a9c6a 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/BackRefNode.java
@@ -24,7 +24,7 @@
 public final class BackRefNode extends StateNode {
     public final int backRef;
 
-    public BackRefNode(int backRef, ScanEnvironment env) {
+    public BackRefNode(final int backRef, final ScanEnvironment env) {
         this.backRef = backRef;
 
         if (backRef <= env.numMem && env.memNodes[backRef] == null) {
@@ -43,8 +43,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder(super.toString(level));
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder(super.toString(level));
         value.append("\n  back: ").append(backRef);
         return value.toString();
     }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java
index b33eeee..ce3bef1 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/CClassNode.java
@@ -19,7 +19,12 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni.ast;
 
-import jdk.nashorn.internal.runtime.regexp.joni.*;
+import jdk.nashorn.internal.runtime.regexp.joni.BitSet;
+import jdk.nashorn.internal.runtime.regexp.joni.CodeRangeBuffer;
+import jdk.nashorn.internal.runtime.regexp.joni.Config;
+import jdk.nashorn.internal.runtime.regexp.joni.EncodingHelper;
+import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
+import jdk.nashorn.internal.runtime.regexp.joni.Syntax;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.CCSTATE;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.CCVALTYPE;
 import jdk.nashorn.internal.runtime.regexp.joni.encoding.CharacterType;
@@ -94,9 +99,9 @@
     }
 
     @Override
-    public boolean equals(Object other) {
+    public boolean equals(final Object other) {
         if (!(other instanceof CClassNode)) return false;
-        CClassNode cc = (CClassNode)other;
+        final CClassNode cc = (CClassNode)other;
         return ctype == cc.ctype && isNot() == cc.isNot();
     }
 
@@ -113,8 +118,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder();
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder();
         value.append("\n  flags: " + flagsToString());
         value.append("\n  bs: " + pad(bs, level + 1));
         value.append("\n  mbuf: " + pad(mbuf, level + 1));
@@ -123,7 +128,7 @@
     }
 
     public String flagsToString() {
-        StringBuilder flags = new StringBuilder();
+        final StringBuilder flags = new StringBuilder();
         if (isNot()) flags.append("NOT ");
         if (isShare()) flags.append("SHARE ");
         return flags.toString();
@@ -133,11 +138,11 @@
         return mbuf == null && bs.isEmpty();
     }
 
-    public void addCodeRangeToBuf(int from, int to) {
+    public void addCodeRangeToBuf(final int from, final int to) {
         mbuf = CodeRangeBuffer.addCodeRangeToBuff(mbuf, from, to);
     }
 
-    public void addCodeRange(ScanEnvironment env, int from, int to) {
+    public void addCodeRange(final ScanEnvironment env, final int from, final int to) {
         mbuf = CodeRangeBuffer.addCodeRange(mbuf, env, from, to);
     }
 
@@ -155,22 +160,22 @@
     }
 
     // and_cclass
-    public void and(CClassNode other) {
-        boolean not1 = isNot();
+    public void and(final CClassNode other) {
+        final boolean not1 = isNot();
         BitSet bsr1 = bs;
-        CodeRangeBuffer buf1 = mbuf;
-        boolean not2 = other.isNot();
+        final CodeRangeBuffer buf1 = mbuf;
+        final boolean not2 = other.isNot();
         BitSet bsr2 = other.bs;
-        CodeRangeBuffer buf2 = other.mbuf;
+        final CodeRangeBuffer buf2 = other.mbuf;
 
         if (not1) {
-            BitSet bs1 = new BitSet();
+            final BitSet bs1 = new BitSet();
             bsr1.invertTo(bs1);
             bsr1 = bs1;
         }
 
         if (not2) {
-            BitSet bs2 = new BitSet();
+            final BitSet bs2 = new BitSet();
             bsr2.invertTo(bs2);
             bsr2 = bs2;
         }
@@ -202,22 +207,22 @@
     }
 
     // or_cclass
-    public void or(CClassNode other) {
-        boolean not1 = isNot();
+    public void or(final CClassNode other) {
+        final boolean not1 = isNot();
         BitSet bsr1 = bs;
-        CodeRangeBuffer buf1 = mbuf;
-        boolean not2 = other.isNot();
+        final CodeRangeBuffer buf1 = mbuf;
+        final boolean not2 = other.isNot();
         BitSet bsr2 = other.bs;
-        CodeRangeBuffer buf2 = other.mbuf;
+        final CodeRangeBuffer buf2 = other.mbuf;
 
         if (not1) {
-            BitSet bs1 = new BitSet();
+            final BitSet bs1 = new BitSet();
             bsr1.invertTo(bs1);
             bsr1 = bs1;
         }
 
         if (not2) {
-            BitSet bs2 = new BitSet();
+            final BitSet bs2 = new BitSet();
             bsr2.invertTo(bs2);
             bsr2 = bs2;
         }
@@ -246,8 +251,8 @@
     }
 
     // add_ctype_to_cc_by_range // Encoding out!
-    public void addCTypeByRange(int ctype, boolean not, int sbOut, int mbr[]) {
-        int n = mbr[0];
+    public void addCTypeByRange(final int ctype, final boolean not, final int sbOut, final int mbr[]) {
+        final int n = mbr[0];
 
         if (!not) {
             for (int i=0; i<n; i++) {
@@ -314,7 +319,7 @@
         }
     }
 
-    public void addCType(int ctype, boolean not, ScanEnvironment env, IntHolder sbOut) {
+    public void addCType(int ctype, final boolean not, final ScanEnvironment env, final IntHolder sbOut) {
         if (Config.NON_UNICODE_SDW) {
             switch(ctype) {
             case CharacterType.D:
@@ -343,7 +348,7 @@
             }
         }
 
-        int[] ranges = EncodingHelper.ctypeCodeRange(ctype, sbOut);
+        final int[] ranges = EncodingHelper.ctypeCodeRange(ctype, sbOut);
         if (ranges != null) {
             addCTypeByRange(ctype, not, sbOut.value, ranges);
             return;
@@ -416,7 +421,7 @@
         public CCSTATE state;
     }
 
-    public void nextStateClass(CCStateArg arg, ScanEnvironment env) {
+    public void nextStateClass(final CCStateArg arg, final ScanEnvironment env) {
         if (arg.state == CCSTATE.RANGE) throw new SyntaxException(ErrorMessages.ERR_CHAR_CLASS_VALUE_AT_END_OF_RANGE);
 
         if (arg.state == CCSTATE.VALUE && arg.type != CCVALTYPE.CLASS) {
@@ -430,7 +435,7 @@
         arg.type = CCVALTYPE.CLASS;
     }
 
-    public void nextStateValue(CCStateArg arg, ScanEnvironment env) {
+    public void nextStateValue(final CCStateArg arg, final ScanEnvironment env) {
 
         switch(arg.state) {
         case VALUE:
@@ -493,7 +498,7 @@
     }
 
     // onig_is_code_in_cc_len
-    public boolean isCodeInCCLength(int code) {
+    public boolean isCodeInCCLength(final int code) {
         boolean found;
 
         if (code > 0xff) {
@@ -510,7 +515,7 @@
     }
 
     // onig_is_code_in_cc
-    public boolean isCodeInCC(int code) {
+    public boolean isCodeInCC(final int code) {
          return isCodeInCCLength(code);
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java
index e8bcb30..45dc386 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/ConsAltNode.java
@@ -20,7 +20,6 @@
 package jdk.nashorn.internal.runtime.regexp.joni.ast;
 
 import java.util.Set;
-
 import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
 import jdk.nashorn.internal.runtime.regexp.joni.exception.ErrorMessages;
 import jdk.nashorn.internal.runtime.regexp.joni.exception.InternalException;
@@ -30,7 +29,7 @@
     public ConsAltNode cdr;
     private int type;           // List or Alt
 
-    private ConsAltNode(Node car, ConsAltNode cdr, int type) {
+    private ConsAltNode(final Node car, final ConsAltNode cdr, final int type) {
         this.car = car;
         if (car != null) car.parent = this;
         this.cdr = cdr;
@@ -39,16 +38,16 @@
         this.type = type;
     }
 
-    public static ConsAltNode newAltNode(Node left, ConsAltNode right) {
+    public static ConsAltNode newAltNode(final Node left, final ConsAltNode right) {
         return new ConsAltNode(left, right, ALT);
     }
 
-    public static ConsAltNode newListNode(Node left, ConsAltNode right) {
+    public static ConsAltNode newListNode(final Node left, final ConsAltNode right) {
         return new ConsAltNode(left, right, LIST);
     }
 
-    public static ConsAltNode listAdd(ConsAltNode list, Node x) {
-        ConsAltNode n = newListNode(x, null);
+    public static ConsAltNode listAdd(ConsAltNode list, final Node x) {
+        final ConsAltNode n = newListNode(x, null);
 
         if (list != null) {
             while (list.cdr != null) {
@@ -73,7 +72,7 @@
     }
 
     @Override
-    protected void setChild(Node newChild) {
+    protected void setChild(final Node newChild) {
         car = newChild;
     }
 
@@ -83,13 +82,13 @@
     }
 
     @Override
-    public void swap(Node with) {
+    public void swap(final Node with) {
         if (cdr != null) {
             cdr.parent = with;
             if (with instanceof ConsAltNode) {
-                ConsAltNode withCan = (ConsAltNode)with;
+                final ConsAltNode withCan = (ConsAltNode)with;
                 withCan.cdr.parent = this;
-                ConsAltNode tmp = cdr;
+                final ConsAltNode tmp = cdr;
                 cdr = withCan.cdr;
                 withCan.cdr = tmp;
             }
@@ -98,7 +97,7 @@
     }
 
     @Override
-    public void verifyTree(Set<Node> set, WarnCallback warnings) {
+    public void verifyTree(final Set<Node> set, final WarnCallback warnings) {
         if (!set.contains(this)) {
             set.add(this);
             if (car != null) {
@@ -116,13 +115,13 @@
         }
     }
 
-    public Node setCar(Node ca) {
+    public Node setCar(final Node ca) {
         car = ca;
         ca.parent = this;
         return car;
     }
 
-    public ConsAltNode setCdr(ConsAltNode cd) {
+    public ConsAltNode setCdr(final ConsAltNode cd) {
         cdr = cd;
         cd.parent = this;
         return cdr;
@@ -141,8 +140,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder();
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder();
         value.append("\n  car: " + pad(car, level + 1));
         value.append("\n  cdr: " + (cdr == null ? "NULL" : cdr.toString()));
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
index e494c1c..cd5a1e9 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/EncloseNode.java
@@ -35,7 +35,7 @@
     public int optCount;            // referenced count in optimize_node_left()
 
     // node_new_enclose / onig_node_new_enclose
-    public EncloseNode(int type) {
+    public EncloseNode(final int type) {
         this.type = type;
         callAddr = -1;
     }
@@ -46,7 +46,7 @@
     }
 
     // node_new_option
-    public EncloseNode(int option, int i) {
+    public EncloseNode(final int option, final int i) {
         this(OPTION);
         this.option = option;
     }
@@ -57,7 +57,7 @@
     }
 
     @Override
-    protected void setChild(Node newChild) {
+    protected void setChild(final Node newChild) {
         target = newChild;
     }
 
@@ -66,7 +66,7 @@
         return target;
     }
 
-    public void setTarget(Node tgt) {
+    public void setTarget(final Node tgt) {
         target = tgt;
         tgt.parent = this;
     }
@@ -77,8 +77,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder(super.toString(level));
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder(super.toString(level));
         value.append("\n  type: " + typeToString());
         value.append("\n  regNum: " + regNum);
         value.append("\n  option: " + Option.toString(option));
@@ -93,7 +93,7 @@
     }
 
     public String typeToString() {
-        StringBuilder types = new StringBuilder();
+        final StringBuilder types = new StringBuilder();
         if (isStopBacktrack()) types.append("STOP_BACKTRACK ");
         if (isMemory()) types.append("MEMORY ");
         if (isOption()) types.append("OPTION ");
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java
index fdf9687..dbf812e 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/Node.java
@@ -20,7 +20,6 @@
 package jdk.nashorn.internal.runtime.regexp.joni.ast;
 
 import java.util.Set;
-
 import jdk.nashorn.internal.runtime.regexp.joni.Config;
 import jdk.nashorn.internal.runtime.regexp.joni.WarnCallback;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.NodeType;
@@ -34,10 +33,10 @@
         return 1 << getType();
     }
 
-    protected void setChild(Node tgt){}         // default definition
+    protected void setChild(final Node tgt){}         // default definition
     protected Node getChild(){return null;}     // default definition
 
-    public void swap(Node with) {
+    public void swap(final Node with) {
         Node tmp;
 
         //if (getChild() != null) getChild().parent = with;
@@ -57,7 +56,7 @@
     }
 
     // overridden by ConsAltNode and CallNode
-    public void verifyTree(Set<Node> set, WarnCallback warnings) {
+    public void verifyTree(final Set<Node> set, final WarnCallback warnings) {
         if (!set.contains(this) && getChild() != null) {
             set.add(this);
             if (getChild().parent != this) {
@@ -76,15 +75,15 @@
 
     @Override
     public final String toString() {
-        StringBuilder s = new StringBuilder();
+        final StringBuilder s = new StringBuilder();
         s.append("<" + getAddressName() + " (" + (parent == null ? "NULL" : parent.getAddressName())  + ")>");
         return s + toString(0);
     }
 
-    protected static String pad(Object value, int level) {
+    protected static String pad(final Object value, final int level) {
         if (value == null) return "NULL";
 
-        StringBuilder pad = new StringBuilder("  ");
+        final StringBuilder pad = new StringBuilder("  ");
         for (int i=0; i<level; i++) pad.append(pad);
 
         return value.toString().replace("\n",  "\n" + pad);
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
index 7d84acc..6afac36 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/QuantifierNode.java
@@ -19,12 +19,18 @@
  */
 package jdk.nashorn.internal.runtime.regexp.joni.ast;
 
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.A;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.AQ;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.ASIS;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.DEL;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.PQ_Q;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.P_QQ;
+import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.QQ;
+
 import jdk.nashorn.internal.runtime.regexp.joni.Config;
 import jdk.nashorn.internal.runtime.regexp.joni.ScanEnvironment;
 import jdk.nashorn.internal.runtime.regexp.joni.constants.TargetInfo;
 
-import static jdk.nashorn.internal.runtime.regexp.joni.ast.QuantifierNode.ReduceType.*;
-
 public final class QuantifierNode extends StateNode {
 
     public Node target;
@@ -66,7 +72,7 @@
     };
 
 
-    public QuantifierNode(int lower, int upper, boolean byNumber) {
+    public QuantifierNode(final int lower, final int upper, final boolean byNumber) {
         this.lower = lower;
         this.upper = upper;
         greedy = true;
@@ -81,7 +87,7 @@
     }
 
     @Override
-    protected void setChild(Node newChild) {
+    protected void setChild(final Node newChild) {
         target = newChild;
     }
 
@@ -90,13 +96,13 @@
         return target;
     }
 
-    public void setTarget(Node tgt) {
+    public void setTarget(final Node tgt) {
         target = tgt;
         tgt.parent = this;
     }
 
-    public StringNode convertToString(int flag) {
-        StringNode sn = new StringNode();
+    public StringNode convertToString(final int flag) {
+        final StringNode sn = new StringNode();
         sn.flag = flag;
         sn.swap(this);
         return sn;
@@ -108,8 +114,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder(super.toString(level));
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder(super.toString(level));
         value.append("\n  target: " + pad(target, level + 1));
         value.append("\n  lower: " + lower);
         value.append("\n  upper: " + upper);
@@ -146,7 +152,7 @@
         return -1;
     }
 
-    protected void set(QuantifierNode other) {
+    protected void set(final QuantifierNode other) {
         setTarget(other.target);
         other.target = null;
         lower = other.lower;
@@ -161,9 +167,9 @@
         isRefered = other.isRefered;
     }
 
-    public void reduceNestedQuantifier(QuantifierNode other) {
-        int pnum = popularNum();
-        int cnum = other.popularNum();
+    public void reduceNestedQuantifier(final QuantifierNode other) {
+        final int pnum = popularNum();
+        final int cnum = other.popularNum();
 
         if (pnum < 0 || cnum < 0) return;
 
@@ -224,16 +230,16 @@
     }
 
     @SuppressWarnings("fallthrough")
-    public int setQuantifier(Node tgt, boolean group, ScanEnvironment env, char[] chars, int p, int end) {
+    public int setQuantifier(final Node tgt, final boolean group, final ScanEnvironment env, final char[] chars, final int p, final int end) {
         if (lower == 1 && upper == 1) return 1;
 
         switch(tgt.getType()) {
 
         case STR:
             if (!group) {
-                StringNode sn = (StringNode)tgt;
+                final StringNode sn = (StringNode)tgt;
                 if (sn.canBeSplit()) {
-                    StringNode n = sn.splitLastChar();
+                    final StringNode n = sn.splitLastChar();
                     if (n != null) {
                         setTarget(n);
                         return 2;
@@ -245,9 +251,9 @@
         case QTFR:
             /* check redundant double repeat. */
             /* verbose warn (?:.?)? etc... but not warn (.?)? etc... */
-            QuantifierNode qnt = (QuantifierNode)tgt;
-            int nestQNum = popularNum();
-            int targetQNum = qnt.popularNum();
+            final QuantifierNode qnt = (QuantifierNode)tgt;
+            final int nestQNum = popularNum();
+            final int targetQNum = qnt.popularNum();
 
             if (Config.USE_WARNING_REDUNDANT_NESTED_REPEAT_OPERATOR) {
                 if (!isByNumber() && !qnt.isByNumber() && env.syntax.warnReduntantNestedRepeat()) {
@@ -290,7 +296,7 @@
     }
 
     public static final int REPEAT_INFINITE         = -1;
-    public static boolean isRepeatInfinite(int n) {
+    public static boolean isRepeatInfinite(final int n) {
         return n == REPEAT_INFINITE;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
index d2b3c95..29c6786 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StateNode.java
@@ -25,12 +25,12 @@
     protected int state;
 
     @Override
-    public String toString(int level) {
+    public String toString(final int level) {
         return "\n  state: " + stateToString();
     }
 
     public String stateToString() {
-        StringBuilder states = new StringBuilder();
+        final StringBuilder states = new StringBuilder();
         if (isMinFixed()) states.append("MIN_FIXED ");
         if (isMaxFixed()) states.append("MAX_FIXED ");
         if (isMark1()) states.append("MARK1 ");
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java
index 0618ddf..73dfd29 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/ast/StringNode.java
@@ -38,14 +38,14 @@
         this.chars = new char[NODE_STR_BUF_SIZE];
     }
 
-    public StringNode(char[] chars, int p, int end) {
+    public StringNode(final char[] chars, final int p, final int end) {
         this.chars = chars;
         this.p = p;
         this.end = end;
         setShared();
     }
 
-    public StringNode(char c) {
+    public StringNode(final char c) {
         this();
         chars[end++] = c;
     }
@@ -53,10 +53,10 @@
     /* Ensure there is ahead bytes available in node's buffer
      * (assumes that the node is not shared)
      */
-    public void ensure(int ahead) {
-        int len = (end - p) + ahead;
+    public void ensure(final int ahead) {
+        final int len = (end - p) + ahead;
         if (len >= chars.length) {
-            char[] tmp = new char[len + NODE_STR_MARGIN];
+            final char[] tmp = new char[len + NODE_STR_MARGIN];
             System.arraycopy(chars, p, tmp, 0, end - p);
             chars = tmp;
         }
@@ -64,10 +64,10 @@
 
     /* COW and/or ensure there is ahead bytes available in node's buffer
      */
-    private void modifyEnsure(int ahead) {
+    private void modifyEnsure(final int ahead) {
         if (isShared()) {
-            int len = (end - p) + ahead;
-            char[] tmp = new char[len + NODE_STR_MARGIN];
+            final int len = (end - p) + ahead;
+            final char[] tmp = new char[len + NODE_STR_MARGIN];
             System.arraycopy(chars, p, tmp, 0, end - p);
             chars = tmp;
             end = end - p;
@@ -89,8 +89,8 @@
     }
 
     @Override
-    public String toString(int level) {
-        StringBuilder value = new StringBuilder();
+    public String toString(final int level) {
+        final StringBuilder value = new StringBuilder();
         value.append("\n  bytes: '");
         for (int i=p; i<end; i++) {
             if (chars[i] >= 0x20 && chars[i] < 0x7f) {
@@ -111,7 +111,7 @@
         StringNode n = null;
 
         if (end > p) {
-            int prev = EncodingHelper.prevCharHead(p, end);
+            final int prev = EncodingHelper.prevCharHead(p, end);
             if (prev != -1 && prev > p) { /* can be splitted. */
                 n = new StringNode(chars, prev, end);
                 if (isRaw()) n.setRaw();
@@ -125,26 +125,26 @@
         return end > p && 1 < (end - p);
     }
 
-    public void set(char[] chars, int p, int end) {
+    public void set(final char[] chars, final int p, final int end) {
         this.chars = chars;
         this.p = p;
         this.end = end;
         setShared();
     }
 
-    public void cat(char[] cat, int catP, int catEnd) {
-        int len = catEnd - catP;
+    public void cat(final char[] cat, final int catP, final int catEnd) {
+        final int len = catEnd - catP;
         modifyEnsure(len);
         System.arraycopy(cat, catP, chars, end, len);
         end += len;
     }
 
-    public void cat(char c) {
+    public void cat(final char c) {
         modifyEnsure(1);
         chars[end++] = c;
     }
 
-    public void catCode(int code) {
+    public void catCode(final int code) {
         cat((char)code);
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java
index 5c02457..68d8a07 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/encoding/ObjPtr.java
@@ -24,7 +24,7 @@
         this(null);
     }
 
-    public ObjPtr(T p) {
+    public ObjPtr(final T p) {
         this.p = p;
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java
index 47028ae..6f2b024 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/InternalException.java
@@ -22,7 +22,7 @@
 public class InternalException extends JOniException{
     private static final long serialVersionUID = -3871816465397927992L;
 
-    public InternalException(String message) {
+    public InternalException(final String message) {
         super(message);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
index a5f237f..8024a56 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/JOniException.java
@@ -22,7 +22,7 @@
 public class JOniException extends RuntimeException{
     private static final long serialVersionUID = -6027192180014164667L;
 
-    public JOniException(String message) {
+    public JOniException(final String message) {
         super(message);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java
index e53fe36..172e788 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/SyntaxException.java
@@ -22,7 +22,7 @@
 public class SyntaxException extends JOniException{
     private static final long serialVersionUID = 7862720128961874288L;
 
-    public SyntaxException(String message) {
+    public SyntaxException(final String message) {
         super(message);
     }
 }
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
index 597fe22..1ed57d4 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
+++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/joni/exception/ValueException.java
@@ -22,11 +22,11 @@
 public class ValueException extends SyntaxException{
     private static final long serialVersionUID = -196013852479929134L;
 
-    public ValueException(String message) {
+    public ValueException(final String message) {
         super(message);
     }
 
-    public ValueException(String message, String str) {
+    public ValueException(final String message, final String str) {
         super(message.replaceAll("%n", str));
     }
 
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
index c98c1c7..73445ec 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties
@@ -78,8 +78,10 @@
 type.error.not.a.function={0} is not a function
 type.error.not.a.constructor={0} is not a constructor function
 type.error.not.a.file={0} is not a File
+type.error.not.a.numeric.array={0} is not a numeric array
 type.error.not.a.bytebuffer={0} is not a java.nio.ByteBuffer
 type.error.not.an.arraybuffer.in.dataview=First arg to DataView constructor must be an ArrayBuffer
+type.error.no.reflection.with.classfilter=Java reflection not supported when class filter is present
 
 # operations not permitted on undefined
 type.error.cant.call.undefined=Cannot call undefined
@@ -91,6 +93,9 @@
 type.error.property.has.no.setter=Cannot set property "{0}" of {1} that has only a getter
 type.error.cant.set.proto.to.non.object=Cannot set Object {0}'s __proto__ to be a non-object like {1}
 type.error.no.such.function={1} has no such function "{0}"
+type.error.no.such.java.class=No such Java class: {0}
+type.error.no.such.java.constructor=No such Java constructor: {0}
+type.error.improper.constructor.signature=Java constructor signature invalid: {0}
 type.error.cant.get.property=Cannot get property "{0}" of {1}
 type.error.cant.set.property=Cannot set property "{0}" of {1}
 type.error.cant.delete.property=Cannot delete property "{0}" of {1}
@@ -138,6 +143,7 @@
 type.error.method.not.constructor=Java method {0} can't be used as a constructor.
 type.error.env.not.object=$ENV must be an Object.
 type.error.unsupported.java.to.type=Unsupported Java.to target type {0}.
+type.error.constructor.requires.new=Constructor {0} requires 'new'.
 type.error.new.on.nonpublic.javatype=new cannot be used with non-public java type {0}.
 
 range.error.dataview.constructor.offset=Wrong offset or length in DataView constructor
@@ -149,6 +155,7 @@
 range.error.invalid.radix=radix argument must be in [2, 36]
 range.error.invalid.date=Invalid Date
 range.error.too.many.errors=Script contains too many errors: {0} errors
+range.error.concat.string.too.big=Concatenated String is too big
 
 reference.error.not.defined="{0}" is not defined
 reference.error.cant.be.used.as.lhs="{0}" can not be used as the left-hand side of assignment
diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
index 9262a40..b6d98dc 100644
--- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
+++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Options.properties
@@ -177,7 +177,7 @@
     is_undocumented=true,                                                    \
     params="<module:level>,*",                                               \
     desc="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].",                   \
     type=Log                                                                 \
 }
 
@@ -197,7 +197,15 @@
 nashorn.option.lazy.compilation = {                                                                      \
     name="--lazy-compilation",                                                                           \
     is_undocumented=true,                                                                                \
-    desc="EXPERIMENTAL: Use lazy code generation strategies - do not compile the entire script at once." \
+    desc="Use lazy code generation strategies - do not compile the entire script at once.", \
+    default=true                                   \
+}
+
+nashorn.option.optimistic.types = {                                                                      \
+    name="--optimistic-types",                                                                           \
+    is_undocumented=true,                                                                                \
+    desc="Use optimistic type assumptions with deoptimizing recompilation.", \
+    default=true                                   \
 }
 
 nashorn.option.loader.per.compile = {              \
@@ -211,23 +219,23 @@
     name="--no-java",                              \
     short_name="-nj",                              \
     is_undocumented=true,                          \
-    desc="No Java support",                        \
+    desc="Disable Java support.",                  \
     default=false                                  \
 }
 
-nashorn.option.no.syntax.extensions = {            \
-    name="--no-syntax-extensions",                 \
-    short_name="-nse",                             \
-    is_undocumented=true,                          \
-    desc="No non-standard syntax extensions",      \
-    default=false                                  \
+nashorn.option.no.syntax.extensions = {              \
+    name="--no-syntax-extensions",                   \
+    short_name="-nse",                               \
+    is_undocumented=true,                            \
+    desc="Disallow non-standard syntax extensions.", \
+    default=false                                    \
 }
 
 nashorn.option.no.typed.arrays = {                 \
     name="--no-typed-arrays",                      \
     short_name="-nta",                             \
     is_undocumented=true,                          \
-    desc="No Typed arrays support",                \
+    desc="Disable typed arrays support.",          \
     default=false                                  \
 }
 
@@ -266,8 +274,11 @@
 
 nashorn.option.print.code = { \
     name="--print-code",      \
+    short_name="-pc",         \
     is_undocumented=true,     \
-    desc="Print bytecode."    \
+    params="[dir:<output-dir>,function:<name>]", \
+    type=keyvalues,           \
+    desc="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."  \
 }
 
 nashorn.option.print.mem.usage = {                            \
@@ -284,12 +295,14 @@
 
 nashorn.option.print.parse = {   \
     name="--print-parse",        \
+    short_name="-pp",            \
     is_undocumented=true,        \
     desc="Print the parse tree." \
 }
 
 nashorn.option.print.lower.parse = {            \
     name="--print-lower-parse",                 \
+    short_name="-plp",                          \
     is_undocumented=true,                       \
     desc="Print the parse tree after lowering." \
 }
@@ -300,12 +313,6 @@
     desc="Print the symbol table." \
 }
 
-nashorn.option.range.analysis = { \
-    name="--range-analysis",      \
-    is_undocumented=true,         \
-    desc="EXPERIMENTAL: Do range analysis using known compile time types, and try to narrow number types" \
-}    
-
 nashorn.option.D = {                                                          \
     name="-D",                                                                \
     desc="-Dname=value. Set a system property. This option can be repeated.", \
@@ -322,28 +329,20 @@
     desc="Enable scripting features."   \
 }
 
-nashorn.option.specialize.calls = {                                                              \
-    name="--specialize-calls",                                                                   \
-    is_undocumented=true,                                                                        \
-    type=String,                                                                                 \
-    params="[=function_1,...,function_n]",                                                       \
-    desc="EXPERIMENTAL: Specialize all or a set of method according to callsite parameter types" \
+nashorn.option.stdout = {                                                \
+    name="--stdout",                                                     \
+    is_undocumented=true,                                                \
+    type=String,                                                         \
+    params="<output console>",                                           \
+    desc="Redirect stdout to a filename or to another tty, e.g. stderr." \
 }
 
-nashorn.option.stdout = {                                               \
-    name="--stdout",                                                    \
-    is_undocumented=true,                                               \
-    type=String,                                                        \
-    params="<output console>",                                          \
-    desc="Redirect stdout to a filename or to another tty, e.g. stderr" \
-}
-
-nashorn.option.stderr = {                                               \
-    name="--stderr",                                                    \
-    is_undocumented=true,                                               \
-    type=String,                                                        \
-    params="<output console>",                                          \
-    desc="Redirect stderr to a filename or to another tty, e.g. stdout" \
+nashorn.option.stderr = {                                                \
+    name="--stderr",                                                     \
+    is_undocumented=true,                                                \
+    type=String,                                                         \
+    params="<output console>",                                           \
+    desc="Redirect stderr to a filename or to another tty, e.g. stdout." \
 }
 
 nashorn.option.timezone = {                    \
@@ -363,14 +362,14 @@
     type=Locale                              \
 }
 
-nashorn.option.trace.callsites = {                                              \
-    name="--trace-callsites",                                                   \
-    short_name="-tcs",                                                          \
-    is_undocumented=true,                                                       \
-    type=keyvalues,                                                             \
-    params="[=[option,]*]",                                                     \
-    desc="Enable callsite trace mode. Options are: miss [trace callsite misses] \
-    enterexit [trace callsite enter/exit], objects [print object properties]"   \
+nashorn.option.trace.callsites = {                                               \
+    name="--trace-callsites",                                                    \
+    short_name="-tcs",                                                           \
+    is_undocumented=true,                                                        \
+    type=keyvalues,                                                              \
+    params="[=[option,]*]",                                                      \
+    desc="Enable callsite trace mode. Options are: miss [trace callsite misses]  \
+    enterexit [trace callsite enter/exit], objects [print object properties]."   \
 }
 
 nashorn.option.verify.code = {              \
diff --git a/nashorn/src/jdk/nashorn/internal/scripts/JO.java b/nashorn/src/jdk/nashorn/internal/scripts/JO.java
index d617391..e5346cb 100644
--- a/nashorn/src/jdk/nashorn/internal/scripts/JO.java
+++ b/nashorn/src/jdk/nashorn/internal/scripts/JO.java
@@ -25,6 +25,7 @@
 
 package jdk.nashorn.internal.scripts;
 
+import jdk.nashorn.internal.codegen.SpillObjectCreator;
 import jdk.nashorn.internal.runtime.PropertyMap;
 import jdk.nashorn.internal.runtime.ScriptObject;
 
@@ -63,6 +64,18 @@
     }
 
     /**
+     * Constructor that takes a pre-initialized spill pool. Used for
+     * by {@link SpillObjectCreator} for intializing object literals
+     *
+     * @param map            property map
+     * @param primitiveSpill primitive spill pool
+     * @param objectSpill    reference spill pool
+     */
+    public JO(final PropertyMap map, final long[] primitiveSpill, final Object[] objectSpill) {
+        super(map, primitiveSpill, objectSpill);
+    }
+
+    /**
      * A method handle of this method is passed to the ScriptFunction constructor.
      *
      * @param map  the property map to use for allocatorMap
diff --git a/nashorn/src/jdk/nashorn/tools/Shell.java b/nashorn/src/jdk/nashorn/tools/Shell.java
index 33e0afd..e879a7f 100644
--- a/nashorn/src/jdk/nashorn/tools/Shell.java
+++ b/nashorn/src/jdk/nashorn/tools/Shell.java
@@ -41,6 +41,7 @@
 import java.util.ResourceBundle;
 import jdk.nashorn.api.scripting.NashornException;
 import jdk.nashorn.internal.codegen.Compiler;
+import jdk.nashorn.internal.codegen.Compiler.CompilationPhases;
 import jdk.nashorn.internal.ir.FunctionNode;
 import jdk.nashorn.internal.ir.debug.ASTWriter;
 import jdk.nashorn.internal.ir.debug.PrintVisitor;
@@ -178,7 +179,6 @@
      *
      * @return null if there are problems with option parsing.
      */
-    @SuppressWarnings("resource")
     private static Context makeContext(final InputStream in, final OutputStream out, final OutputStream err, final String[] args) {
         final PrintStream pout = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
         final PrintStream perr = err instanceof PrintStream ? (PrintStream) err : new PrintStream(err);
@@ -225,6 +225,7 @@
 
     /**
      * Compiles the given script files in the command line
+     * This is called only when using the --compile-only flag
      *
      * @param context the nashorn context
      * @param global the global scope
@@ -245,7 +246,7 @@
 
             // For each file on the command line.
             for (final String fileName : files) {
-                final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors).parse();
+                final FunctionNode functionNode = new Parser(env, sourceFor(fileName, new File(fileName)), errors, env._strict, FunctionNode.FIRST_FUNCTION_ID, 0, context.getLogger(Parser.class)).parse();
 
                 if (errors.getNumberOfErrors() != 0) {
                     return COMPILATION_ERROR;
@@ -260,7 +261,13 @@
                 }
 
                 //null - pass no code installer - this is compile only
-                new Compiler(env).compile(functionNode);
+                new Compiler(
+                       context,
+                       env,
+                       null,
+                       functionNode.getSource(),
+                       env._strict | functionNode.isStrict()).
+                       compile(functionNode, CompilationPhases.COMPILE_ALL_NO_INSTALL);
             }
         } finally {
             env.getOut().flush();
@@ -390,7 +397,6 @@
      * @param global  global scope object to use
      * @return return code
      */
-    @SuppressWarnings("resource")
     private static int readEvalPrint(final Context context, final Global global) {
         final String prompt = bundle.getString("shell.prompt");
         final BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
@@ -436,19 +442,16 @@
                     continue;
                 }
 
-                Object res;
                 try {
-                    res = context.eval(global, source, global, "<shell>", env._strict);
+                    final Object res = context.eval(global, source, global, "<shell>", env._strict);
+                    if (res != ScriptRuntime.UNDEFINED) {
+                        err.println(JSType.toString(res));
+                    }
                 } catch (final Exception e) {
                     err.println(e);
                     if (env._dump_on_error) {
                         e.printStackTrace(err);
                     }
-                    continue;
-                }
-
-                if (res != ScriptRuntime.UNDEFINED) {
-                    err.println(JSType.toString(res));
                 }
             }
         } finally {
diff --git a/nashorn/test/examples/apply_to_call_benchmark.js b/nashorn/test/examples/apply_to_call_benchmark.js
new file mode 100644
index 0000000..bed80ec
--- /dev/null
+++ b/nashorn/test/examples/apply_to_call_benchmark.js
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ *
+ * 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 Oracle nor the names of its
+ *     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 THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS 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.
+ */
+
+var Class = {
+  create: function() {
+    return function() { //vararg
+        this.initialize.apply(this, arguments);
+    }
+  }
+};
+
+Color = Class.create();
+Color.prototype = {
+    red: 0, green: 0, blue: 0,
+    initialize: function(r,g,b) {
+    this.red = r;
+    this.green = g;
+    this.blue = b;
+    }
+}
+
+function bench(x) {
+    var d = new Date;
+    var colors = new Array(16);
+    for (var i=0;i<1e8;i++) {
+    colors[i&0xf] = (new Color(1,2,3));
+    }
+    print(new Date - d);
+    return colors;
+}
+bench(17);
+
+print("Swapping out call");
+Function.prototype.call = function() {
+    throw "This should not happen, apply should be called instead";
+};
+
+bench(17);
+
+print("All done!");
diff --git a/nashorn/test/examples/array-micro.js b/nashorn/test/examples/array-micro.js
index 9bb898f..1a7b1d6 100644
--- a/nashorn/test/examples/array-micro.js
+++ b/nashorn/test/examples/array-micro.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/test/examples/dual-fields-micro.js b/nashorn/test/examples/dual-fields-micro.js
index aafc888..b1aa511 100644
--- a/nashorn/test/examples/dual-fields-micro.js
+++ b/nashorn/test/examples/dual-fields-micro.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -34,15 +34,15 @@
 }
 
 var sum = 1;
-function bench() {    
+function bench() {
     var d = new Date;
 
     for (var iter = 0; iter <4*50e6; iter++) {
-	sum *= 20 * b(21,22);
+    sum *= 20 * b(21,22);
     }
 
     print("time = " +(new Date-d));
-    print(sum);    
+    print(sum);
 }
 
 bench();
diff --git a/nashorn/test/examples/innerbench.js b/nashorn/test/examples/innerbench.js
index b7be741..3077075 100644
--- a/nashorn/test/examples/innerbench.js
+++ b/nashorn/test/examples/innerbench.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/test/examples/int-micro.js b/nashorn/test/examples/int-micro.js
index 82f4b09..0e2ec83 100644
--- a/nashorn/test/examples/int-micro.js
+++ b/nashorn/test/examples/int-micro.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/test/examples/string-micro.js b/nashorn/test/examples/string-micro.js
index 56ed0dd..8b2f5f3 100644
--- a/nashorn/test/examples/string-micro.js
+++ b/nashorn/test/examples/string-micro.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -46,12 +46,18 @@
     str[2];
 });
 
-bench("fromCharCode", function() {
+bench("fromCharCode 1", function() {
     String.fromCharCode(97);
     String.fromCharCode(98);
     String.fromCharCode(99);
 });
 
+bench("fromCharCode 2", function() {
+    String.fromCharCode(97, 98);
+    String.fromCharCode(97, 98, 99);
+    String.fromCharCode(97, 98, 99, 100);
+});
+
 bench("charAt 1", function() {
     str.charAt(0);
     str.charAt(1);
diff --git a/nashorn/test/examples/typechain.js b/nashorn/test/examples/typechain.js
index 8b13ad9..90401a2 100644
--- a/nashorn/test/examples/typechain.js
+++ b/nashorn/test/examples/typechain.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
diff --git a/nashorn/test/lib/benchmark.js b/nashorn/test/lib/benchmark.js
index e759cf1..67cd4fa 100644
--- a/nashorn/test/lib/benchmark.js
+++ b/nashorn/test/lib/benchmark.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,14 +33,14 @@
     startTime = new Date,
     runs = 0;
     do {
-	method.apply(args);
-	runs++;
-	totalTime = new Date - startTime;
+    method.apply(args);
+    runs++;
+    totalTime = new Date - startTime;
     } while (totalTime < timeInMillis);
-    
+
     // convert ms to seconds
     totalTime /= 1000;
-    
+
     // period → how long per operation
     period = totalTime / runs;
 
diff --git a/nashorn/test/opt/add.js b/nashorn/test/opt/add.js
index 6e43ae0..3e67571 100644
--- a/nashorn/test/opt/add.js
+++ b/nashorn/test/opt/add.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Example of an add function that gets specialized to doubles
- * if run with --optimize flag set 
+ * if run with --optimize flag set
  */
 
 function add(a,b) {
@@ -34,7 +34,7 @@
 function bench() {
     var sum = 1;
     for (var x = 0 ; x < 10e8/2 ; x ++) {
-	sum *= add(x,x + 1);
+    sum *= add(x,x + 1);
     }
     return sum;
 }
diff --git a/nashorn/test/opt/add_constant.js b/nashorn/test/opt/add_constant.js
index 0f2ae8b..334ea0f 100644
--- a/nashorn/test/opt/add_constant.js
+++ b/nashorn/test/opt/add_constant.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Example of an add function that gets specialized to doubles
- * if run with --optimize flag set 
+ * if run with --optimize flag set
  */
 
 function add(a,b) {
@@ -34,7 +34,7 @@
 function bench() {
     var sum = 1;
     for (var x = 0 ; x < 5e7 ; x++) {
-	sum *= add(x, 17);
+    sum *= add(x, 17);
     }
     return sum;
 }
diff --git a/nashorn/test/opt/add_reuse_callsite.js b/nashorn/test/opt/add_reuse_callsite.js
index 3539823..9d04e3f 100644
--- a/nashorn/test/opt/add_reuse_callsite.js
+++ b/nashorn/test/opt/add_reuse_callsite.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Example of an add function that gets specialized to doubles
- * if run with --optimize flag set 
+ * if run with --optimize flag set
  */
 
 function add(a,b) {
@@ -34,10 +34,10 @@
 function bench() {
     var sum = 1;
     for (var x = 0 ; x < 5e7 ; x++) {
-	sum *= add(x,x + 1);
+    sum *= add(x,x + 1);
     }
     for (var x = 0; x < 5e7 ; x++) {
-	sum *= add(x + 2, x + 3);
+    sum *= add(x + 2, x + 3);
     }
     return sum;
 }
diff --git a/nashorn/test/opt/add_revert2.js b/nashorn/test/opt/add_revert2.js
index 6ea36c5..b7ea1bb 100644
--- a/nashorn/test/opt/add_revert2.js
+++ b/nashorn/test/opt/add_revert2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Example of an add function that gets specialized to doubles
- * if run with --optimize flag set 
+ * if run with --optimize flag set
  */
 
 function add(a,b) {
@@ -34,8 +34,8 @@
 function bench() {
     var sum = 1;
     for (var x = 0 ; x < 5e7 ; x++) {
-	sum *= add(x, 17);
-	sum *= add(x, x); //can use same revert as 17?
+    sum *= add(x, 17);
+    sum *= add(x, x); //can use same revert as 17?
     }
     return sum;
 }
diff --git a/nashorn/test/opt/cascade_specialize.js b/nashorn/test/opt/cascade_specialize.js
index 7b5d66c..12e41f0 100644
--- a/nashorn/test/opt/cascade_specialize.js
+++ b/nashorn/test/opt/cascade_specialize.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,4 +37,4 @@
 }
 
 test();
- 
+
diff --git a/nashorn/test/script/assert.js b/nashorn/test/script/assert.js
index 3656f86..9971d29 100644
--- a/nashorn/test/script/assert.js
+++ b/nashorn/test/script/assert.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,8 +28,8 @@
  */
 
 // Assert is TestNG's Assert class
-Object.defineProperty(this, "Assert", { 
-    configuable: true,
+Object.defineProperty(this, "Assert", {
+    configurable: true,
     enumerable: false,
     writable: true,
     value: Packages.org.testng.Assert
@@ -37,10 +37,10 @@
 
 // fail function to call TestNG Assert.fail
 Object.defineProperty(this, "fail", {
-    configuable: true,
+    configurable: true,
     enumerable: false,
     writable: true,
-    // 'error' is optional. if present it has to be 
+    // 'error' is optional. if present it has to be
     // an ECMAScript Error object or java Throwable object
     value: function (message, error) {
         var throwable = null;
@@ -63,7 +63,7 @@
 });
 
 Object.defineProperty(this, "printError", {
-    configuable: true,
+    configurable: true,
     enumerable: false,
     writable: true,
     value: function (e) {
diff --git a/nashorn/test/script/basic/8024180/global_var_delete.js b/nashorn/test/script/basic/8024180/global_var_delete.js
index f099dd3..b1725fb 100644
--- a/nashorn/test/script/basic/8024180/global_var_delete.js
+++ b/nashorn/test/script/basic/8024180/global_var_delete.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/8024180/global_var_shadow.js b/nashorn/test/script/basic/8024180/global_var_shadow.js
index 5ba5f5e..f43f21f 100644
--- a/nashorn/test/script/basic/8024180/global_var_shadow.js
+++ b/nashorn/test/script/basic/8024180/global_var_shadow.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/8024180/scope_no_such_prop.js b/nashorn/test/script/basic/8024180/scope_no_such_prop.js
index 5973c46..8813eb0 100644
--- a/nashorn/test/script/basic/8024180/scope_no_such_prop.js
+++ b/nashorn/test/script/basic/8024180/scope_no_such_prop.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/8024180/with_expr_prop_add.js b/nashorn/test/script/basic/8024180/with_expr_prop_add.js
index 7c3b3a5..359b829 100644
--- a/nashorn/test/script/basic/8024180/with_expr_prop_add.js
+++ b/nashorn/test/script/basic/8024180/with_expr_prop_add.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js b/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js
index a6a17e7..ad582e9 100644
--- a/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js
+++ b/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -42,7 +42,7 @@
             if (i == 0) {
                 p.x = "p.x";
             }
-        } 
+        }
     }
 }
 
diff --git a/nashorn/test/script/basic/8024180/with_java_object.js b/nashorn/test/script/basic/8024180/with_java_object.js
index 32db2a5..e50a6a3 100644
--- a/nashorn/test/script/basic/8024180/with_java_object.js
+++ b/nashorn/test/script/basic/8024180/with_java_object.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8005958.js b/nashorn/test/script/basic/JDK-8005958.js
index e72ba09..485283b 100644
--- a/nashorn/test/script/basic/JDK-8005958.js
+++ b/nashorn/test/script/basic/JDK-8005958.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8005958 : invoking a function through INVOKESTATIC with more 
+ * JDK-8005958 : invoking a function through INVOKESTATIC with more
  * arguments than it declares resulted in malformed bytecode being
  * generated.
  *
diff --git a/nashorn/test/script/basic/JDK-8006304.js b/nashorn/test/script/basic/JDK-8006304.js
index f2d2c01..71fded1 100644
--- a/nashorn/test/script/basic/JDK-8006304.js
+++ b/nashorn/test/script/basic/JDK-8006304.js
@@ -1,26 +1,26 @@
 /*
  * 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.
  */
- 
+
 /**
  * JDK-8006304 : Remove pre-population of maps for constructor produced maps.
  *
diff --git a/nashorn/test/script/basic/JDK-8006337.js b/nashorn/test/script/basic/JDK-8006337.js
index 21c469a..189af27 100644
--- a/nashorn/test/script/basic/JDK-8006337.js
+++ b/nashorn/test/script/basic/JDK-8006337.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8006337 : Discarded arguments for INVOKESTATIC must still be 
+ * JDK-8006337 : Discarded arguments for INVOKESTATIC must still be
  * evaluated for side effects.
  *
  * @test
diff --git a/nashorn/test/script/basic/JDK-8006529-b.js b/nashorn/test/script/basic/JDK-8006529-b.js
index a7a6e3f..4a63c62 100644
--- a/nashorn/test/script/basic/JDK-8006529-b.js
+++ b/nashorn/test/script/basic/JDK-8006529-b.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -62,4 +62,4 @@
 for(var i in x) {
   print("Doing " + i)
   new x[i]()
-}
\ No newline at end of file
+}
diff --git a/nashorn/test/script/basic/JDK-8006570.js b/nashorn/test/script/basic/JDK-8006570.js
index 29dc7ab..da7e891 100644
--- a/nashorn/test/script/basic/JDK-8006570.js
+++ b/nashorn/test/script/basic/JDK-8006570.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -57,4 +57,4 @@
 strict.call(null);
 strict.call("foo");
 strict.call(1);
-strict.call(true);
\ No newline at end of file
+strict.call(true);
diff --git a/nashorn/test/script/basic/JDK-8006852a.js b/nashorn/test/script/basic/JDK-8006852a.js
index 7e706bd..0c3ee40 100644
--- a/nashorn/test/script/basic/JDK-8006852a.js
+++ b/nashorn/test/script/basic/JDK-8006852a.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,24 +27,24 @@
  * @test
  * @run
  */
- 
-function Field(val){                                                                                                                                                                                                                                          
-    this.value = val;                                                                                                                                                                                                                                         
-}                                                                                                                                                                                                                                                             
-var times = 0;                                                                                                                                                                                                                                                
-                                                                                                                                                                                                                                                              
-Field.prototype = {                                                                                                                                                                                                                                           
-    get value(){                                                                                                                                                                                                                                              
-        print("GETTER!");                                                                                                                                                                                                                                     
-        return this._value;                                                                                                                                                                                                                                   
-    },                                                                                                                                                                                                                                                        
-    set value(val){                                                                                                                                                                                                                                           
-        print("SETTER!");                                                                                                                                                                                                                                     
-        this._value = val + (++times);                                                                                                                                                                                                                        
-    }                                                                                                                                                                                                                                                         
-};                                                                                                                                                                                                                                                            
-                                                                                                                                                                                                                                                              
-var f = new Field("test");                                                                                                                                                                                                                                    
-print(f.value);                                                                                                                                                                                                                                               
-f.value = "test2";                                                                                                                                                                                                                                            
+
+function Field(val){
+    this.value = val;
+}
+var times = 0;
+
+Field.prototype = {
+    get value(){
+        print("GETTER!");
+        return this._value;
+    },
+    set value(val){
+        print("SETTER!");
+        this._value = val + (++times);
+    }
+};
+
+var f = new Field("test");
+print(f.value);
+f.value = "test2";
 print(f.value);
diff --git a/nashorn/test/script/basic/JDK-8006852b.js b/nashorn/test/script/basic/JDK-8006852b.js
index 2d0c4b6..d236bc7 100644
--- a/nashorn/test/script/basic/JDK-8006852b.js
+++ b/nashorn/test/script/basic/JDK-8006852b.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 function MyCons(arg) {
     if (arg == 2) {
        this.foo = 3;
diff --git a/nashorn/test/script/basic/JDK-8006857.js b/nashorn/test/script/basic/JDK-8006857.js
index c651464..4f9e2c6 100644
--- a/nashorn/test/script/basic/JDK-8006857.js
+++ b/nashorn/test/script/basic/JDK-8006857.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8006983.js b/nashorn/test/script/basic/JDK-8006983.js
index 2c126c4..af4233a 100644
--- a/nashorn/test/script/basic/JDK-8006983.js
+++ b/nashorn/test/script/basic/JDK-8006983.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8006984.js b/nashorn/test/script/basic/JDK-8006984.js
index 60702e3..19ccf09 100644
--- a/nashorn/test/script/basic/JDK-8006984.js
+++ b/nashorn/test/script/basic/JDK-8006984.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,22 +23,22 @@
 
 /**
  * findProperty on WithObject was not considering its object argument
- * 
+ *
  * @test
  * @run
  */
 
-var guiPkgs = { JFrame: function() { print("created"); } }; 
+var guiPkgs = { JFrame: function() { print("created"); } };
 
-with (guiPkgs) { 
-     var main = function() { 
+with (guiPkgs) {
+     var main = function() {
         var frame; // <---- this local variable caused scope to be not set properly prior to fix
 
-        function createFrame() { 
-            frame = new JFrame(); 
-        } 
+        function createFrame() {
+            frame = new JFrame();
+        }
 
-        createFrame(); 
-    } 
-} 
+        createFrame();
+    }
+}
 main();
diff --git a/nashorn/test/script/basic/JDK-8007060.js b/nashorn/test/script/basic/JDK-8007060.js
index 699cecb..9d9a673 100644
--- a/nashorn/test/script/basic/JDK-8007060.js
+++ b/nashorn/test/script/basic/JDK-8007060.js
@@ -91,4 +91,4 @@
 [1, 2, 3].filter(F, "hello");
 [1, 2, 3].filter(F, 1);
 [1, 2, 3].filter(F, {});
-[1, 2, 3].filter(F, "hello");
\ No newline at end of file
+[1, 2, 3].filter(F, "hello");
diff --git a/nashorn/test/script/basic/JDK-8007140.js b/nashorn/test/script/basic/JDK-8007140.js
index 28b4191..a9faa4f 100644
--- a/nashorn/test/script/basic/JDK-8007140.js
+++ b/nashorn/test/script/basic/JDK-8007140.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8007215.js b/nashorn/test/script/basic/JDK-8007215.js
index 0dbd718..65b4d38 100644
--- a/nashorn/test/script/basic/JDK-8007215.js
+++ b/nashorn/test/script/basic/JDK-8007215.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Varargs based on too many parameters broke. Regression test.
- * 
+ *
  * @test
  * @run
  */
@@ -31,11 +31,11 @@
 function f() {
     var sum = 0;
     for (var i = 0; i < arguments.length; i++) {
-	var a = arguments[i];
-	sum += a;
+    var a = arguments[i];
+    sum += a;
     }
     return sum;
-} 
+}
 
 var res;
 
diff --git a/nashorn/test/script/basic/JDK-8007460.js b/nashorn/test/script/basic/JDK-8007460.js
index 7dc4c31..37fd434 100644
--- a/nashorn/test/script/basic/JDK-8007460.js
+++ b/nashorn/test/script/basic/JDK-8007460.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,4 +37,4 @@
   print(y)
   print(arguments[0])
 }
-f(2)
\ No newline at end of file
+f(2)
diff --git a/nashorn/test/script/basic/JDK-8007522.js b/nashorn/test/script/basic/JDK-8007522.js
index 855d7d1..fca7696 100644
--- a/nashorn/test/script/basic/JDK-8007522.js
+++ b/nashorn/test/script/basic/JDK-8007522.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8007523.js b/nashorn/test/script/basic/JDK-8007523.js
index 2a97ce2..a157faf 100644
--- a/nashorn/test/script/basic/JDK-8007523.js
+++ b/nashorn/test/script/basic/JDK-8007523.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8007523: VerifyError on script that uses regular expression literals with ternary operator 
+ * JDK-8007523: VerifyError on script that uses regular expression literals with ternary operator
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8007619.js b/nashorn/test/script/basic/JDK-8007619.js
index 2c91f9c..ca5b33f 100644
--- a/nashorn/test/script/basic/JDK-8007619.js
+++ b/nashorn/test/script/basic/JDK-8007619.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,11 +37,11 @@
 while (match != null) {
     print("Match = " + match);
     print("RegExp.lastMatch = " + RegExp.lastMatch);
-   
+
     print("RegExp.$1 = " + RegExp.$1);
     print("RegExp.$2 = " + RegExp.$2);
     print("RegExp.$3 = " + RegExp.$3);
- 
+
     print("RegExp.lastParen = " + RegExp.lastParen)
     print("RegExp.input = " + RegExp.input);
 
diff --git a/nashorn/test/script/basic/JDK-8007990.js b/nashorn/test/script/basic/JDK-8007990.js
index 7f4f739..d5a41aa 100644
--- a/nashorn/test/script/basic/JDK-8007990.js
+++ b/nashorn/test/script/basic/JDK-8007990.js
@@ -22,15 +22,15 @@
  */
 
 /**
- * JDK-8007990: Access methods declared on public interfaces implemented by 
+ * JDK-8007990: Access methods declared on public interfaces implemented by
  * non-public classes
  *
  * @test
  * @run
  */
 
-var p = new Packages.java.io.File("test/script/basic/JDK-8007990.js"); 
-var path = p.toPath(); 
-var basicView = Packages.java.nio.file.Files.getFileAttributeView(path, Packages.java.nio.file.attribute.BasicFileAttributeView.class); 
+var p = new Packages.java.io.File("test/script/basic/JDK-8007990.js");
+var path = p.toPath();
+var basicView = Packages.java.nio.file.Files.getFileAttributeView(path, Packages.java.nio.file.attribute.BasicFileAttributeView.class);
 // We just want to confirm we can access the readAttributes() function
 print(basicView.readAttributes().directory);
diff --git a/nashorn/test/script/basic/JDK-8008197.js b/nashorn/test/script/basic/JDK-8008197.js
index e77a13a..c19186c 100644
--- a/nashorn/test/script/basic/JDK-8008197.js
+++ b/nashorn/test/script/basic/JDK-8008197.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,7 +33,7 @@
 var e = m.getEngineByName("nashorn");
 
 var obj = {
-    func: function(str) { 
+    func: function(str) {
         return /hello/.exec(str);
     }
 };
diff --git a/nashorn/test/script/basic/JDK-8008206.js b/nashorn/test/script/basic/JDK-8008206.js
index be84f51..757edab 100644
--- a/nashorn/test/script/basic/JDK-8008206.js
+++ b/nashorn/test/script/basic/JDK-8008206.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,9 +28,9 @@
  * @run
  */
 
-var x = 1; 
+var x = 1;
 
-switch (x) { 
-  case foo = false, 1: 
-     print("ok"); 
-} 
+switch (x) {
+  case foo = false, 1:
+     print("ok");
+}
diff --git a/nashorn/test/script/basic/JDK-8008238.js b/nashorn/test/script/basic/JDK-8008238.js
index f58ec20..8dbf1f8 100644
--- a/nashorn/test/script/basic/JDK-8008238.js
+++ b/nashorn/test/script/basic/JDK-8008238.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8008554.js b/nashorn/test/script/basic/JDK-8008554.js
index f8ec958..a40a4b4 100644
--- a/nashorn/test/script/basic/JDK-8008554.js
+++ b/nashorn/test/script/basic/JDK-8008554.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8008814-3.js b/nashorn/test/script/basic/JDK-8008814-3.js
index 87a9ebf..da79802 100644
--- a/nashorn/test/script/basic/JDK-8008814-3.js
+++ b/nashorn/test/script/basic/JDK-8008814-3.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8008814-4.js b/nashorn/test/script/basic/JDK-8008814-4.js
index baca022..766fac1 100644
--- a/nashorn/test/script/basic/JDK-8008814-4.js
+++ b/nashorn/test/script/basic/JDK-8008814-4.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8009553.js b/nashorn/test/script/basic/JDK-8009553.js
index 3617f16..64693fd 100644
--- a/nashorn/test/script/basic/JDK-8009553.js
+++ b/nashorn/test/script/basic/JDK-8009553.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8009868.js b/nashorn/test/script/basic/JDK-8009868.js
index ffbc8c2..f9aabca 100644
--- a/nashorn/test/script/basic/JDK-8009868.js
+++ b/nashorn/test/script/basic/JDK-8009868.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8010709.js b/nashorn/test/script/basic/JDK-8010709.js
index d2ec87a..863a12e 100644
--- a/nashorn/test/script/basic/JDK-8010709.js
+++ b/nashorn/test/script/basic/JDK-8010709.js
@@ -22,7 +22,7 @@
  */
 
 /**
- * JDK-8010709  org on the top level doesn't resolve 
+ * JDK-8010709  org on the top level doesn't resolve
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8010710.js b/nashorn/test/script/basic/JDK-8010710.js
index aa6e61a..04375c4 100644
--- a/nashorn/test/script/basic/JDK-8010710.js
+++ b/nashorn/test/script/basic/JDK-8010710.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -26,7 +26,7 @@
  * as array index in self modifying assigns
  *
  * @test
- * @run 
+ * @run
  */
 function zero() {
     return 0;
@@ -38,9 +38,9 @@
 print(b[zero() + 1][2 + a[0]] += 10);
 
 //repro for NASHORN-258 that never made it
-function AddRoundKey() {        
-    var r=0;  
-    state[r][1] &= 17;    
+function AddRoundKey() {
+    var r=0;
+    state[r][1] &= 17;
 }
 
 var srcFiles = [];
@@ -52,7 +52,7 @@
 //this broke the javafx build system. verify it works
 function bouncingBall() {
     for (j=0; j<100; j++) {
-	added += srcFiles[j];
+    added += srcFiles[j];
     }
 }
 bouncingBall();
@@ -61,7 +61,7 @@
 //this is how they should have done it for speed, that works always, verify this too
 function bouncingBall2() {
     for (var k=0; k<100; k++) {
-	added += srcFiles[k];
+    added += srcFiles[k];
     }
 }
 bouncingBall2();
diff --git a/nashorn/test/script/basic/JDK-8010720.js b/nashorn/test/script/basic/JDK-8010720.js
index 1dddf22..11d35b4 100644
--- a/nashorn/test/script/basic/JDK-8010720.js
+++ b/nashorn/test/script/basic/JDK-8010720.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8010731.js b/nashorn/test/script/basic/JDK-8010731.js
new file mode 100644
index 0000000..a7c7fb3
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8010731.js
@@ -0,0 +1,64 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8010731: Nashorn exposes internal symbols such as __callee__, __scope__ to scripts
+ *
+ * @test
+ * @run
+ */
+
+function checkCallee() {
+     var x = arguments[0]; // force __callee__ (renamed as :callee)
+
+     print(__callee__);
+}
+
+try {
+    checkCallee();
+    fail("Should have thrown ReferenceError for __callee__");
+} catch (e) {
+    if (! (e instanceof ReferenceError)) {
+        fail("ReferenceError expected, got " + e);
+    }
+}
+
+function checkScope() {
+    var x = 334;
+
+    function inner() {
+        var y = x * x;  // force __scope__ (renamed as :scope")
+        print(__scope__);
+    }
+
+    inner();
+}
+
+try {
+    checkScope();
+    fail("Should have thrown ReferenceError for __scope__");
+} catch (e) {
+    if (! (e instanceof ReferenceError)) {
+        fail("ReferenceError expected, got " + e);
+    }
+}
diff --git a/nashorn/test/script/basic/JDK-8010804.js b/nashorn/test/script/basic/JDK-8010804.js
index 04e216a..5d6d260 100644
--- a/nashorn/test/script/basic/JDK-8010804.js
+++ b/nashorn/test/script/basic/JDK-8010804.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -83,4 +83,4 @@
 
 var d = new Date();
 d.setYear(Infinity);
-print(d);
\ No newline at end of file
+print(d);
diff --git a/nashorn/test/script/basic/JDK-8010946-privileged.js b/nashorn/test/script/basic/JDK-8010946-privileged.js
index fc409f9..2e04f54 100644
--- a/nashorn/test/script/basic/JDK-8010946-privileged.js
+++ b/nashorn/test/script/basic/JDK-8010946-privileged.js
@@ -25,7 +25,7 @@
  * JDK-8010946: AccessController.doPrivileged() doesn't work as expected.
  * This is actually a broader issue of having Dynalink correctly handle
  * caller-sensitive methods.
- * 
+ *
  * NOTE: This is not a standalone test file, it is loaded by JDK-801946.js
  * @subtest
  */
diff --git a/nashorn/test/script/basic/JDK-8010946.js b/nashorn/test/script/basic/JDK-8010946.js
index 4f01242..290d60e 100644
--- a/nashorn/test/script/basic/JDK-8010946.js
+++ b/nashorn/test/script/basic/JDK-8010946.js
@@ -34,7 +34,7 @@
 load(__DIR__ + "JDK-8010946-privileged.js")
 
 try {
-    // This should fail, even though the code itself resides in the 
+    // This should fail, even though the code itself resides in the
     // privileged script, as we're invoking it without going through
     // doPrivileged()
     print("Attempting unprivileged execution...")
diff --git a/nashorn/test/script/basic/JDK-8011023.js b/nashorn/test/script/basic/JDK-8011023.js
index fbc2ca9..d010462 100644
--- a/nashorn/test/script/basic/JDK-8011023.js
+++ b/nashorn/test/script/basic/JDK-8011023.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Round should be ecma compliant
  *
  * @test
- * @run 
+ * @run
  */
 
 print(1/Math.round(-0.5));
diff --git a/nashorn/test/script/basic/JDK-8011209.js b/nashorn/test/script/basic/JDK-8011209.js
index 9098dfa..975347d 100644
--- a/nashorn/test/script/basic/JDK-8011209.js
+++ b/nashorn/test/script/basic/JDK-8011209.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011237.js b/nashorn/test/script/basic/JDK-8011237.js
index e9e521a..2bb2585 100644
--- a/nashorn/test/script/basic/JDK-8011237.js
+++ b/nashorn/test/script/basic/JDK-8011237.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011274.js b/nashorn/test/script/basic/JDK-8011274.js
index b483c3e..c2a9732 100644
--- a/nashorn/test/script/basic/JDK-8011274.js
+++ b/nashorn/test/script/basic/JDK-8011274.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011357.js b/nashorn/test/script/basic/JDK-8011357.js
index 40efec5..147be0c 100644
--- a/nashorn/test/script/basic/JDK-8011357.js
+++ b/nashorn/test/script/basic/JDK-8011357.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011362.js b/nashorn/test/script/basic/JDK-8011362.js
index bda4851..c52edd6 100644
--- a/nashorn/test/script/basic/JDK-8011362.js
+++ b/nashorn/test/script/basic/JDK-8011362.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011365.js b/nashorn/test/script/basic/JDK-8011365.js
index 3080257..cbec8b6 100644
--- a/nashorn/test/script/basic/JDK-8011365.js
+++ b/nashorn/test/script/basic/JDK-8011365.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 try {
     Array.prototype.join.call(null, { toString:function() { throw 2 } });
-    fail("should have thrown TypeError");    
+    fail("should have thrown TypeError");
 } catch (e) {
     if (! (e instanceof TypeError)) {
         fail("TypeError expected, got " + e);
@@ -46,7 +46,7 @@
     if (funcName == "constructor") {
         continue;
     }
-   
+
     var prop = Array.prototype[funcName];
     if (prop instanceof Function) {
         // try 'null' this
diff --git a/nashorn/test/script/basic/JDK-8011382.js b/nashorn/test/script/basic/JDK-8011382.js
index 13b3a77..0c06b5b 100644
--- a/nashorn/test/script/basic/JDK-8011382.js
+++ b/nashorn/test/script/basic/JDK-8011382.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8011382: Data prototype methods and constructor do not call user defined toISOString, valueOf methods per spec. 
+ * JDK-8011382: Data prototype methods and constructor do not call user defined toISOString, valueOf methods per spec.
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8011394.js b/nashorn/test/script/basic/JDK-8011394.js
index 070f5d3..97ca915 100644
--- a/nashorn/test/script/basic/JDK-8011394.js
+++ b/nashorn/test/script/basic/JDK-8011394.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011552.js b/nashorn/test/script/basic/JDK-8011552.js
index f0735a0..4fa6137 100644
--- a/nashorn/test/script/basic/JDK-8011552.js
+++ b/nashorn/test/script/basic/JDK-8011552.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011555.js b/nashorn/test/script/basic/JDK-8011555.js
index c65ad61..c4b58e6 100644
--- a/nashorn/test/script/basic/JDK-8011555.js
+++ b/nashorn/test/script/basic/JDK-8011555.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -35,7 +35,7 @@
     } catch(e) {
         // We expect to get a TypeError for trying to use __noSuchMethod__ as
         // a constructor. Before we fixed this bug, we were getting a runtime
-        // exception with MH type mismatch on a MH.foldArguments within the 
+        // exception with MH type mismatch on a MH.foldArguments within the
         // WithObject code instead.
         print(e)
     }
diff --git a/nashorn/test/script/basic/JDK-8011578.js b/nashorn/test/script/basic/JDK-8011578.js
index 9a2f743..ef8fa62 100644
--- a/nashorn/test/script/basic/JDK-8011578.js
+++ b/nashorn/test/script/basic/JDK-8011578.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011718.js b/nashorn/test/script/basic/JDK-8011718.js
index 7cb24f2..0c2fc8d 100644
--- a/nashorn/test/script/basic/JDK-8011718.js
+++ b/nashorn/test/script/basic/JDK-8011718.js
@@ -28,19 +28,19 @@
  * @run
  */
 
-var obj = { 
-    hello:"From obj", 
-}; 
-var obj2 = { 
-    hello:"From obj2", 
-}; 
+var obj = {
+    hello:"From obj",
+};
+var obj2 = {
+    hello:"From obj2",
+};
 
-function doit(cb){ 
-    cb(); 
-    var cb2 = cb.bind(obj2, "This one is not acccepted"); 
-    cb2(); 
-} 
+function doit(cb){
+    cb();
+    var cb2 = cb.bind(obj2, "This one is not acccepted");
+    cb2();
+}
 
-doit(function(){ 
-        print(this.hello); 
+doit(function(){
+        print(this.hello);
     }.bind(obj));
diff --git a/nashorn/test/script/basic/JDK-8011756.js b/nashorn/test/script/basic/JDK-8011756.js
index c0e8d83..3081048 100644
--- a/nashorn/test/script/basic/JDK-8011756.js
+++ b/nashorn/test/script/basic/JDK-8011756.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011893.js b/nashorn/test/script/basic/JDK-8011893.js
index 28382d2..7c93924e 100644
--- a/nashorn/test/script/basic/JDK-8011893.js
+++ b/nashorn/test/script/basic/JDK-8011893.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011960.js b/nashorn/test/script/basic/JDK-8011960.js
index f691d2c..508b0b6 100644
--- a/nashorn/test/script/basic/JDK-8011960.js
+++ b/nashorn/test/script/basic/JDK-8011960.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8011964.js b/nashorn/test/script/basic/JDK-8011964.js
index a46023e..ad010ac 100644
--- a/nashorn/test/script/basic/JDK-8011964.js
+++ b/nashorn/test/script/basic/JDK-8011964.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/JDK-8011974.js b/nashorn/test/script/basic/JDK-8011974.js
index f3f9b4a..c8f791c 100644
--- a/nashorn/test/script/basic/JDK-8011974.js
+++ b/nashorn/test/script/basic/JDK-8011974.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8012083.js b/nashorn/test/script/basic/JDK-8012083.js
index e782ff5..ae828f1 100644
--- a/nashorn/test/script/basic/JDK-8012083.js
+++ b/nashorn/test/script/basic/JDK-8012083.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8012093 - array literals can only be subject to constant evaluation under very special
+ * JDK-8012083 - array literals can only be subject to constant evaluation under very special
  * circumstances.
  *
  * @test
diff --git a/nashorn/test/script/basic/JDK-8012164.js b/nashorn/test/script/basic/JDK-8012164.js
index 62bb09c..4d0ed45 100644
--- a/nashorn/test/script/basic/JDK-8012164.js
+++ b/nashorn/test/script/basic/JDK-8012164.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -46,11 +46,11 @@
 
 func();
 
-// See JDK-8015855: test/script/basic/JDK-8012164.js fails on Windows 
+// See JDK-8015855: test/script/basic/JDK-8012164.js fails on Windows
 // Replace '\' to '/' in class and file names of StackFrameElement objects
 function printFrame(stack) {
    var fileName = stack.fileName.replace(/\\/g, '/');
    var className = stack.className.replace(/\\/g, '/');
    print(className + '.' + stack.methodName + '(' +
-         fileName + ':' + stack.lineNumber + ')'); 
+         fileName + ':' + stack.lineNumber + ')');
 }
diff --git a/nashorn/test/script/basic/JDK-8012191.js b/nashorn/test/script/basic/JDK-8012191.js
index 8d1d284..1bc0b34 100644
--- a/nashorn/test/script/basic/JDK-8012191.js
+++ b/nashorn/test/script/basic/JDK-8012191.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-// ClassCastException: Cannot cast java.lang.String to [Ljava.lang.Object; 
+// ClassCastException: Cannot cast java.lang.String to [Ljava.lang.Object;
 __noSuchProperty__ = function() {
     print("obj.__noSuchProperty__ invoked for " + arguments[0]);
 }
diff --git a/nashorn/test/script/basic/JDK-8012240.js b/nashorn/test/script/basic/JDK-8012240.js
index 2ac6eaf..4128eeb 100644
--- a/nashorn/test/script/basic/JDK-8012240.js
+++ b/nashorn/test/script/basic/JDK-8012240.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,15 +33,15 @@
 try {
     Array.prototype.map.call(
         {
-            length: -1, 
+            length: -1,
             get 0() {
                 in_getter_for_0 = true;
                 throw 0;
             }
-        }, 
+        },
     function(){}).length;
 } catch (e) {
     if (e !== 0 || !in_getter_for_0) {
        fail("should have thrown error from getter for '0'th element");
     }
-} 
+}
diff --git a/nashorn/test/script/basic/JDK-8012291.js b/nashorn/test/script/basic/JDK-8012291.js
index b902df4..93f1250 100644
--- a/nashorn/test/script/basic/JDK-8012291.js
+++ b/nashorn/test/script/basic/JDK-8012291.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8012305.js b/nashorn/test/script/basic/JDK-8012305.js
index d08502d..211a809 100644
--- a/nashorn/test/script/basic/JDK-8012305.js
+++ b/nashorn/test/script/basic/JDK-8012305.js
@@ -22,7 +22,7 @@
  */
 
 /**
- * JDK-8012305: Function.bind can't be called on prototype function inside constructor 
+ * JDK-8012305: Function.bind can't be called on prototype function inside constructor
  *
  * @test
  * @run
@@ -36,4 +36,4 @@
 
 MyObject.prototype._process = function() { print("Message "); }
 
-var s = new MyObject(); 
+var s = new MyObject();
diff --git a/nashorn/test/script/basic/JDK-8012457.js b/nashorn/test/script/basic/JDK-8012457.js
index 2f71a9a..e7d4665 100644
--- a/nashorn/test/script/basic/JDK-8012457.js
+++ b/nashorn/test/script/basic/JDK-8012457.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -35,7 +35,7 @@
 // getter should be called
 var getter_0_called = false;
 
-Function().apply(null, 
+Function().apply(null,
     Object.defineProperty([],"0",
         {  get: function(){ getter_0_called = true; return 0 }
     })
diff --git a/nashorn/test/script/basic/JDK-8012462.js b/nashorn/test/script/basic/JDK-8012462.js
index 4e015a9..1c7a16e 100644
--- a/nashorn/test/script/basic/JDK-8012462.js
+++ b/nashorn/test/script/basic/JDK-8012462.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8013131.js b/nashorn/test/script/basic/JDK-8013131.js
index dfff8ac..c7496b0 100644
--- a/nashorn/test/script/basic/JDK-8013131.js
+++ b/nashorn/test/script/basic/JDK-8013131.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8013167.js b/nashorn/test/script/basic/JDK-8013167.js
index ec3c71a..6988183 100644
--- a/nashorn/test/script/basic/JDK-8013167.js
+++ b/nashorn/test/script/basic/JDK-8013167.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,4 +29,4 @@
  */
 
 var x = new Packages.jdk.nashorn.test.models.VarArgConstructor(1, false, "a", "b", "c")
-print(x.indicator)
\ No newline at end of file
+print(x.indicator)
diff --git a/nashorn/test/script/basic/JDK-8013325.js b/nashorn/test/script/basic/JDK-8013325.js
index e1faa7b..70e9fcb 100644
--- a/nashorn/test/script/basic/JDK-8013325.js
+++ b/nashorn/test/script/basic/JDK-8013325.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,9 +33,9 @@
   // x doesn't see an arguments object as it has a nested function with that name
   // so it'll invoke the function.
   arguments("a", "b", "c");
-  
+
   function arguments(x, y, z) {
-      // The function 'arguments' OTOH can't see itself; if it uses the 
+      // The function 'arguments' OTOH can't see itself; if it uses the
       // identifier 'arguments', it'll see its own arguments object.
       print(arguments)
       print(x + " " + y + " " + z)
diff --git a/nashorn/test/script/basic/JDK-8013337.js b/nashorn/test/script/basic/JDK-8013337.js
index b95da8b..00ed490 100644
--- a/nashorn/test/script/basic/JDK-8013337.js
+++ b/nashorn/test/script/basic/JDK-8013337.js
@@ -22,7 +22,7 @@
  */
 
 /**
- * JDK-8013337: Issues with Date.prototype's get, set functions 
+ * JDK-8013337: Issues with Date.prototype's get, set functions
  *
  * @test
  * @option -timezone=Asia/Calcutta
@@ -63,7 +63,7 @@
 checkGetterCalled("setUTCMonth");
 
 try {
-    Date.prototype.setTime.call({}, { valueOf: function() { throw "err" } }) 
+    Date.prototype.setTime.call({}, { valueOf: function() { throw "err" } })
 } catch (e) {
     if (! (e instanceof TypeError)) {
         fail("TypeError expected, got " + e);
diff --git a/nashorn/test/script/basic/JDK-8013444.js b/nashorn/test/script/basic/JDK-8013444.js
index 166575c..0f3c19e 100644
--- a/nashorn/test/script/basic/JDK-8013444.js
+++ b/nashorn/test/script/basic/JDK-8013444.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,14 +32,14 @@
 var type = typeof JSON.parse('{}',function(){})
 print("type is " + type);
 
-var obj = JSON.parse('{"name": "nashorn"}', 
+var obj = JSON.parse('{"name": "nashorn"}',
     function(k, v) {
         if (k === "") return v;
         return v.toUpperCase();
     });
 print(JSON.stringify(obj))
 
-var array = 
+var array =
   JSON.parse("[1, 3, 5, 7, 9, 11]",
    function(k, v) {
       if (k === "") return v;
diff --git a/nashorn/test/script/basic/JDK-8013729.js b/nashorn/test/script/basic/JDK-8013729.js
index a500602..d4397f3 100644
--- a/nashorn/test/script/basic/JDK-8013729.js
+++ b/nashorn/test/script/basic/JDK-8013729.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8013873.js b/nashorn/test/script/basic/JDK-8013873.js
index dcae75c..212c087 100644
--- a/nashorn/test/script/basic/JDK-8013873.js
+++ b/nashorn/test/script/basic/JDK-8013873.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8013874.js b/nashorn/test/script/basic/JDK-8013874.js
index 4b02b92..32dbcf7 100644
--- a/nashorn/test/script/basic/JDK-8013874.js
+++ b/nashorn/test/script/basic/JDK-8013874.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8013878.js b/nashorn/test/script/basic/JDK-8013878.js
index 81e39f9..d00ebd3 100644
--- a/nashorn/test/script/basic/JDK-8013878.js
+++ b/nashorn/test/script/basic/JDK-8013878.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8013919.js b/nashorn/test/script/basic/JDK-8013919.js
index bd25dc1..b986dc5 100644
--- a/nashorn/test/script/basic/JDK-8013919.js
+++ b/nashorn/test/script/basic/JDK-8013919.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,7 +33,7 @@
     print("a");
 } finally {
     var b = function() {
-	print("b");
+    print("b");
     }
     b();
 }
diff --git a/nashorn/test/script/basic/JDK-8014426.js b/nashorn/test/script/basic/JDK-8014426.js
index 220aa7f..f32989e 100644
--- a/nashorn/test/script/basic/JDK-8014426.js
+++ b/nashorn/test/script/basic/JDK-8014426.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8014647.js b/nashorn/test/script/basic/JDK-8014647.js
index 8d06848..ec76e1f 100644
--- a/nashorn/test/script/basic/JDK-8014647.js
+++ b/nashorn/test/script/basic/JDK-8014647.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8014781.js b/nashorn/test/script/basic/JDK-8014781.js
index 3c6d7d8..72732a8 100644
--- a/nashorn/test/script/basic/JDK-8014781.js
+++ b/nashorn/test/script/basic/JDK-8014781.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8014785.js b/nashorn/test/script/basic/JDK-8014785.js
index 27b05bd..5bb0a25 100644
--- a/nashorn/test/script/basic/JDK-8014785.js
+++ b/nashorn/test/script/basic/JDK-8014785.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -40,7 +40,7 @@
 // update obj.x via foo.x
 foo.x = "hello";
 print("obj.x = " + obj.x); // prints "hello" now
-     
+
 obj.x = 42;   // foo.x also becomes 42
 print("obj.x = " + obj.x); // prints 42
 print("foo.x = " + foo.x); // prints 42
diff --git a/nashorn/test/script/basic/JDK-8014953.js b/nashorn/test/script/basic/JDK-8014953.js
index ba7cef0..06b74af 100644
--- a/nashorn/test/script/basic/JDK-8014953.js
+++ b/nashorn/test/script/basic/JDK-8014953.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 try {
     new java.util.ArrrayList(16)
 } catch(e) {
diff --git a/nashorn/test/script/basic/JDK-8015267.js b/nashorn/test/script/basic/JDK-8015267.js
index b7c1f9b..74fac2a 100644
--- a/nashorn/test/script/basic/JDK-8015267.js
+++ b/nashorn/test/script/basic/JDK-8015267.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 var a = ['a', 'b', 'c', 'd']
 
 var l = Java.to(a, java.util.List)
@@ -64,10 +64,10 @@
 l[7] = 'g'
 print(a)
 
-try { l.add(15, '') } catch(e) { print(e.class) } 
-try { l.remove(15) } catch(e) { print(e.class) } 
-try { l.add(-1, '') } catch(e) { print(e.class) } 
-try { l.remove(-1) } catch(e) { print(e.class) } 
+try { l.add(15, '') } catch(e) { print(e.class) }
+try { l.remove(15) } catch(e) { print(e.class) }
+try { l.add(-1, '') } catch(e) { print(e.class) }
+try { l.remove(-1) } catch(e) { print(e.class) }
 
 l.remove(7)
 l.remove(2)
diff --git a/nashorn/test/script/basic/JDK-8015345.js b/nashorn/test/script/basic/JDK-8015345.js
index 3f551d9..938d9c9 100644
--- a/nashorn/test/script/basic/JDK-8015345.js
+++ b/nashorn/test/script/basic/JDK-8015345.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015346.js b/nashorn/test/script/basic/JDK-8015346.js
index 2365cc8..271ebba 100644
--- a/nashorn/test/script/basic/JDK-8015346.js
+++ b/nashorn/test/script/basic/JDK-8015346.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015347.js b/nashorn/test/script/basic/JDK-8015347.js
index d5a8ba3..7b1898c 100644
--- a/nashorn/test/script/basic/JDK-8015347.js
+++ b/nashorn/test/script/basic/JDK-8015347.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015348.js b/nashorn/test/script/basic/JDK-8015348.js
index 77ff603..46e30f3 100644
--- a/nashorn/test/script/basic/JDK-8015348.js
+++ b/nashorn/test/script/basic/JDK-8015348.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015349.js b/nashorn/test/script/basic/JDK-8015349.js
index 7588a65..e91b13e 100644
--- a/nashorn/test/script/basic/JDK-8015349.js
+++ b/nashorn/test/script/basic/JDK-8015349.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
     print(code + " = " + eval(code));
 }
 
-printEval("'abc'.lastIndexOf('a', 4)"); 
+printEval("'abc'.lastIndexOf('a', 4)");
 printEval("'abc'.lastIndexOf('b', Infinity)");
 printEval("'abc'.lastIndexOf('a', -1)");
 printEval("'abc'.lastIndexOf('a', -Infinity)");
diff --git a/nashorn/test/script/basic/JDK-8015350.js b/nashorn/test/script/basic/JDK-8015350.js
index c820296..62c9796 100644
--- a/nashorn/test/script/basic/JDK-8015350.js
+++ b/nashorn/test/script/basic/JDK-8015350.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015352.js b/nashorn/test/script/basic/JDK-8015352.js
index b40e646..ecb54f5 100644
--- a/nashorn/test/script/basic/JDK-8015352.js
+++ b/nashorn/test/script/basic/JDK-8015352.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015353.js b/nashorn/test/script/basic/JDK-8015353.js
index a9baa46..2b101a0 100644
--- a/nashorn/test/script/basic/JDK-8015353.js
+++ b/nashorn/test/script/basic/JDK-8015353.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015354.js b/nashorn/test/script/basic/JDK-8015354.js
index 3cbe676..80fa9cf 100644
--- a/nashorn/test/script/basic/JDK-8015354.js
+++ b/nashorn/test/script/basic/JDK-8015354.js
@@ -22,7 +22,7 @@
  */
 
 /**
- * JDK-8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead 
+ * JDK-8015354: JSON.parse should not use [[Put]] but use [[DefineOwnProperty]] instead
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8015355.js b/nashorn/test/script/basic/JDK-8015355.js
index aa1a39d..f5176ec 100644
--- a/nashorn/test/script/basic/JDK-8015355.js
+++ b/nashorn/test/script/basic/JDK-8015355.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * JDK-8015355: Array.prototype functions don't honour non-writable length and / or index properties
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/JDK-8015356.js b/nashorn/test/script/basic/JDK-8015356.js
index edc77c0..60bb146 100644
--- a/nashorn/test/script/basic/JDK-8015356.js
+++ b/nashorn/test/script/basic/JDK-8015356.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * JDK-8015355: Array concatenation should ignore empty array elements.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/JDK-8015357.js b/nashorn/test/script/basic/JDK-8015357.js
index b6c9453..325c571 100644
--- a/nashorn/test/script/basic/JDK-8015357.js
+++ b/nashorn/test/script/basic/JDK-8015357.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,8 +28,8 @@
  * @run
  */
 
-var a = []; 
-a[0x7fffffff]=1; 
+var a = [];
+a[0x7fffffff]=1;
 
 if (a.sort()[0] != 1) {
     fail("a.sort()[0] != 1");
diff --git a/nashorn/test/script/basic/JDK-8015741.js b/nashorn/test/script/basic/JDK-8015741.js
index fdecee2..61b3939 100644
--- a/nashorn/test/script/basic/JDK-8015741.js
+++ b/nashorn/test/script/basic/JDK-8015741.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015830.js b/nashorn/test/script/basic/JDK-8015830.js
index 314a73a..90132f9 100644
--- a/nashorn/test/script/basic/JDK-8015830.js
+++ b/nashorn/test/script/basic/JDK-8015830.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015892.js b/nashorn/test/script/basic/JDK-8015892.js
index a6ab4c8..9c53159 100644
--- a/nashorn/test/script/basic/JDK-8015892.js
+++ b/nashorn/test/script/basic/JDK-8015892.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,10 +29,10 @@
  * @run
  */
 
-function doIt() { 
-    if (something) { 
-	x = x.obj; 
-    } else { 
-	var x = "x"; 
-    } 
-} 
+function doIt() {
+    if (something) {
+    x = x.obj;
+    } else {
+    var x = "x";
+    }
+}
diff --git a/nashorn/test/script/basic/JDK-8015945.js b/nashorn/test/script/basic/JDK-8015945.js
index 5b9962e..e97965b 100644
--- a/nashorn/test/script/basic/JDK-8015945.js
+++ b/nashorn/test/script/basic/JDK-8015945.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015959.js b/nashorn/test/script/basic/JDK-8015959.js
index c5322e3..4056737 100644
--- a/nashorn/test/script/basic/JDK-8015959.js
+++ b/nashorn/test/script/basic/JDK-8015959.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8015969.js b/nashorn/test/script/basic/JDK-8015969.js
index a981377..57c6e1f 100644
--- a/nashorn/test/script/basic/JDK-8015969.js
+++ b/nashorn/test/script/basic/JDK-8015969.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,43 +32,26 @@
 var m = new javax.script.ScriptEngineManager();
 var e = m.getEngineByName("nashorn");
 
+e.put("fail", fail);
 e.eval(<<EOF
 
 'use strict';
 
 try {
-    context = 444;
-    print("FAILED!! context write should have thrown error");
-} catch (e) {
-    if (! (e instanceof TypeError)) {
-        print("TypeError expected but got " + e);
-    }
-}
-
-try {
-    engine = "hello";
-    print("FAILED!! engine write should have thrown error");
-} catch (e) {
-    if (! (e instanceof TypeError)) {
-        print("TypeError expected but got " + e);
-    }
-}
-
-try {
     delete context;
-    print("FAILED!! context delete should have thrown error");
+    fail("FAILED!! context delete should have thrown error");
 } catch (e) {
     if (! (e instanceof SyntaxError)) {
-        print("SyntaxError expected but got " + e);
+        fail("SyntaxError expected but got " + e);
     }
 }
 
 try {
     delete engine;
-    print("FAILED!! engine delete should have thrown error");
+    fail("FAILED!! engine delete should have thrown error");
 } catch (e) {
     if (! (e instanceof SyntaxError)) {
-        print("SyntaxError expected but got " + e);
+        fail("SyntaxError expected but got " + e);
     }
 }
 
diff --git a/nashorn/test/script/basic/JDK-8016235.js b/nashorn/test/script/basic/JDK-8016235.js
index 3945f8f..9ac999c 100644
--- a/nashorn/test/script/basic/JDK-8016235.js
+++ b/nashorn/test/script/basic/JDK-8016235.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,27 +23,27 @@
 
 /**
  * JDK-8016235 : use before definition in catch block generated erroneous bytecode
- * as there is no guarantee anything in the try block has executed. 
+ * as there is no guarantee anything in the try block has executed.
  *
  * @test
- * @run 
+ * @run
  */
 
 function f() {
     try {
-	var parser = {};
+    var parser = {};
     } catch (e) {
-	parser = parser.context();
+    parser = parser.context();
     }
 }
 
-function g() { 
+function g() {
     try {
         return "apa";
     } catch (tmp) {
-	//for now, too conservative as var ex declaration exists on the function
-	//level, but at least the code does not break, and the analysis is driven
-	//from the catch block (the rare case), not the try block (the common case)
+    //for now, too conservative as var ex declaration exists on the function
+    //level, but at least the code does not break, and the analysis is driven
+    //from the catch block (the rare case), not the try block (the common case)
         var ex = new Error("DOM Exception 5");
         ex.code = ex.number = 5;
         return ex;
diff --git a/nashorn/test/script/basic/JDK-8016239.js b/nashorn/test/script/basic/JDK-8016239.js
index 84849ae..119851c 100644
--- a/nashorn/test/script/basic/JDK-8016239.js
+++ b/nashorn/test/script/basic/JDK-8016239.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8016518.js b/nashorn/test/script/basic/JDK-8016518.js
index a468483..e31d758 100644
--- a/nashorn/test/script/basic/JDK-8016518.js
+++ b/nashorn/test/script/basic/JDK-8016518.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8016542.js b/nashorn/test/script/basic/JDK-8016542.js
index 6aeae26..5b8987f 100644
--- a/nashorn/test/script/basic/JDK-8016542.js
+++ b/nashorn/test/script/basic/JDK-8016542.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8016618.js b/nashorn/test/script/basic/JDK-8016618.js
index 1b35db7..0db20a0 100644
--- a/nashorn/test/script/basic/JDK-8016618.js
+++ b/nashorn/test/script/basic/JDK-8016618.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -38,7 +38,7 @@
 function func(x, y) {
     print('func.x = ' + x);
     print('func.x = ' + y)
-}; 
+};
 
 var obj = {
     foo: 'hello',
@@ -54,18 +54,30 @@
 });
 
 // load on mirror with local object as argument
-global.load({ 
+global.load({
     name: "code",
     script: "print('x = ' + x)"
 });
 
 function f() {
     // mirror function called with local arguments
+    //    global.func.apply(obj, arguments);
     global.func.apply(obj, arguments);
 }
 
 f(23, "hello");
 
+f(24, "hello2");
+
+var oldCall = Function.prototype.call;
+Function.prototype.call = function() {
+    throw "this should never happen! go back to apply!";
+};
+
+f(25, "hello3");
+
+Function.prototype.call = oldCall;
+
 var fObject = global.eval("Object");
 
 // instanceof on mirrors
diff --git a/nashorn/test/script/basic/JDK-8016618.js.EXPECTED b/nashorn/test/script/basic/JDK-8016618.js.EXPECTED
index fe260ba..4fc9210 100644
--- a/nashorn/test/script/basic/JDK-8016618.js.EXPECTED
+++ b/nashorn/test/script/basic/JDK-8016618.js.EXPECTED
@@ -1,6 +1,10 @@
 x = 33
 func.x = 23
 func.x = hello
+func.x = 24
+func.x = hello2
+func.x = 25
+func.x = hello3
 global instanceof fObject? true
 x is wriable ? true
 x value = 33
diff --git a/nashorn/test/script/basic/JDK-8016667.js b/nashorn/test/script/basic/JDK-8016667.js
index 169a8f3..831de47 100644
--- a/nashorn/test/script/basic/JDK-8016667.js
+++ b/nashorn/test/script/basic/JDK-8016667.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,22 +31,22 @@
 function toto() {
     var friends = 1;
     (joe = friends) == null;
-} 
+}
 
 //JDK-8019476 duplicate case of this
-Function("with(\nnull == (this % {}))( /x/g );"); 
+Function("with(\nnull == (this % {}))( /x/g );");
 
 function f() {
     with(null == (this % {}))(/x/g);
 }
 
-Function("return (null != [,,] <= this);"); 
+Function("return (null != [,,] <= this);");
 
 function f2() {
     return (null != [,,] <= this);
 }
 
-Function("/*infloop*/L:for(var x; ([+(function (window)[,,])(function(q) { return q; }, -0)].some(new Function)); [11,12,13,14].some) {/*infloop*/do {;return this; } while(x); }"); 
+Function("/*infloop*/L:for(var x; ([+(function (window)[,,])(function(q) { return q; }, -0)].some(new Function)); [11,12,13,14].some) {/*infloop*/do {;return this; } while(x); }");
 
 function f3() {
     /*infloop*/L:for(var x; ([+(function (window)[,,])(function(q) { return q; }, -0)].some(new Function)); [11,12,13,14].some) {/*infloop*/do {;return this; } while(x); }
diff --git a/nashorn/test/script/basic/JDK-8016681.js b/nashorn/test/script/basic/JDK-8016681.js
index 9596b0d..2c93b7c 100644
--- a/nashorn/test/script/basic/JDK-8016681.js
+++ b/nashorn/test/script/basic/JDK-8016681.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8017046.js b/nashorn/test/script/basic/JDK-8017046.js
index 7097e9f..be3261c 100644
--- a/nashorn/test/script/basic/JDK-8017046.js
+++ b/nashorn/test/script/basic/JDK-8017046.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8017082.js b/nashorn/test/script/basic/JDK-8017082.js
index 5ac9632..3b7934f 100644
--- a/nashorn/test/script/basic/JDK-8017082.js
+++ b/nashorn/test/script/basic/JDK-8017082.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8017084.js b/nashorn/test/script/basic/JDK-8017084.js
index ceac68e..1c3bf8b 100644
--- a/nashorn/test/script/basic/JDK-8017084.js
+++ b/nashorn/test/script/basic/JDK-8017084.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8017768.js b/nashorn/test/script/basic/JDK-8017768.js
index c91f6d1..2f23267 100644
--- a/nashorn/test/script/basic/JDK-8017768.js
+++ b/nashorn/test/script/basic/JDK-8017768.js
@@ -23,7 +23,7 @@
 
 /**
  * JDK-8017768: Allow use of dot notation for inner class names.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/JDK-8017950.js b/nashorn/test/script/basic/JDK-8017950.js
index c84eacc..3684cfb 100644
--- a/nashorn/test/script/basic/JDK-8017950.js
+++ b/nashorn/test/script/basic/JDK-8017950.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -36,7 +36,7 @@
     }
 }
 
-function f() { 
+function f() {
     func()
 }
 
diff --git a/nashorn/test/script/basic/JDK-8019226.js b/nashorn/test/script/basic/JDK-8019226.js
index 3a1cf2f..6c0f374 100644
--- a/nashorn/test/script/basic/JDK-8019226.js
+++ b/nashorn/test/script/basic/JDK-8019226.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8019226: line number not generated for first statement if it is on the same function declaration line 
+ * JDK-8019226: line number not generated for first statement if it is on the same function declaration line
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8019473.js b/nashorn/test/script/basic/JDK-8019473.js
index 5001f3d..f13375f 100644
--- a/nashorn/test/script/basic/JDK-8019473.js
+++ b/nashorn/test/script/basic/JDK-8019473.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019478.js b/nashorn/test/script/basic/JDK-8019478.js
index f5e2a645..3736ea8 100644
--- a/nashorn/test/script/basic/JDK-8019478.js
+++ b/nashorn/test/script/basic/JDK-8019478.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019482.js b/nashorn/test/script/basic/JDK-8019482.js
index 09f91e4..f9061d8 100644
--- a/nashorn/test/script/basic/JDK-8019482.js
+++ b/nashorn/test/script/basic/JDK-8019482.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019488.js b/nashorn/test/script/basic/JDK-8019488.js
index 0cb58e9..1a4a536 100644
--- a/nashorn/test/script/basic/JDK-8019488.js
+++ b/nashorn/test/script/basic/JDK-8019488.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019508.js b/nashorn/test/script/basic/JDK-8019508.js
index 88ecbec..cfd8080 100644
--- a/nashorn/test/script/basic/JDK-8019508.js
+++ b/nashorn/test/script/basic/JDK-8019508.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019553.js b/nashorn/test/script/basic/JDK-8019553.js
index bec3a52..a9d84af 100644
--- a/nashorn/test/script/basic/JDK-8019553.js
+++ b/nashorn/test/script/basic/JDK-8019553.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019585.js b/nashorn/test/script/basic/JDK-8019585.js
index 58d18f3..235e694 100644
--- a/nashorn/test/script/basic/JDK-8019585.js
+++ b/nashorn/test/script/basic/JDK-8019585.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,5 +30,5 @@
  */
 
 function f() {
-    var a = b == 17 && (a = toto(b)) && toto2(a); 
+    var a = b == 17 && (a = toto(b)) && toto2(a);
 }
diff --git a/nashorn/test/script/basic/JDK-8019629.js b/nashorn/test/script/basic/JDK-8019629.js
index 2d284d0..643bd61 100644
--- a/nashorn/test/script/basic/JDK-8019629.js
+++ b/nashorn/test/script/basic/JDK-8019629.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8019629: void operator should always evaluate to undefined 
+ * JDK-8019629: void operator should always evaluate to undefined
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8019783.js b/nashorn/test/script/basic/JDK-8019783.js
index 27afcaf..b9fcbd8 100644
--- a/nashorn/test/script/basic/JDK-8019783.js
+++ b/nashorn/test/script/basic/JDK-8019783.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019791.js b/nashorn/test/script/basic/JDK-8019791.js
index ad32ce3..feda555 100644
--- a/nashorn/test/script/basic/JDK-8019791.js
+++ b/nashorn/test/script/basic/JDK-8019791.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019805.js b/nashorn/test/script/basic/JDK-8019805.js
index 7e3e25b..a8423b3 100644
--- a/nashorn/test/script/basic/JDK-8019805.js
+++ b/nashorn/test/script/basic/JDK-8019805.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019808.js b/nashorn/test/script/basic/JDK-8019808.js
index 08d090c..2584ab4 100644
--- a/nashorn/test/script/basic/JDK-8019808.js
+++ b/nashorn/test/script/basic/JDK-8019808.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-Function("switch([]) { case 7: }"); 
+Function("switch([]) { case 7: }");
 
 function f() {
     switch([]) {
diff --git a/nashorn/test/script/basic/JDK-8019809.js b/nashorn/test/script/basic/JDK-8019809.js
index cc31bd8..ae1a9e0 100644
--- a/nashorn/test/script/basic/JDK-8019809.js
+++ b/nashorn/test/script/basic/JDK-8019809.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-//Function("L: {break L;return; }"); 
+//Function("L: {break L;return; }");
 
 function f() {
     L: { break L; return; }
diff --git a/nashorn/test/script/basic/JDK-8019810.js b/nashorn/test/script/basic/JDK-8019810.js
index a22fb06..5ee1fab 100644
--- a/nashorn/test/script/basic/JDK-8019810.js
+++ b/nashorn/test/script/basic/JDK-8019810.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019811.js b/nashorn/test/script/basic/JDK-8019811.js
index e64fafb..b72f9bc 100644
--- a/nashorn/test/script/basic/JDK-8019811.js
+++ b/nashorn/test/script/basic/JDK-8019811.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,18 +30,18 @@
 
 function f(x) {
     var window = 17;
-    return function (x) { 
-	return true 
+    return function (x) {
+    return true
     } (x) >> window;
 }
 
-Function("L:if((function x ()3)() + arguments++) {return; } else if (new gc()) while(((x2.prop = functional)) && 0){ }"); 
+Function("L:if((function x ()3)() + arguments++) {return; } else if (new gc()) while(((x2.prop = functional)) && 0){ }");
 
-Function("var x = x -= '' "); 
+Function("var x = x -= '' ");
 
-Function("switch((Math.pow ? x = 1.2e3 : 3)) { default: return; }") 
+Function("switch((Math.pow ? x = 1.2e3 : 3)) { default: return; }")
 
 Function("x = 0.1, x\ntrue\n~this");
 
 Function("with((function (x)x2)() ^ this){return; }");
- 
\ No newline at end of file
+
diff --git a/nashorn/test/script/basic/JDK-8019814.js b/nashorn/test/script/basic/JDK-8019814.js
index 24abf53..d3a658a 100644
--- a/nashorn/test/script/basic/JDK-8019814.js
+++ b/nashorn/test/script/basic/JDK-8019814.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -34,7 +34,7 @@
 // java.lang.AssertionError: expecting integer type or object for jump, but found double
 Function("with(\nnull == (this % {}))( /x/g );");
 
-// java.lang.AssertionError: expecting equivalent types on stack but got double and int 
+// java.lang.AssertionError: expecting equivalent types on stack but got double and int
 try {
     eval('Function("/*infloop*/while(((function ()4.)([z1,,], [,,]) - true++))switch(1e+81.x) { default: break; \u0009 }")');
 } catch (e) {
@@ -48,11 +48,11 @@
 Function("return (null != [,,] <= this);");
 
 // java.lang.AssertionError: Only return value on stack allowed at return point
-// - depth=2 stack = jdk.nashorn.internal.codegen.Label$Stack@4bd0d62f 
+// - depth=2 stack = jdk.nashorn.internal.codegen.Label$Stack@4bd0d62f
 Function("x = 0.1, x\ntrue\n~this");
 
 // java.lang.AssertionError: node NaN ~ window class jdk.nashorn.internal.ir.BinaryNode
-// has no symbol! [object] function _L1() 
+// has no symbol! [object] function _L1()
 Function("throw NaN\n~window;");
 
 // java.lang.AssertionError: array element type doesn't match array type
@@ -65,9 +65,9 @@
 }
 
 // java.lang.AssertionError: stacks jdk.nashorn.internal.codegen.Label$Stack@4918f90f
-// is not equivalent with jdk.nashorn.internal.codegen.Label$Stack@5f9b21a1 at join point 
+// is not equivalent with jdk.nashorn.internal.codegen.Label$Stack@5f9b21a1 at join point
 Function("if((null ^ [1]) !== (this.yoyo(false))) {var NaN, x;x\n~[,,z1] }");
 
 // java.lang.AssertionError
-//    at jdk.nashorn.internal.codegen.Attr.enterFunctionBody(Attr.java:276) 
-Function("return (void ({ set each (x2)y }));"); 
+//    at jdk.nashorn.internal.codegen.Attr.enterFunctionBody(Attr.java:276)
+Function("return (void ({ set each (x2)y }));");
diff --git a/nashorn/test/script/basic/JDK-8019817.js b/nashorn/test/script/basic/JDK-8019817.js
index 6611e9b..37af970 100644
--- a/nashorn/test/script/basic/JDK-8019817.js
+++ b/nashorn/test/script/basic/JDK-8019817.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 var y = 17.17;
 
-Function("return y % function(q) { return q; }();"); 
+Function("return y % function(q) { return q; }();");
 
 function f() {
     return y % function(q) { return q; }();
diff --git a/nashorn/test/script/basic/JDK-8019819.js b/nashorn/test/script/basic/JDK-8019819.js
index 1760ac3..f899850 100644
--- a/nashorn/test/script/basic/JDK-8019819.js
+++ b/nashorn/test/script/basic/JDK-8019819.js
@@ -23,14 +23,14 @@
 
 /**
  * JDK-8019819: scope symbol didn't get a slot in certain cases
- * 
+ *
  * @test
  * @run
  */
 function f() {
     try {
-    } catch(e if [].g(e)) { 
-        with({}) { 
+    } catch(e if [].g(e)) {
+        with({}) {
             throw e;
         }
     }
@@ -38,8 +38,8 @@
 
 function g() {
     try {
-    } catch(e) { 
-        with({}) { 
+    } catch(e) {
+        with({}) {
             throw e;
         }
     }
diff --git a/nashorn/test/script/basic/JDK-8019821.js b/nashorn/test/script/basic/JDK-8019821.js
index c296ac3..0e79748 100644
--- a/nashorn/test/script/basic/JDK-8019821.js
+++ b/nashorn/test/script/basic/JDK-8019821.js
@@ -1,37 +1,37 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8019821: boolean switch value accidentally triggered "allInts" case 
+ * JDK-8019821: boolean switch value accidentally triggered "allInts" case
  * as boolean is considered narrower than int. This caused a ClassCastException
  *
  * @test
  * @run
  */
 
-function f() { 
-    switch(gc()) { 
-    case true: 
-    case 1:  
+function f() {
+    switch(gc()) {
+    case true:
+    case 1:
     }
 }
diff --git a/nashorn/test/script/basic/JDK-8019822.js b/nashorn/test/script/basic/JDK-8019822.js
index 2a49150..6c6fc34 100644
--- a/nashorn/test/script/basic/JDK-8019822.js
+++ b/nashorn/test/script/basic/JDK-8019822.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019947.js b/nashorn/test/script/basic/JDK-8019947.js
index 4b64a81..52a7339 100644
--- a/nashorn/test/script/basic/JDK-8019947.js
+++ b/nashorn/test/script/basic/JDK-8019947.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019963.js b/nashorn/test/script/basic/JDK-8019963.js
index 5767a41..1ca749a 100644
--- a/nashorn/test/script/basic/JDK-8019963.js
+++ b/nashorn/test/script/basic/JDK-8019963.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8019983.js b/nashorn/test/script/basic/JDK-8019983.js
index 7851ab0..39cf813 100644
--- a/nashorn/test/script/basic/JDK-8019983.js
+++ b/nashorn/test/script/basic/JDK-8019983.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,18 +24,18 @@
 /**
  * JDK-8019983.js return without expression combined with return with expression should produce object
  * return type (undefined)
- * 
+ *
  * @test
  * @run
  */
 
 
-function g() { 
-    switch(1) { 
-    case 0: 
-    case '': 
+function g() {
+    switch(1) {
+    case 0:
+    case '':
     default:
-	return;
+    return;
     }
     return 10;
 }
diff --git a/nashorn/test/script/basic/JDK-8019985.js b/nashorn/test/script/basic/JDK-8019985.js
index adc7fbf..a4783f4 100644
--- a/nashorn/test/script/basic/JDK-8019985.js
+++ b/nashorn/test/script/basic/JDK-8019985.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020124.js b/nashorn/test/script/basic/JDK-8020124.js
index f7735fc..6326643 100644
--- a/nashorn/test/script/basic/JDK-8020124.js
+++ b/nashorn/test/script/basic/JDK-8020124.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020132.js b/nashorn/test/script/basic/JDK-8020132.js
index 49fc1b1..9cb6a76 100644
--- a/nashorn/test/script/basic/JDK-8020132.js
+++ b/nashorn/test/script/basic/JDK-8020132.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020223.js b/nashorn/test/script/basic/JDK-8020223.js
index 9bbbad2..9d5f68a 100644
--- a/nashorn/test/script/basic/JDK-8020223.js
+++ b/nashorn/test/script/basic/JDK-8020223.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020324.js b/nashorn/test/script/basic/JDK-8020324.js
index 8f48f76..0ef7325 100644
--- a/nashorn/test/script/basic/JDK-8020324.js
+++ b/nashorn/test/script/basic/JDK-8020324.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020325.js b/nashorn/test/script/basic/JDK-8020325.js
index 5c8e64f..c991c34 100644
--- a/nashorn/test/script/basic/JDK-8020325.js
+++ b/nashorn/test/script/basic/JDK-8020325.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020354.js b/nashorn/test/script/basic/JDK-8020354.js
index fbfa826..fd9b29b 100644
--- a/nashorn/test/script/basic/JDK-8020354.js
+++ b/nashorn/test/script/basic/JDK-8020354.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020355.js b/nashorn/test/script/basic/JDK-8020355.js
index 262c458..e55328c 100644
--- a/nashorn/test/script/basic/JDK-8020355.js
+++ b/nashorn/test/script/basic/JDK-8020355.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020356.js b/nashorn/test/script/basic/JDK-8020356.js
index 062a541..cb564ca 100644
--- a/nashorn/test/script/basic/JDK-8020356.js
+++ b/nashorn/test/script/basic/JDK-8020356.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020357.js b/nashorn/test/script/basic/JDK-8020357.js
index 6940637..c3bce25 100644
--- a/nashorn/test/script/basic/JDK-8020357.js
+++ b/nashorn/test/script/basic/JDK-8020357.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -35,7 +35,7 @@
 
 // A value over the limit should throw a RangeError.
 try {
-    Int32Array(limit)
+    new Int32Array(limit)
 } catch(e) {
     print(e)
 }
diff --git a/nashorn/test/script/basic/JDK-8020358.js b/nashorn/test/script/basic/JDK-8020358.js
index 401531d..6151a95 100644
--- a/nashorn/test/script/basic/JDK-8020358.js
+++ b/nashorn/test/script/basic/JDK-8020358.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020380.js b/nashorn/test/script/basic/JDK-8020380.js
index 90357fa..3c71d69 100644
--- a/nashorn/test/script/basic/JDK-8020380.js
+++ b/nashorn/test/script/basic/JDK-8020380.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020437.js b/nashorn/test/script/basic/JDK-8020437.js
index d758355..1a53aaf 100644
--- a/nashorn/test/script/basic/JDK-8020437.js
+++ b/nashorn/test/script/basic/JDK-8020437.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020463.js b/nashorn/test/script/basic/JDK-8020463.js
index 1b3830b..6554a62 100644
--- a/nashorn/test/script/basic/JDK-8020463.js
+++ b/nashorn/test/script/basic/JDK-8020463.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8020508.js b/nashorn/test/script/basic/JDK-8020508.js
index 304870a..3499e17 100644
--- a/nashorn/test/script/basic/JDK-8020508.js
+++ b/nashorn/test/script/basic/JDK-8020508.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8020508: Enforce reflection check on 
+ * JDK-8020508: Enforce reflection check on
  * Object.bindProperties(target, source) for beans
  *
  * @test
diff --git a/nashorn/test/script/basic/JDK-8021122.js b/nashorn/test/script/basic/JDK-8021122.js
index 769164f..bf716fb 100644
--- a/nashorn/test/script/basic/JDK-8021122.js
+++ b/nashorn/test/script/basic/JDK-8021122.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8022598.js b/nashorn/test/script/basic/JDK-8022598.js
index 95f2ab4..b33bed9 100644
--- a/nashorn/test/script/basic/JDK-8022598.js
+++ b/nashorn/test/script/basic/JDK-8022598.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8022731.js b/nashorn/test/script/basic/JDK-8022731.js
index 635bd2d..e44ff12 100644
--- a/nashorn/test/script/basic/JDK-8022731.js
+++ b/nashorn/test/script/basic/JDK-8022731.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8022903.js b/nashorn/test/script/basic/JDK-8022903.js
index 1733c51..8ab6cd4 100644
--- a/nashorn/test/script/basic/JDK-8022903.js
+++ b/nashorn/test/script/basic/JDK-8022903.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -43,7 +43,7 @@
 
 var capitals = new java.util.LinkedHashMap()
 capitals.Sweden = "Stockholm"
-capitals.Hungary = "Budapet"
+capitals.Hungary = "Budapest"
 capitals.Croatia = "Zagreb"
 
 for(var key in capitals) {
diff --git a/nashorn/test/script/basic/JDK-8022903.js.EXPECTED b/nashorn/test/script/basic/JDK-8022903.js.EXPECTED
index 8d64bae..bf13978 100644
--- a/nashorn/test/script/basic/JDK-8022903.js.EXPECTED
+++ b/nashorn/test/script/basic/JDK-8022903.js.EXPECTED
@@ -5,8 +5,8 @@
 purple
 pink
 capital of Sweden is Stockholm
-capital of Hungary is Budapet
+capital of Hungary is Budapest
 capital of Croatia is Zagreb
 Stockholm
-Budapet
+Budapest
 Zagreb
diff --git a/nashorn/test/script/basic/JDK-8023026.js b/nashorn/test/script/basic/JDK-8023026.js
index 0a6f027..2070de5 100644
--- a/nashorn/test/script/basic/JDK-8023026.js
+++ b/nashorn/test/script/basic/JDK-8023026.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8023373.js b/nashorn/test/script/basic/JDK-8023373.js
index 1a01982..b8bf418 100644
--- a/nashorn/test/script/basic/JDK-8023373.js
+++ b/nashorn/test/script/basic/JDK-8023373.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -50,7 +50,7 @@
     write: function(s, off, len) {
         s = capitalize(s)
         // Must handle overloads by arity
-        if(off === undefined) {	
+        if(off === undefined) {
             cw.super$write(s, 0, s.length())
         } else if (typeof s === "string") {
             cw.super$write(s, off, len)
diff --git a/nashorn/test/script/basic/JDK-8023531.js b/nashorn/test/script/basic/JDK-8023531.js
index 819e46b..9520f74 100644
--- a/nashorn/test/script/basic/JDK-8023531.js
+++ b/nashorn/test/script/basic/JDK-8023531.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8023551.js b/nashorn/test/script/basic/JDK-8023551.js
index 8545fbb..f02107d 100644
--- a/nashorn/test/script/basic/JDK-8023551.js
+++ b/nashorn/test/script/basic/JDK-8023551.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8023630.js b/nashorn/test/script/basic/JDK-8023630.js
index f0f4c58..68cbcc2 100644
--- a/nashorn/test/script/basic/JDK-8023630.js
+++ b/nashorn/test/script/basic/JDK-8023630.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -50,7 +50,7 @@
     write: function(s, off, len) {
         s = capitalize(s)
         // Must handle overloads by arity
-        if(off === undefined) {	
+        if(off === undefined) {
             cw_super.write(s, 0, s.length())
         } else if (typeof s === "string") {
             cw_super.write(s, off, len)
diff --git a/nashorn/test/script/basic/JDK-8023650.js b/nashorn/test/script/basic/JDK-8023650.js
index 8b01f49..d0e6178 100644
--- a/nashorn/test/script/basic/JDK-8023650.js
+++ b/nashorn/test/script/basic/JDK-8023650.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8023780.js b/nashorn/test/script/basic/JDK-8023780.js
index 675f22c..0c2f5bb 100644
--- a/nashorn/test/script/basic/JDK-8023780.js
+++ b/nashorn/test/script/basic/JDK-8023780.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8023784.js b/nashorn/test/script/basic/JDK-8023784.js
index c8a5099..c5b3a46 100644
--- a/nashorn/test/script/basic/JDK-8023784.js
+++ b/nashorn/test/script/basic/JDK-8023784.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8024120.js b/nashorn/test/script/basic/JDK-8024120.js
index d2913d5..1b72cb9 100644
--- a/nashorn/test/script/basic/JDK-8024120.js
+++ b/nashorn/test/script/basic/JDK-8024120.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8024174.js b/nashorn/test/script/basic/JDK-8024174.js
index bd9206a..c718bcd 100644
--- a/nashorn/test/script/basic/JDK-8024174.js
+++ b/nashorn/test/script/basic/JDK-8024174.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8024255.js b/nashorn/test/script/basic/JDK-8024255.js
index 54022a5..07933fc 100644
--- a/nashorn/test/script/basic/JDK-8024255.js
+++ b/nashorn/test/script/basic/JDK-8024255.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -39,9 +39,9 @@
     }
 }
 
-var obj = { 
+var obj = {
     default: 344,
-    in: 'hello', 
+    in: 'hello',
     if: false,
     class: 4.223
 }
diff --git a/nashorn/test/script/basic/JDK-8024512.js b/nashorn/test/script/basic/JDK-8024512.js
index c03ba21..f70477b 100644
--- a/nashorn/test/script/basic/JDK-8024512.js
+++ b/nashorn/test/script/basic/JDK-8024512.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8024619.js b/nashorn/test/script/basic/JDK-8024619.js
index 064e0d7..57a0895 100644
--- a/nashorn/test/script/basic/JDK-8024619.js
+++ b/nashorn/test/script/basic/JDK-8024619.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8024846.js b/nashorn/test/script/basic/JDK-8024846.js
index ccdf8fc..b87c8d9 100644
--- a/nashorn/test/script/basic/JDK-8024846.js
+++ b/nashorn/test/script/basic/JDK-8024846.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8024847.js b/nashorn/test/script/basic/JDK-8024847.js
index 2ead01f..96fdaa7 100644
--- a/nashorn/test/script/basic/JDK-8024847.js
+++ b/nashorn/test/script/basic/JDK-8024847.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -79,7 +79,7 @@
 var __array__ =  [ "nashorn", "js" ];
 
 var obj = new JSObject() {
-    
+
     hasMember: function(name) {
         return name in __array__;
     },
diff --git a/nashorn/test/script/basic/JDK-8024972.js b/nashorn/test/script/basic/JDK-8024972.js
index 2e94081..9e1c1b7 100644
--- a/nashorn/test/script/basic/JDK-8024972.js
+++ b/nashorn/test/script/basic/JDK-8024972.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025048-2.js b/nashorn/test/script/basic/JDK-8025048-2.js
index c11816b..2ee7709 100644
--- a/nashorn/test/script/basic/JDK-8025048-2.js
+++ b/nashorn/test/script/basic/JDK-8025048-2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 
 function func(x) {
-    switch(x) { 
+    switch(x) {
         case 8: break; case false:
     }
 }
diff --git a/nashorn/test/script/basic/JDK-8025048.js b/nashorn/test/script/basic/JDK-8025048.js
index 75838a9..397ee65 100644
--- a/nashorn/test/script/basic/JDK-8025048.js
+++ b/nashorn/test/script/basic/JDK-8025048.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 
 function func(x) {
-    switch(x) { 
+    switch(x) {
         case 8: break; case true:
     }
 }
diff --git a/nashorn/test/script/basic/JDK-8025080.js b/nashorn/test/script/basic/JDK-8025080.js
index 1ea46ef..72a695a 100644
--- a/nashorn/test/script/basic/JDK-8025080.js
+++ b/nashorn/test/script/basic/JDK-8025080.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025090.js b/nashorn/test/script/basic/JDK-8025090.js
index 8e42099..5a4136f 100644
--- a/nashorn/test/script/basic/JDK-8025090.js
+++ b/nashorn/test/script/basic/JDK-8025090.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025111.js b/nashorn/test/script/basic/JDK-8025111.js
index 953f27c..9e13355 100644
--- a/nashorn/test/script/basic/JDK-8025111.js
+++ b/nashorn/test/script/basic/JDK-8025111.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025147.js b/nashorn/test/script/basic/JDK-8025147.js
index 905a1c9..7c239b3 100644
--- a/nashorn/test/script/basic/JDK-8025147.js
+++ b/nashorn/test/script/basic/JDK-8025147.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025149.js b/nashorn/test/script/basic/JDK-8025149.js
index b1d33a1..4dd880d 100644
--- a/nashorn/test/script/basic/JDK-8025149.js
+++ b/nashorn/test/script/basic/JDK-8025149.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025163.js b/nashorn/test/script/basic/JDK-8025163.js
index 1eaa98e..9017d62 100644
--- a/nashorn/test/script/basic/JDK-8025163.js
+++ b/nashorn/test/script/basic/JDK-8025163.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025197.js b/nashorn/test/script/basic/JDK-8025197.js
index 5099b67..44b5425 100644
--- a/nashorn/test/script/basic/JDK-8025197.js
+++ b/nashorn/test/script/basic/JDK-8025197.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025213.js b/nashorn/test/script/basic/JDK-8025213.js
index 062a389..5d21984 100644
--- a/nashorn/test/script/basic/JDK-8025213.js
+++ b/nashorn/test/script/basic/JDK-8025213.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025312.js b/nashorn/test/script/basic/JDK-8025312.js
index 6f2b42f..5256aef 100644
--- a/nashorn/test/script/basic/JDK-8025312.js
+++ b/nashorn/test/script/basic/JDK-8025312.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025325.js b/nashorn/test/script/basic/JDK-8025325.js
index 63dfef9..e61929f 100644
--- a/nashorn/test/script/basic/JDK-8025325.js
+++ b/nashorn/test/script/basic/JDK-8025325.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025434.js b/nashorn/test/script/basic/JDK-8025434.js
index 1d42959..5c33f37 100644
--- a/nashorn/test/script/basic/JDK-8025434.js
+++ b/nashorn/test/script/basic/JDK-8025434.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025486.js b/nashorn/test/script/basic/JDK-8025486.js
index 8012f72..f1012a9 100644
--- a/nashorn/test/script/basic/JDK-8025486.js
+++ b/nashorn/test/script/basic/JDK-8025486.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025488.js b/nashorn/test/script/basic/JDK-8025488.js
index 8229b9f..2d1dfeb 100644
--- a/nashorn/test/script/basic/JDK-8025488.js
+++ b/nashorn/test/script/basic/JDK-8025488.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -39,5 +39,5 @@
     return this.arr.toString();
 }
 
-var e = new MyError(); 
+var e = new MyError();
 print(e.stack.replace(/\\/g, '/'));
diff --git a/nashorn/test/script/basic/JDK-8025515.js b/nashorn/test/script/basic/JDK-8025515.js
index 29574d2..b88897b 100644
--- a/nashorn/test/script/basic/JDK-8025515.js
+++ b/nashorn/test/script/basic/JDK-8025515.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -47,7 +47,7 @@
         var stack = e.nashornException.getStackTrace();
         var name = getFirstScriptFrame(stack).methodName;
         if (name !== expected) {
-            fail("got " + stack[0].methodName + ", expected " + expected);
+            fail("got " + name + ", expected " + expected);
         }
     }
 }
@@ -61,7 +61,7 @@
 var f = (function() {
     return function() { a.b.c; };
 })();
-testMethodName(f, "L:61$L:62");
+testMethodName(f, "f$L:62");
 
 testMethodName((function() {
     return function() { return a.b.c; };
diff --git a/nashorn/test/script/basic/JDK-8025520.js b/nashorn/test/script/basic/JDK-8025520.js
index 773a30a..0e8ff80 100644
--- a/nashorn/test/script/basic/JDK-8025520.js
+++ b/nashorn/test/script/basic/JDK-8025520.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8025589.js b/nashorn/test/script/basic/JDK-8025589.js
index a74261c..75fdadb 100644
--- a/nashorn/test/script/basic/JDK-8025589.js
+++ b/nashorn/test/script/basic/JDK-8025589.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026008.js b/nashorn/test/script/basic/JDK-8026008.js
index 20c1d5f..0064646 100644
--- a/nashorn/test/script/basic/JDK-8026008.js
+++ b/nashorn/test/script/basic/JDK-8026008.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026016.js b/nashorn/test/script/basic/JDK-8026016.js
index 43f268d..4858b2c 100644
--- a/nashorn/test/script/basic/JDK-8026016.js
+++ b/nashorn/test/script/basic/JDK-8026016.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026033.js b/nashorn/test/script/basic/JDK-8026033.js
index 4a5d859..550f3c2 100644
--- a/nashorn/test/script/basic/JDK-8026033.js
+++ b/nashorn/test/script/basic/JDK-8026033.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026042.js b/nashorn/test/script/basic/JDK-8026042.js
index a853626..860488e 100644
--- a/nashorn/test/script/basic/JDK-8026042.js
+++ b/nashorn/test/script/basic/JDK-8026042.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026048.js b/nashorn/test/script/basic/JDK-8026048.js
index 33789fe..9c86147 100644
--- a/nashorn/test/script/basic/JDK-8026048.js
+++ b/nashorn/test/script/basic/JDK-8026048.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026112.js b/nashorn/test/script/basic/JDK-8026112.js
index 0e869f7..ae6f6ca 100644
--- a/nashorn/test/script/basic/JDK-8026112.js
+++ b/nashorn/test/script/basic/JDK-8026112.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026125.js b/nashorn/test/script/basic/JDK-8026125.js
index bb3a43d..d67b765 100644
--- a/nashorn/test/script/basic/JDK-8026125.js
+++ b/nashorn/test/script/basic/JDK-8026125.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026137.js b/nashorn/test/script/basic/JDK-8026137.js
index 4a19643..841e4f0 100644
--- a/nashorn/test/script/basic/JDK-8026137.js
+++ b/nashorn/test/script/basic/JDK-8026137.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8026137: Binary evaluation order in JavaScript is load load 
+ * JDK-8026137: Binary evaluation order in JavaScript is load load
  * convert convert, not load convert load convert.
  *
  * @test
@@ -30,14 +30,16 @@
  */
 
 try {
-    (function f() { Object.defineProperty({},"x",{get: function(){return {valueOf:function(){throw 0}}}}).x - Object.defineProperty({},"x",{get: function(){throw 1}}).x })()
-} 
+    (function f() {
+        Object.defineProperty({},"x",{get: function(){return {valueOf:function(){throw 0}}}}).x -
+        Object.defineProperty({},"x",{get: function(){throw 1}}).x })()
+}
 catch (e) {
     print(e);
 }
 
 try {
-    ({valueOf: function(){throw 0}}) - ({valueOf: function(){throw 1}} - 1) 
+    ({valueOf: function(){throw 0}}) - ({valueOf: function(){throw 1}} - 1)
 } catch (e) {
     print(e);
 }
diff --git a/nashorn/test/script/basic/JDK-8026161.js b/nashorn/test/script/basic/JDK-8026161.js
index e3e8848..caef2bb 100644
--- a/nashorn/test/script/basic/JDK-8026161.js
+++ b/nashorn/test/script/basic/JDK-8026161.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026162.js b/nashorn/test/script/basic/JDK-8026162.js
index ccd6ee7..3f44b98 100644
--- a/nashorn/test/script/basic/JDK-8026162.js
+++ b/nashorn/test/script/basic/JDK-8026162.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026167.js b/nashorn/test/script/basic/JDK-8026167.js
index 4959e62..7293c4c 100644
--- a/nashorn/test/script/basic/JDK-8026167.js
+++ b/nashorn/test/script/basic/JDK-8026167.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,7 +37,7 @@
 e.eval('function f() { var e = 33; eval("e") } f()');
 
 function f() {
-    Function.call.call(function x() { eval("x") }); eval("x") 
+    Function.call.call(function x() { eval("x") }); eval("x")
 }
 
 try {
diff --git a/nashorn/test/script/basic/JDK-8026248.js b/nashorn/test/script/basic/JDK-8026248.js
index e54d338..452b863 100644
--- a/nashorn/test/script/basic/JDK-8026248.js
+++ b/nashorn/test/script/basic/JDK-8026248.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 load('nashorn:mozilla_compat.js')
 
-importClass(java.io.File, java.io.InputStream) 
+importClass(java.io.File, java.io.InputStream)
 
 print(File)
 print(InputStream)
diff --git a/nashorn/test/script/basic/JDK-8026264.js b/nashorn/test/script/basic/JDK-8026264.js
index b4de01d..4d8efed 100644
--- a/nashorn/test/script/basic/JDK-8026264.js
+++ b/nashorn/test/script/basic/JDK-8026264.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026292.js b/nashorn/test/script/basic/JDK-8026292.js
index 740895f..ff33827 100644
--- a/nashorn/test/script/basic/JDK-8026292.js
+++ b/nashorn/test/script/basic/JDK-8026292.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026302.js b/nashorn/test/script/basic/JDK-8026302.js
index 786cc11..8545c3c 100644
--- a/nashorn/test/script/basic/JDK-8026302.js
+++ b/nashorn/test/script/basic/JDK-8026302.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -45,4 +45,4 @@
     var desc = Object.getOwnPropertyDescriptor(obj, prop);
     print(desc.get);
     print(desc.set);
-} 
+}
diff --git a/nashorn/test/script/basic/JDK-8026317.js b/nashorn/test/script/basic/JDK-8026317.js
index 57bea9c..91b5ccf 100644
--- a/nashorn/test/script/basic/JDK-8026317.js
+++ b/nashorn/test/script/basic/JDK-8026317.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026367.js b/nashorn/test/script/basic/JDK-8026367.js
index c5e1235..0b14ecf 100644
--- a/nashorn/test/script/basic/JDK-8026367.js
+++ b/nashorn/test/script/basic/JDK-8026367.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026692.js b/nashorn/test/script/basic/JDK-8026692.js
index f9f0f38..09f1159 100644
--- a/nashorn/test/script/basic/JDK-8026692.js
+++ b/nashorn/test/script/basic/JDK-8026692.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026693.js b/nashorn/test/script/basic/JDK-8026693.js
index fd1dd5f..59c10eb 100644
--- a/nashorn/test/script/basic/JDK-8026693.js
+++ b/nashorn/test/script/basic/JDK-8026693.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026701.js b/nashorn/test/script/basic/JDK-8026701.js
index 90a1739..35d63a4 100644
--- a/nashorn/test/script/basic/JDK-8026701.js
+++ b/nashorn/test/script/basic/JDK-8026701.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026805.js b/nashorn/test/script/basic/JDK-8026805.js
index 0133a0b..943c368 100644
--- a/nashorn/test/script/basic/JDK-8026805.js
+++ b/nashorn/test/script/basic/JDK-8026805.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026858.js b/nashorn/test/script/basic/JDK-8026858.js
index 92562ac..912b480 100644
--- a/nashorn/test/script/basic/JDK-8026858.js
+++ b/nashorn/test/script/basic/JDK-8026858.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8026955.js b/nashorn/test/script/basic/JDK-8026955.js
index a54e3d9..09270f3 100644
--- a/nashorn/test/script/basic/JDK-8026955.js
+++ b/nashorn/test/script/basic/JDK-8026955.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8027016.js b/nashorn/test/script/basic/JDK-8027016.js
index f84050f..69fd5d7 100644
--- a/nashorn/test/script/basic/JDK-8027016.js
+++ b/nashorn/test/script/basic/JDK-8027016.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8027024.js b/nashorn/test/script/basic/JDK-8027024.js
index 890c691..f23c802 100644
--- a/nashorn/test/script/basic/JDK-8027024.js
+++ b/nashorn/test/script/basic/JDK-8027024.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8027024: String.prototype.charAt and charCodeAt do not evaluate 'self' and 'pos' arguments in right order 
+ * JDK-8027024: String.prototype.charAt and charCodeAt do not evaluate 'self' and 'pos' arguments in right order
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8027042.js b/nashorn/test/script/basic/JDK-8027042.js
index eea6373..5977899 100644
--- a/nashorn/test/script/basic/JDK-8027042.js
+++ b/nashorn/test/script/basic/JDK-8027042.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -26,33 +26,35 @@
  *
  * @test
  * @run
+ * @fork
  */
 
 // var with getter side effect
-Object.defineProperty(this, "a", { get: function() {print("get a"); return 1; }});
+Object.defineProperty(this, "a1", { get: function() {print("get a"); return 1; }});
 
 // var with both getter and conversion side effect
-Object.defineProperty(this, "b", { get: function() {print("get b"); return {valueOf: function() { print("conv b"); return 10; }}; }});
+Object.defineProperty(this, "b1", { get: function() {print("get b"); return {valueOf: function() { print("conv b"); return 10; }}; }});
 
 (function() {
     // var with toPrimitive conversion side effect
-    var c = {valueOf: function() { print("conv c"); return 100; }};
-
-    print(b + (c + a));
-    print(b + (c + b));
-    print(b + (a + b));
-    print(b + (b + c));
-    print(b + (b + c));
-    print(b + (c + (a - b)));
-    print(b + (c + (c - b)));
-    print(b + (c + (b - c)));
-    print(b + (b + (a ? 2 : 3)));
-    print(b + (b + (b ? 2 : 3)));
-    print(b + (b + (c ? 2 : 3)));
-    print(b + ((-c) + (-a)));
-    print(b + ((-c) + (-b)));
-    print(b + ((-c) + (-c)));
-    try { print(b + new a); } catch (e) {}
-    try { print(b + new b); } catch (e) {}
-    try { print(b + new c); } catch (e) {}
+    var c1 = {valueOf: function() { print("conv c"); return 100; }};
+    print("start");
+    print(b1 + (c1 + a1));
+    print("done with first");
+    print(b1 + (c1 + b1));
+    print(b1 + (a1 + b1));
+    print(b1 + (b1 + c1));
+    print(b1 + (b1 + c1));
+    print(b1 + (c1 + (a1 - b1)));
+    print(b1 + (c1 + (c1 - b1)));
+    print(b1 + (c1 + (b1 - c1)));
+    print(b1 + (b1 + (a1 ? 2 : 3)));
+    print(b1 + (b1 + (b1 ? 2 : 3)));
+    print(b1 + (b1 + (c1 ? 2 : 3)));
+    print(b1 + ((-c1) + (-a1)));
+    print(b1 + ((-c1) + (-b1)));
+    print(b1 + ((-c1) + (-c1)));
+    try { print(b1 + new a1); } catch (e) {}
+    try { print(b1 + new b1); } catch (e) {}
+    try { print(b1 + new c1); } catch (e) {}
 })();
diff --git a/nashorn/test/script/basic/JDK-8027042.js.EXPECTED b/nashorn/test/script/basic/JDK-8027042.js.EXPECTED
index 25b34e6..e05a507 100644
--- a/nashorn/test/script/basic/JDK-8027042.js.EXPECTED
+++ b/nashorn/test/script/basic/JDK-8027042.js.EXPECTED
@@ -1,8 +1,10 @@
+start
 get b
 get a
 conv c
 conv b
 111
+done with first
 get b
 get b
 conv c
diff --git a/nashorn/test/script/basic/JDK-8027236.js b/nashorn/test/script/basic/JDK-8027236.js
index 02f9e8d..48b5367 100644
--- a/nashorn/test/script/basic/JDK-8027236.js
+++ b/nashorn/test/script/basic/JDK-8027236.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8027562.js b/nashorn/test/script/basic/JDK-8027562.js
index 950584b..16675df 100644
--- a/nashorn/test/script/basic/JDK-8027562.js
+++ b/nashorn/test/script/basic/JDK-8027562.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8027700.js b/nashorn/test/script/basic/JDK-8027700.js
index 4c5445d..1d2f4e7 100644
--- a/nashorn/test/script/basic/JDK-8027700.js
+++ b/nashorn/test/script/basic/JDK-8027700.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -43,7 +43,7 @@
     }
 }
 
-Object.defineProperty(this, "foo", { value:0 }) 
+Object.defineProperty(this, "foo", { value:0 })
 try {
     eval("function foo() {}");
     fail("should have thrown TypeError");
diff --git a/nashorn/test/script/basic/JDK-8027753.js b/nashorn/test/script/basic/JDK-8027753.js
index 2af0baa..4cb0187 100644
--- a/nashorn/test/script/basic/JDK-8027753.js
+++ b/nashorn/test/script/basic/JDK-8027753.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8027828.js b/nashorn/test/script/basic/JDK-8027828.js
index ab60938..3503dd1 100644
--- a/nashorn/test/script/basic/JDK-8027828.js
+++ b/nashorn/test/script/basic/JDK-8027828.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8027933.js b/nashorn/test/script/basic/JDK-8027933.js
index 506abc2..e723bc3 100644
--- a/nashorn/test/script/basic/JDK-8027933.js
+++ b/nashorn/test/script/basic/JDK-8027933.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/JDK-8028020.js b/nashorn/test/script/basic/JDK-8028020.js
index 4dfa0ca..36e5a79 100644
--- a/nashorn/test/script/basic/JDK-8028020.js
+++ b/nashorn/test/script/basic/JDK-8028020.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8028210.js b/nashorn/test/script/basic/JDK-8028210.js
index 54f113a..f3aef0b 100644
--- a/nashorn/test/script/basic/JDK-8028210.js
+++ b/nashorn/test/script/basic/JDK-8028210.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8028434.js b/nashorn/test/script/basic/JDK-8028434.js
index c337415..798ce6e 100644
--- a/nashorn/test/script/basic/JDK-8028434.js
+++ b/nashorn/test/script/basic/JDK-8028434.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,28 +31,28 @@
 
 try {
     while (test.apa < 0) {
-	print("x");
+    print("x");
     }
 } catch (e) {
     var st = e.getStackTrace();
     if (st.length != 1) {
-	print("erroneous stacktrace length " + s.length);
+    print("erroneous stacktrace length " + s.length);
     }
     if (st[0].lineNumber !== 33) {
-	print("erroneous stacktrace element, lineNumber=" + st[0].lineNumber + " elem=" + st);
+    print("erroneous stacktrace element, lineNumber=" + st[0].lineNumber + " elem=" + st);
     }
 }
 
 try {
     do {
-	print("x");
+    print("x");
     } while (test.apa < 0);
 } catch (e) {
     var st = e.getStackTrace();
     if (st.length != 1) {
-	print("erroneous stacktrace length " + s.length);
+    print("erroneous stacktrace length " + s.length);
     }
     if (st[0].lineNumber !== 49) {
-	print("erroneous stacktrace element, lineNumber= " + st[0].lineNumber + " elem=" + st);
+    print("erroneous stacktrace element, lineNumber= " + st[0].lineNumber + " elem=" + st);
     }
 }
diff --git a/nashorn/test/script/basic/JDK-8029364.js b/nashorn/test/script/basic/JDK-8029364.js
index dfa8ea9..fe93562 100644
--- a/nashorn/test/script/basic/JDK-8029364.js
+++ b/nashorn/test/script/basic/JDK-8029364.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8029384.js
similarity index 85%
rename from nashorn/test/script/basic/runsunspider-eager.js
rename to nashorn/test/script/basic/JDK-8029384.js
index db358d2..0012400 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8029384.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8029384: Function expression self-symbol not available for eval
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var g = function f() { print(eval("f.x")) }
+g.x = "tada!"
+g()
diff --git a/nashorn/test/script/basic/JDK-8029384.js.EXPECTED b/nashorn/test/script/basic/JDK-8029384.js.EXPECTED
new file mode 100644
index 0000000..c8f9123
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8029384.js.EXPECTED
@@ -0,0 +1 @@
+tada!
diff --git a/nashorn/test/script/basic/JDK-8029467.js b/nashorn/test/script/basic/JDK-8029467.js
index ad7f2fd..76b280a 100644
--- a/nashorn/test/script/basic/JDK-8029467.js
+++ b/nashorn/test/script/basic/JDK-8029467.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,3 +32,4 @@
 print((function (x) { if(x) { return true } else { return 0 } })(true))
 print(typeof (function (x) { return x ? 1 : "123" })(true) === "number")
 print(typeof (function (x) { if(x) { return 1 } else { return "123" } })(true) === "number")
+
diff --git a/nashorn/test/script/basic/JDK-8029667.js b/nashorn/test/script/basic/JDK-8029667.js
index c0c2d15..016b4e8 100644
--- a/nashorn/test/script/basic/JDK-8029667.js
+++ b/nashorn/test/script/basic/JDK-8029667.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 
 function f(x) {
-  return (function inner() { 
+  return (function inner() {
       var y; (function dummy() { return y })() // force own scope for the inner function
       with({}) { // 'with' block turns off fast scopes
           return x
@@ -39,8 +39,8 @@
 print(f(1));
 print(f(2));
 
-function g(x) { 
-  (function inner() { 
+function g(x) {
+  (function inner() {
       var y; (function dummy() { return y })() // force own scope for the inner function
       with({}) { // 'with' block turns off fast scopes
           // Test setter as well as getter
@@ -83,9 +83,7 @@
         }
     }
     main();
-} 
+}
 
 print(withScopes[0].func);
 print(withScopes[1].func);
-
-
diff --git a/nashorn/test/script/basic/JDK-8030182.js b/nashorn/test/script/basic/JDK-8030182.js
index f3c492d..f9f0e9b 100644
--- a/nashorn/test/script/basic/JDK-8030182.js
+++ b/nashorn/test/script/basic/JDK-8030182.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8030182_2.js b/nashorn/test/script/basic/JDK-8030182_2.js
index de507e1..9ad8f31 100644
--- a/nashorn/test/script/basic/JDK-8030182_2.js
+++ b/nashorn/test/script/basic/JDK-8030182_2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,19 +28,19 @@
  * @run
  */
 
-var str = ""; 
+var str = "";
 
 // large code to force splitting
-for (i = 0; i < 1000; ++i) 
+for (i = 0; i < 1000; ++i)
     str +="o = new Object()\n";
 
-str +="g()"; 
+str +="g()";
 
 // check that "$split" or some such internal method
 // does not appear in script stack trace!!
 try {
     eval(str);
 } catch (e) {
-    print(e.stack.replace(/\\/g, '/'));
+    print(e.stack.replace(/\\/g, '/').replace(/<eval>@[0-9]+/, '<eval>@<id>'));
 }
 
diff --git a/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED b/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED
index 772e504..9fdd913 100644
--- a/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED
+++ b/nashorn/test/script/basic/JDK-8030182_2.js.EXPECTED
@@ -1,3 +1,3 @@
 ReferenceError: "g" is not defined
-	at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@0:-1)
+	at <program> (test/script/basic/JDK-8030182_2.js#42:4<eval>@<id>:-1)
 	at <program> (test/script/basic/JDK-8030182_2.js:42)
diff --git a/nashorn/test/script/basic/JDK-8030197.js b/nashorn/test/script/basic/JDK-8030197.js
index 366d33d..5b4ee0b 100644
--- a/nashorn/test/script/basic/JDK-8030197.js
+++ b/nashorn/test/script/basic/JDK-8030197.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/JDK-8030199.js b/nashorn/test/script/basic/JDK-8030199.js
index b6d32fb..c4759ae 100644
--- a/nashorn/test/script/basic/JDK-8030199.js
+++ b/nashorn/test/script/basic/JDK-8030199.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8030200.js b/nashorn/test/script/basic/JDK-8030200.js
index e49eec7..a62fa49 100644
--- a/nashorn/test/script/basic/JDK-8030200.js
+++ b/nashorn/test/script/basic/JDK-8030200.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8030202.js b/nashorn/test/script/basic/JDK-8030202.js
index 6cf5647..e2b014d 100644
--- a/nashorn/test/script/basic/JDK-8030202.js
+++ b/nashorn/test/script/basic/JDK-8030202.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8030809.js b/nashorn/test/script/basic/JDK-8030809.js
index 01c7687..99b21c3 100644
--- a/nashorn/test/script/basic/JDK-8030809.js
+++ b/nashorn/test/script/basic/JDK-8030809.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 
 function func() {
-    (function() { 
+    (function() {
         throw new Error();
     })();
 }
diff --git a/nashorn/test/script/basic/JDK-8031317.js b/nashorn/test/script/basic/JDK-8031317.js
index 240a633..6cf43fe 100644
--- a/nashorn/test/script/basic/JDK-8031317.js
+++ b/nashorn/test/script/basic/JDK-8031317.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8031359.js b/nashorn/test/script/basic/JDK-8031359.js
index 278fd7d..c2d4ac6 100644
--- a/nashorn/test/script/basic/JDK-8031359.js
+++ b/nashorn/test/script/basic/JDK-8031359.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8031983.js b/nashorn/test/script/basic/JDK-8031983.js
index f0bfca1..7f3631d 100644
--- a/nashorn/test/script/basic/JDK-8031983.js
+++ b/nashorn/test/script/basic/JDK-8031983.js
@@ -1,28 +1,28 @@
 /*
  * Copyright (c) 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.
  */
 
 /**
- * JDK-8031983: Error objects should capture stack at the constructor 
+ * JDK-8031983: Error objects should capture stack at the constructor
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8032004.js b/nashorn/test/script/basic/JDK-8032004.js
index 2995566..29e8cb0 100644
--- a/nashorn/test/script/basic/JDK-8032004.js
+++ b/nashorn/test/script/basic/JDK-8032004.js
@@ -1,28 +1,28 @@
 /*
  * Copyright (c) 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.
  */
 
 /**
- * JDK-8032004: instance property "message" of Error objects should be non-enumerable 
+ * JDK-8032004: instance property "message" of Error objects should be non-enumerable
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8032068.js b/nashorn/test/script/basic/JDK-8032068.js
index 570789d..f98f0c6 100644
--- a/nashorn/test/script/basic/JDK-8032068.js
+++ b/nashorn/test/script/basic/JDK-8032068.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/JDK-8034055.js b/nashorn/test/script/basic/JDK-8034055.js
index 0a21d9f..ff87068 100644
--- a/nashorn/test/script/basic/JDK-8034055.js
+++ b/nashorn/test/script/basic/JDK-8034055.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8037562.js b/nashorn/test/script/basic/JDK-8037562.js
index 7534a0d..bcd828c 100644
--- a/nashorn/test/script/basic/JDK-8037562.js
+++ b/nashorn/test/script/basic/JDK-8037562.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8038413.js
similarity index 70%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8038413.js
index db358d2..d7b5ed2 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8038413.js
@@ -1,33 +1,38 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8038413: NPE in unboxInteger
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+// When adapting a method returning Integer to an optimistic call site
+// expecting int, can't forego filters because of null. That is, the
+// Integer->int conversion can't be left to the automatisms present in
+// java.lang.invoke.MethodHandle.asType() because of potential null
+// values.
+var IntegerArray = Java.type("java.lang.Integer[]");
+var arr = new IntegerArray(1);
+print(arr[0]);
diff --git a/nashorn/test/script/basic/JDK-8038413.js.EXPECTED b/nashorn/test/script/basic/JDK-8038413.js.EXPECTED
new file mode 100644
index 0000000..19765bd
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8038413.js.EXPECTED
@@ -0,0 +1 @@
+null
diff --git a/nashorn/test/script/basic/JDK-8038945.js b/nashorn/test/script/basic/JDK-8038945.js
new file mode 100644
index 0000000..efaccd6
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8038945.js
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8038945.js : test various undefined strict intrinsics and that they
+ * aren't erroneously applied when undefined is in any scope but global
+ *
+ * @test
+ * @run
+ */
+
+//:program internals={print=0, f1=0, f2=0, f3=0, f4=0, undefined=0, f5=0} externals=null
+
+//f1 internals={} externals={undefined=0}
+function f1(x) {
+    return x === undefined;
+}
+
+//f2 internals={} externals=null
+function f2(x, undefined) {
+    return x === undefined;
+}
+
+//f3 internals={x=0} externals=null
+function f3(x) {
+    //f3$f3_2 internals={} externals={x=0}
+    function f3_2(undefined) {
+    return x === undefined;
+    }
+    return f3_2(17);
+}
+
+//f4 internals={x=0} externals=null
+function f4(x) {
+    //f4$f4_2 internals={} externals={x=0}
+    function f4_2() {
+    var undefined = 17;
+    return x === undefined;
+    }
+    return f4_2();
+}
+
+//f5 internals={x=0, undefined=0} externals=null
+function f5(x) {
+    var undefined = 17;
+    //f5$f5_2 internals={} externals={x=0, undefined=0}
+    function f5_2() {
+    return x === undefined;
+    }
+    return f5_2();
+}
+
+print(" 1: " + f1(17) + " === false");
+print(" 2: " + f2(17) + " === false");
+print(" 3: " + f3(17) + " === true");
+print(" 4: " + f4(17) + " === true");
+print(" 5: " + f5(17) + " === true");
+
+//recompile
+print(" 6: " + f1("17") + " === false");
+print(" 7: " + f2("17") + " === false");
+print(" 8: " + f3("17") + " === false");
+print(" 9: " + f4("17") + " === false");
+print("10: " + f5("17") + " === false");
+
+//g1 internals={} externals={undefined=0}
+function g1(x) {
+    return x !== undefined;
+}
+
+//g2 internals={} externals=null
+function g2(x, undefined) {
+    return x !== undefined;
+}
+
+//g3 internals={x=0} externals=null
+function g3(x) {
+    //g3$g3_2 internals={} externals={x=0}
+    function g3_2(undefined) {
+    return x !== undefined;
+    }
+    return g3_2(17);
+}
+
+//g4 internals={x=0} externals=null
+function g4(x) {
+    //f4$f4_2 internals={} externals={x=0}
+    function g4_2() {
+    var undefined = 17;
+    return x !== undefined;
+    }
+    return g4_2();
+}
+
+//g5 internals={x=0, undefined=0} externals=null
+function g5(x) {
+    var undefined = 17;
+    //g5$g5_2 internals={} externals={x=0, undefined=0}
+    function g5_2() {
+    return x !== undefined;
+    }
+    return g5_2();
+}
+
+print("11: " + g1(17) + " === true");
+print("12: " + g2(17) + " === true");
+print("13: " + g3(17) + " === false");
+print("14: " + g4(17) + " === false");
+print("15: " + g5(17) + " === false");
+
+//recompile
+print("16: " + g1("17") + " === true");
+print("17: " + g2("17") + " === true");
+print("18: " + g3("17") + " === true");
+print("19: " + g4("17") + " === true");
+print("20: " + g5("17") + " === true");
+
+//h1 internals={} externals={undefined=0}
+function h1(x) {
+    return undefined === x;
+}
+
+//h2 internals={} externals=null
+function h2(x, undefined) {
+    return undefined === x;
+}
+
+//h3 internals={x=0} externals=null
+function h3(x) {
+    //h3$f3_2 internals={} externals={x=0}
+    function h3_2(undefined) {
+    return undefined === x;
+    }
+    return h3_2(17);
+}
+
+//h4 internals={x=0} externals=null
+function h4(x) {
+    //h4$h4_2 internals={} externals={x=0}
+    function h4_2() {
+    var undefined = 17;
+    return undefined === x;
+    }
+    return h4_2();
+}
+
+//h5 internals={x=0, undefined=0} externals=null
+function h5(x) {
+    var undefined = 17;
+    //h5$h5_2 internals={} externals={x=0, undefined=0}
+    function h5_2() {
+    return undefined === x;
+    }
+    return h5_2();
+}
+
+print("21: " + h1(17) + " === false");
+print("22: " + h2(17) + " === false");
+print("23: " + h3(17) + " === true");
+print("24: " + h4(17) + " === true");
+print("25: " + h5(17) + " === true");
+
+//recompile
+print("26: " + h1("17") + " === false");
+print("27: " + h2("17") + " === false");
+print("28: " + h3("17") + " === false");
+print("29: " + h4("17") + " === false");
+print("30: " + h5("17") + " === false");
+
+//i1 internals={} externals={undefined=0}
+function i1(x) {
+    return undefined !== x;
+}
+
+//i2 internals={} externals=null
+function i2(x, undefined) {
+    return undefined !== x;
+}
+
+//i3 internals={x=0} externals=null
+function i3(x) {
+    //i3$f3_2 internals={} externals={x=0}
+    function i3_2(undefined) {
+    return undefined !== x;
+    }
+    return i3_2(17);
+}
+
+//i4 internals={x=0} externals=null
+function i4(x) {
+    //i4$i4_2 internals={} externals={x=0}
+    function i4_2() {
+    var undefined = 17;
+    return undefined !== x;
+    }
+    return i4_2();
+}
+
+//h5 internals={x=0, undefined=0} externals=null
+function i5(x) {
+    var undefined = 17;
+    //i5$i5_2 internals={} externals={x=0, undefined=0}
+    function i5_2() {
+    return undefined !== x;
+    }
+    return i5_2();
+}
+
+print("31: " + i1(17) + " === true");
+print("32: " + i2(17) + " === true");
+print("33: " + i3(17) + " === false");
+print("34: " + i4(17) + " === false");
+print("35: " + i5(17) + " === false");
+
+//recompile
+print("36: " + i1("17") + " === true");
+print("37: " + i2("17") + " === true");
+print("38: " + i3("17") + " === true");
+print("39: " + i4("17") + " === true");
+print("40: " + i5("17") + " === true");
diff --git a/nashorn/test/script/basic/JDK-8038945.js.EXPECTED b/nashorn/test/script/basic/JDK-8038945.js.EXPECTED
new file mode 100644
index 0000000..4d8dbc3
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8038945.js.EXPECTED
@@ -0,0 +1,40 @@
+ 1: false === false
+ 2: false === false
+ 3: true === true
+ 4: true === true
+ 5: true === true
+ 6: false === false
+ 7: false === false
+ 8: false === false
+ 9: false === false
+10: false === false
+11: true === true
+12: true === true
+13: false === false
+14: false === false
+15: false === false
+16: true === true
+17: true === true
+18: true === true
+19: true === true
+20: true === true
+21: false === false
+22: false === false
+23: true === true
+24: true === true
+25: true === true
+26: false === false
+27: false === false
+28: false === false
+29: false === false
+30: false === false
+31: true === true
+32: true === true
+33: false === false
+34: false === false
+35: false === false
+36: true === true
+37: true === true
+38: true === true
+39: true === true
+40: true === true
diff --git a/nashorn/test/script/basic/JDK-8039387.js b/nashorn/test/script/basic/JDK-8039387.js
index 8f903c1..562b29a 100644
--- a/nashorn/test/script/basic/JDK-8039387.js
+++ b/nashorn/test/script/basic/JDK-8039387.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/JDK-8040024.js b/nashorn/test/script/basic/JDK-8040024.js
new file mode 100644
index 0000000..86ce683
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8040024.js
@@ -0,0 +1,100 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8040024: NaN comparisons were failing
+ *
+ * @test
+ * @run
+ */
+
+function f(x) {
+  if((x - '0') <= 9) {
+      print("FAIL if <=");
+  } else {
+      print("OK");
+  }
+
+  if((x - '0') < 9) {
+      print("FAIL if <");
+  } else {
+      print("OK");
+  }
+
+  if((x - '0') >= 9) {
+      print("FAIL if >=");
+  } else {
+      print("OK");
+  }
+
+  if((x - '0') > 9) {
+      print("FAIL if >");
+  } else {
+      print("OK");
+  }
+
+  while((x - '0') <= 9) {
+      print("FAIL while <=");
+      break;
+  }
+
+  while((x - '0') < 9) {
+      print("FAIL while <");
+      break;
+  }
+
+  while((x - '0') > 9) {
+      print("FAIL while >");
+      break;
+  }
+
+  while((x - '0') >= 9) {
+      print("FAIL while >=");
+      break;
+  }
+
+  var i = 0;
+  do {
+      print("do-while <= only once");
+      if(++i == 2) { break; }
+  } while((x - '0') <= 9);
+
+  var i = 0;
+  do {
+      print("do-while < only once");
+      if(++i == 2) { break; }
+  } while((x - '0') < 9);
+
+  var i = 0;
+  do {
+      print("do-while >= only once");
+      if(++i == 2) { break; }
+  } while((x - '0') >= 9);
+
+  var i = 0;
+  do {
+      print("do-while > only once");
+      if(++i == 2) { break; }
+  } while((x - '0') > 9);
+}
+f('%')
diff --git a/nashorn/test/script/basic/JDK-8040024.js.EXPECTED b/nashorn/test/script/basic/JDK-8040024.js.EXPECTED
new file mode 100644
index 0000000..9623302
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8040024.js.EXPECTED
@@ -0,0 +1,8 @@
+OK
+OK
+OK
+OK
+do-while <= only once
+do-while < only once
+do-while >= only once
+do-while > only once
diff --git a/nashorn/test/script/basic/JDK-8041995.js b/nashorn/test/script/basic/JDK-8041995.js
new file mode 100644
index 0000000..9da26b7
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8041995.js
@@ -0,0 +1,69 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8041995: optimistic object property maps were only updated if the outermost program
+ * point in a property setter failed, not an inner one, which is wrong.
+ *
+ * @test
+ * @run
+ */
+
+function xyzzy() {
+    return 17.4711;
+}
+var obj = {
+    z: -xyzzy()
+};
+print(obj.z);
+
+function phlug() {
+    var obj = {
+    4: -Infinity,
+     5: Infinity,
+    length: 5 - Math.pow(2, 32)
+    };
+
+    return Array.prototype.lastIndexOf.call(obj, -Infinity) === 4;
+}
+
+var d = new Date;
+print(phlug());
+var d2 = new Date - d;
+print(d2 < 5000); // if this takes more than five seconds we have read the double length as an int
+
+function wrong() {
+    var obj = {
+    length1: 5 - Math.pow(2, 32),
+    length2: 4 - Math.pow(2, 32),
+    length3: 3 - Math.pow(2, 32),
+    length4: 2 - Math.pow(2, 32),
+    length5: 1 - Math.pow(2, 32),
+    length6: Math.pow(2, 32)
+    };
+    for (var i in obj) {
+       print(obj[i]);
+    }
+}
+
+wrong();
diff --git a/nashorn/test/script/basic/JDK-8041995.js.EXPECTED b/nashorn/test/script/basic/JDK-8041995.js.EXPECTED
new file mode 100644
index 0000000..accabf4
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8041995.js.EXPECTED
@@ -0,0 +1,9 @@
+-17.4711
+true
+true
+-4294967291
+-4294967292
+-4294967293
+-4294967294
+-4294967295
+4294967296
diff --git a/nashorn/test/script/basic/JDK-8041998.js b/nashorn/test/script/basic/JDK-8041998.js
index 33e4d13..c19f8a2 100644
--- a/nashorn/test/script/basic/JDK-8041998.js
+++ b/nashorn/test/script/basic/JDK-8041998.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/JDK-8042364.js b/nashorn/test/script/basic/JDK-8042364.js
index d8b81e2..97f36cf 100644
--- a/nashorn/test/script/basic/JDK-8042364.js
+++ b/nashorn/test/script/basic/JDK-8042364.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -23,7 +23,7 @@
 
 /**
  * JDK-8042364: Make __proto__ ES6 draft compliant
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8043133.js
similarity index 72%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8043133.js
index db358d2..b1f9e37 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8043133.js
@@ -1,33 +1,41 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8043133: Fix corner cases of JDK-8041995
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+var x = {}
+var b = false;
+// Ternary expression is not optimistic, yet the analyzer must still
+// find the optimistic subexpression f() that triggered deoptimizing
+// recompilation.
+Object.defineProperty(x, 'foo', { value: b ? b : f() });
+print(x.foo); // Must print "Hello world" instead of 0
 
+function f() {
+    return "Hello World!"
+}
diff --git a/nashorn/test/script/basic/JDK-8043133.js.EXPECTED b/nashorn/test/script/basic/JDK-8043133.js.EXPECTED
new file mode 100644
index 0000000..980a0d5
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8043133.js.EXPECTED
@@ -0,0 +1 @@
+Hello World!
diff --git a/nashorn/test/script/basic/JDK-8043232.js b/nashorn/test/script/basic/JDK-8043232.js
new file mode 100644
index 0000000..fa46b41
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8043232.js
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8043232: Index selection of overloaded java new constructors
+ *
+ * @test
+ * @run
+ */
+
+// call explicit constructor
+print(new (java.awt["Color(int,int,int)"])(255,0,255));
+// print the constructor itself
+print(java.awt["Color(int,int,int)"]);
+
+// store constructor to call later
+var Color = java.awt["Color(int,int,int)"];
+// call stored constructor
+print(new Color(33, 233, 2))
+
+// check if default constructor works
+var obj = new (java.lang["Object()"])();
+if (obj.class != java.lang.Object.class) {
+    fail("obj is a java.lang.Object");
+}
+
+// expected failure cases.
+function checkIt(func) {
+    try {
+        func();
+        throw new Error("should have thrown TypeError");
+    } catch(e) {
+        if (! (e instanceof TypeError)) {
+            fail("Expected TypeError, got " + e);
+        }
+        print(e);
+    }
+}
+
+// constructor of a non-existent class
+checkIt(function() new (java.lang["NonExistent(String)"])());
+
+// non-existent constructor of an existing class
+checkIt(function() new (java.lang["Object(String)"])());
+
+// garbage signature string
+checkIt(function() new (java.lang["Object()xxxxx"])());
+checkIt(function() new (java.lang["Object("])());
+checkIt(function() new (java.lang["Object)"])());
+
+var System = Java.type("java.lang.System");
+// try to do 'new' on static method
+checkIt(function() new (System.getProperty)("java.version"));
+
+// try to do 'new' on an instance method
+var println = System.out.println;
+checkIt(function() new println("hello"));
+
+// call constructor as normal method (without 'new')
+checkIt(function() Color());
+
+// try constructor on interface
+checkIt(function() new java.lang["Runnable()"]);
+checkIt(function() new java.lang["Runnable(int)"]);
+
+// try constructor on abstrace class
+try {
+    new java.io["InputStream()"];
+    throw new Error("should have thrown exception!");
+} catch (e) {
+    print(e);
+}
diff --git a/nashorn/test/script/basic/JDK-8043232.js.EXPECTED b/nashorn/test/script/basic/JDK-8043232.js.EXPECTED
new file mode 100644
index 0000000..5fcfab8
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8043232.js.EXPECTED
@@ -0,0 +1,14 @@
+java.awt.Color[r=255,g=0,b=255]
+[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
+java.awt.Color[r=33,g=233,b=2]
+TypeError: No such Java class: java.lang.NonExistent
+TypeError: No such Java constructor: Object(String)
+TypeError: Java constructor signature invalid: Object()xxxxx
+TypeError: Java constructor signature invalid: Object(
+TypeError: Java constructor signature invalid: Object)
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.lang.System.getProperty] cant be used as a constructor.
+TypeError: Java method [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println] cant be used as a constructor.
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires new.
+TypeError: No such Java constructor: Runnable()
+TypeError: No such Java constructor: Runnable(int)
+java.lang.InstantiationException: java.io.InputStream
diff --git a/nashorn/test/script/basic/JDK-8010697.js b/nashorn/test/script/basic/JDK-8043235.js
similarity index 61%
copy from nashorn/test/script/basic/JDK-8010697.js
copy to nashorn/test/script/basic/JDK-8043235.js
index c1b8e57..05de8f3 100644
--- a/nashorn/test/script/basic/JDK-8010697.js
+++ b/nashorn/test/script/basic/JDK-8043235.js
@@ -22,38 +22,37 @@
  */
 
 /**
- * JDK-8010697: DeletedArrayFilter seems to leak memory
+ * JDK-8043235: Type-based optimizations interfere with continuation methods
  *
  * @test
  * @run
  */
 
-var N = 1000;
-
-var array = new Array(N);
-var WeakReferenceArray = Java.type("java.lang.ref.WeakReference[]");
-var refArray = new WeakReferenceArray(N);
-
-for (var i = 0; i < N; i ++) {
-    var object = new java.lang.Object();
-    array[i] = object;
-    refArray[i] = new java.lang.ref.WeakReference(object);
+function g() {
+  return "Hello World!"
 }
 
-object = null;
-
-for (var i = 0; i < N; i ++) {
-    delete array[i];
-}
-
-java.lang.System.gc();
-java.lang.System.gc();
-
-for (var i = 0; i < N; i ++) {
-    if (refArray[i].get() != null) {
-        print("Reference found at " + i);
-        exit(0);
+function f1() {
+    var c;
+    var paused = false;
+    // If we didn't disable nullCheck specialization for expressions
+    // containing a deoptimization site, we'd get an AssertionError
+    while (!paused && (null !== (c = g()))) {
+      print(c);
+      paused = true;
     }
 }
 
-print("All references gone");
+function f2() {
+    var c;
+    var paused = false;
+    // If we didn't disable undefinedCheck specialization for expressions
+    // containing a deoptimization site, we'd get an AssertionError
+    while (!paused && (undefined !== (c = g()))) {
+      print(c);
+      paused = true;
+    }
+}
+
+f1();
+f2();
diff --git a/nashorn/test/script/basic/JDK-8043235.js.EXPECTED b/nashorn/test/script/basic/JDK-8043235.js.EXPECTED
new file mode 100644
index 0000000..f28b391
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8043235.js.EXPECTED
@@ -0,0 +1,2 @@
+Hello World!
+Hello World!
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8043431.js
similarity index 76%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8043431.js
index c9182ef..270db1c 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8043431.js
@@ -1,35 +1,42 @@
 /*
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8043431: Fix yet another corner case of JDK-8041995
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var a = "Hello World!";
+
+// Without the fix, evaluating "a" optimistically will start a
+// deoptimizing recompilation in a nested object literal, and trigger an
+// assertion in code generator.
+var x = {
+    foo: {
+        value: a
+    }
+};
+
+print(x.foo.value);
diff --git a/nashorn/test/script/basic/JDK-8043431.js.EXPECTED b/nashorn/test/script/basic/JDK-8043431.js.EXPECTED
new file mode 100644
index 0000000..980a0d5
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8043431.js.EXPECTED
@@ -0,0 +1 @@
+Hello World!
diff --git a/nashorn/test/script/basic/JDK-8043930.js b/nashorn/test/script/basic/JDK-8043930.js
index a89b354..a7c93f4 100644
--- a/nashorn/test/script/basic/JDK-8043930.js
+++ b/nashorn/test/script/basic/JDK-8043930.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * JDK-8043930: TypeError when attemping to create an instance of non-public class could be better 
+ * JDK-8043930: TypeError when attemping to create an instance of non-public class could be better
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/JDK-8044520.js b/nashorn/test/script/basic/JDK-8044520.js
index edcaa11..6086ec0 100644
--- a/nashorn/test/script/basic/JDK-8044520.js
+++ b/nashorn/test/script/basic/JDK-8044520.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8044533.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8044533.js
index db358d2..b3f0407 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8044533.js
@@ -1,33 +1,31 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8044533: Deoptimizing negation produces wrong result for zero
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+print(1/(function() { var f = 0; return -f; })())
diff --git a/nashorn/test/script/basic/JDK-8044533.js.EXPECTED b/nashorn/test/script/basic/JDK-8044533.js.EXPECTED
new file mode 100644
index 0000000..879e80e
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8044533.js.EXPECTED
@@ -0,0 +1 @@
+-Infinity
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8044534.js
similarity index 77%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8044534.js
index c9182ef..e274328 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8044534.js
@@ -1,35 +1,36 @@
 /*
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8044534: Constant folding for unary + should produce int for boolean literals
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect;
+
+print(inspect(+true,  "+true "));
+print(inspect(+false, "+false"));
+print(inspect(-true,  "-true "));
+print(inspect(-false, "-false"));
diff --git a/nashorn/test/script/basic/JDK-8044534.js.EXPECTED b/nashorn/test/script/basic/JDK-8044534.js.EXPECTED
new file mode 100644
index 0000000..69c8e4c
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8044534.js.EXPECTED
@@ -0,0 +1,4 @@
++true : int
++false: int
+-true : int
+-false: double
diff --git a/nashorn/test/script/basic/JDK-8044612.js b/nashorn/test/script/basic/JDK-8044612.js
index 6980cd1..9994d87 100644
--- a/nashorn/test/script/basic/JDK-8044612.js
+++ b/nashorn/test/script/basic/JDK-8044612.js
@@ -34,4 +34,4 @@
 
 if ("hello".replace("o", "$x") != "hell$x") {
     fail("String.prototype.replace failed to handle '$x' as replacement");
-} 
+}
diff --git a/nashorn/test/script/basic/JDK-8044695.js b/nashorn/test/script/basic/JDK-8044695.js
index 2e7b774..3f94ffb 100644
--- a/nashorn/test/script/basic/JDK-8044695.js
+++ b/nashorn/test/script/basic/JDK-8044695.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/JDK-8044750.js b/nashorn/test/script/basic/JDK-8044750.js
index ee6fa4d..b084d57 100644
--- a/nashorn/test/script/basic/JDK-8044750.js
+++ b/nashorn/test/script/basic/JDK-8044750.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8046013.js
similarity index 61%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8046013.js
index c9182ef..e3a5ac4 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8046013.js
@@ -1,35 +1,57 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8046013: TypeError: Cannot apply "with" to non script object
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var obj = loadWithNewGlobal({
+    script: "({ f: 33 })",
+    name: "test"
+});
+
+with (obj) {
+   print("f = " + f);
+}
+
+var obj2 = loadWithNewGlobal({
+    script: "var obj = Object.create({ foo: 42 }); obj.bar = 'hello'; obj",
+    name: "test2"
+});
+
+with (obj2) {
+    print("foo = " + foo);
+    print("bar = " + bar);
+}
+
+var obj3 = loadWithNewGlobal({
+    script: "({ f: 33, func: function() { print('this.f =', this.f); } })",
+    name: "test"
+});
+
+with(obj3) {
+    func();
+}
diff --git a/nashorn/test/script/basic/JDK-8046013.js.EXPECTED b/nashorn/test/script/basic/JDK-8046013.js.EXPECTED
new file mode 100644
index 0000000..4b612ed
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8046013.js.EXPECTED
@@ -0,0 +1,4 @@
+f = 33
+foo = 42
+bar = hello
+this.f = 33
diff --git a/nashorn/test/script/basic/JDK-8046026.js b/nashorn/test/script/basic/JDK-8046026.js
new file mode 100644
index 0000000..585621f
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8046026.js
@@ -0,0 +1,49 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8046026: CompiledFunction.relinkComposableInvoker assert is being hit
+ * JDK-8044770: crash with jdk9-dev/nashorn during global object initialization from MT test
+ * JDK-8047770: NPE in deoptimizing recompilation in multithreaded
+ *
+ * @test
+ * @run
+ */
+
+(function() {
+var n = 1 << 25;
+var ThreadLocalRandom = java.util.concurrent.ThreadLocalRandom;
+var m = java.util.stream.IntStream.range(0, n)
+ .parallel() // this is the essence of this test. We must trigger parallel execution
+ .filter(function() {
+     var tlr = ThreadLocalRandom.current();
+
+     var x = tlr.nextDouble(-1.0, 1.0);
+     var y = tlr.nextDouble(-1.0, 1.0);
+
+     return x * x + y * y <= 1.0;
+ })
+ .count();
+var pi = (4.0 * m) / n;
+print(pi.toFixed(2));
+})()
diff --git a/nashorn/test/script/basic/JDK-8046026.js.EXPECTED b/nashorn/test/script/basic/JDK-8046026.js.EXPECTED
new file mode 100644
index 0000000..6324d40
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8046026.js.EXPECTED
@@ -0,0 +1 @@
+3.14
diff --git a/nashorn/test/script/basic/JDK-8046905.js b/nashorn/test/script/basic/JDK-8046905.js
new file mode 100644
index 0000000..b11a6ad
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8046905.js
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8046905: apply on apply is broken
+ *
+ * @test
+ * @run
+ */
+
+var apply = Function.prototype.apply;
+var call = Function.prototype.call;
+var sort = Array.prototype.sort;
+var join = Array.prototype.join;
+
+// Running three times so that we test an already linked call site too:
+// i==0: linking initially with assumed optimistic returned type int.
+// i==1: linking after deoptimization with returned type Object.
+// i==2: re-running code linked in previous iteration. This will
+//       properly exercise the guards too.
+print("1 level of apply")
+for(i = 0; i < 3; ++i) {
+    print(sort.apply([4,3,2,1]))
+}
+print("2 levels of apply")
+for(i = 0; i < 3; ++i) {
+    print(apply.apply(sort,[[4,3,2,1]]))
+}
+print("3 levels of apply")
+for(i = 0; i < 3; ++i) {
+    print(apply.apply(apply,[sort,[[4,3,2,1]]]))
+}
+print("4 levels of apply")
+for(i = 0; i < 3; ++i) {
+    print(apply.apply(apply,[apply,[sort,[[4,3,2,1]]]]))
+}
+print("5 levels of apply")
+for(i = 0; i < 3; ++i) {
+    print(apply.apply(apply,[apply,[apply,[sort,[[4,3,2,1]]]]]))
+}
+print("Many levels of apply!")
+for(i = 0; i < 3; ++i) {
+    print(apply.apply(apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[apply,[sort,[[4,3,2,1]]]]]]]]]]]]]]]]]]]]]]))
+}
+
+print("different invocations that'll trigger relinking")
+var invocation = [sort,[[4,3,2,1]]];
+for(i = 0; i < 4; ++i) {
+    print(apply.apply(apply,[apply,invocation]))
+    // First change after i==1, so it relinks an otherwise stable linkage
+    if(i == 1) {
+    invocation = [sort,[[8,7,6,5]]];
+    } else if(i == 2) {
+        invocation = [join,[[8,7,6,5],["-"]]];
+    }
+}
+
+print("Many levels of call!")
+for(i = 0; i < 3; ++i) {
+    print(call.call(call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,call,sort,[4,3,2,1]))
+}
+
+print("call apply call apply call... a lot");
+for(i = 0; i < 3; ++i) {
+    print(apply.call(call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [sort, [4,3,2,1]]]]]]]))
+}
+
+print("apply call apply call apply... a lot");
+for(i = 0; i < 3; ++i) {
+    print(call.apply(apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, apply, [call, sort, [[4,3,2,1]]]]]]]]]))
+}
diff --git a/nashorn/test/script/basic/JDK-8046905.js.EXPECTED b/nashorn/test/script/basic/JDK-8046905.js.EXPECTED
new file mode 100644
index 0000000..0cee678
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8046905.js.EXPECTED
@@ -0,0 +1,41 @@
+1 level of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+2 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+3 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+4 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+5 levels of apply
+1,2,3,4
+1,2,3,4
+1,2,3,4
+Many levels of apply!
+1,2,3,4
+1,2,3,4
+1,2,3,4
+different invocations that'll trigger relinking
+1,2,3,4
+1,2,3,4
+5,6,7,8
+8-7-6-5
+Many levels of call!
+1,2,3,4
+1,2,3,4
+1,2,3,4
+call apply call apply call... a lot
+1,2,3,4
+1,2,3,4
+1,2,3,4
+apply call apply call apply... a lot
+1,2,3,4
+1,2,3,4
+1,2,3,4
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8047035.js
similarity index 74%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8047035.js
index c9182ef..dc44921 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8047035.js
@@ -1,35 +1,37 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8047035: (function() "hello")() crashes in Lexer with jdk9
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+// should not print ")" at the end
+print(function() "hello");
+print(function() '');
+
+// The following should not crash inside lexer
+print((function() '')());
+print((function() "hello")());
diff --git a/nashorn/test/script/basic/JDK-8047035.js.EXPECTED b/nashorn/test/script/basic/JDK-8047035.js.EXPECTED
new file mode 100644
index 0000000..0c4ab07
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047035.js.EXPECTED
@@ -0,0 +1,4 @@
+function() "hello"
+function() ''
+
+hello
diff --git a/nashorn/test/script/basic/JDK-8047057.js b/nashorn/test/script/basic/JDK-8047057.js
new file mode 100644
index 0000000..bd38ee9
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047057.js
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8047057: Add a regression test for the passing test cases from JDK-8042304
+ *
+ * @test
+ * @run
+ */
+
+// commented out makeFuncAndCall calls are still result in crash
+// Tests commented with //** fail only when assertions are turned on
+
+function makeFuncAndCall(code) {
+    Function(code)();
+}
+
+function makeFuncExpectError(code, ErrorType) {
+    try {
+        makeFuncAndCall(code);
+    } catch (e) {
+        if (! (e instanceof ErrorType)) {
+            fail(ErrorType.name + " expected, got " + e);
+        }
+    }
+}
+
+makeFuncAndCall("switch(0) { default: {break;} return }");
+makeFuncAndCall("L: { { break L; } return; }");
+makeFuncAndCall("L: { while(0) break L; return; }");
+makeFuncExpectError("L: {while(0) break L; return [](); }", TypeError);
+makeFuncAndCall("do with({}) break ; while(0);");
+makeFuncAndCall("while(0) with({}) continue ;");
+makeFuncAndCall("eval([]);");
+makeFuncAndCall("try{} finally{[]}");
+makeFuncAndCall("try { } catch(x if 1) { try { } catch(x2) { } }");
+makeFuncAndCall("try { } catch(x if 1) { try { return; } catch(x2) { { } } }");
+makeFuncAndCall("Error() * (false)[-0]--");
+makeFuncAndCall("try { var x = 1, x = null; } finally { }");
+makeFuncAndCall("try { var x = {}, x = []; } catch(x3) { }");
+makeFuncAndCall("[delete this]");
+makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
+makeFuncAndCall("if(eval('', eval('', function() {}))) { }");
+makeFuncAndCall("eval(\"[,,];\", [11,12,13,14].some)");
+makeFuncAndCall("eval(\"1.2e3\", ({})[ /x/ ])");
+makeFuncExpectError("eval(\"x4\", x3);", ReferenceError);
+makeFuncAndCall("with({5.0000000000000000000000: String()}){(false); }");
+makeFuncAndCall("try { var x = undefined, x = 5.0000000000000000000000; } catch(x) { x = undefined; }");
+makeFuncAndCall("(function (x){ x %= this}(false))");
+makeFuncAndCall("eval.apply.apply(function(){ eval('') })");
+makeFuncAndCall("(false % !this) && 0");
+makeFuncAndCall("with({8: 'fafafa'.replace()}){ }");
+makeFuncAndCall("(function (x) '' )(true)");
+makeFuncExpectError("new eval(function(){})", TypeError);
+makeFuncAndCall('eval("23", ({})[/x/])');
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8047067.js
similarity index 67%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8047067.js
index db358d2..2d8f140 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8047067.js
@@ -1,33 +1,36 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8047067: all eval arguments need to be copied in Lower
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+// The second expression triggers optimistic deoptimization, and if not
+// all eval arguments were copied in Lower, we'd end up with duplicate
+// program points that'd cause incorrect continuation program point in
+// the rest-of, and therefore a bad stack, and therefore an AIOOBE in
+// the continuation setup code.
+eval("23", ({})[/x/])
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8047078.js
similarity index 73%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8047078.js
index c9182ef..984e4f2 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8047078.js
@@ -1,35 +1,38 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8047078: ArrayLiteral mutability caused trouble in optimistic types
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+function makeFuncAndCall(code) {
+    Function(code)();
+}
+
+makeFuncAndCall("eval([]);");
+makeFuncAndCall("eval([1]);");
+makeFuncAndCall("eval([1,2,3,,4]);");
+makeFuncAndCall("try{} finally{[]}");
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8047166.js
similarity index 80%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8047166.js
index db358d2..74e3ae5 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8047166.js
@@ -1,33 +1,31 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8047166: 'do with({}) break ; while(0);' crashes in CodeGenerator
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+(function(){do with({}) break ; while(0);})();
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8047357.js
similarity index 77%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8047357.js
index db358d2..17e4d13 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8047357.js
@@ -1,33 +1,32 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8047357: More precise synthetic return + unreachable throw
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+print((function() { switch(0) { default: {var x; break ; } throw x; } })());
+print((function() { switch(0) { default: {break;} return; } })());
diff --git a/nashorn/test/script/basic/JDK-8047357.js.EXPECTED b/nashorn/test/script/basic/JDK-8047357.js.EXPECTED
new file mode 100644
index 0000000..d4f80bf
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047357.js.EXPECTED
@@ -0,0 +1,2 @@
+undefined
+undefined
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8047359.js
similarity index 61%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8047359.js
index c9182ef..812f341 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8047359.js
@@ -1,35 +1,47 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8047359: large string size RangeError should be thrown rather than reporting negative length
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+try {
+    var s = " "; for (var i=0;i<31;++i) s+=s; s.length;
+    throw new Error("should have thrown RangeError!");
+} catch (e) {
+    if (! (e instanceof RangeError)) {
+        fail("RangeError expected, got " + e);
+    }
+}
+
+try {
+    var s = " "; for (var i=0;i<31;++i) s+=s;
+    throw new Error("should have thrown RangeError!");
+} catch (e) {
+    if (! (e instanceof RangeError)) {
+        fail("RangeError expected, got " + e);
+    }
+}
diff --git a/nashorn/test/script/basic/JDK-8047369.js b/nashorn/test/script/basic/JDK-8047369.js
new file mode 100644
index 0000000..e2b0984
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047369.js
@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8047369: Add regression tests for passing test cases of JDK-8024971
+ *
+ * @test
+ * @run
+ * @option -scripting
+ */
+
+function makeFuncAndCall(code) {
+    Function(code)();
+}
+
+function makeFuncExpectError(code, ErrorType) {
+    try {
+        makeFuncAndCall(code);
+    } catch (e) {
+        if (! (e instanceof ErrorType)) {
+            fail(ErrorType.name + " expected, got " + e);
+        }
+    }
+}
+
+function evalExpectError(code, ErrorType) {
+    try {
+        eval(code)();
+    } catch (e) {
+        if (! (e instanceof ErrorType)) {
+            fail(ErrorType.name + " expected, got " + e);
+        }
+    }
+}
+
+function evalExpectValue(code, value) {
+    if (eval(code) != value) {
+        fail("Expected " + value + " with eval of " + code);
+    }
+}
+
+makeFuncAndCall("for(x.x in 0) {}");
+// bug JDK-8047357
+// makeFuncAndCall("switch((null >> x3)) { default: {var x; break ; }\nthrow x; }");
+makeFuncExpectError("switch(x) { case 8: break; case false: }", ReferenceError);
+makeFuncAndCall("try { return true; } finally { return false; } ");
+makeFuncAndCall("({ get 1e81(){} })");
+makeFuncAndCall("{var x, x3;try { return 0; } finally { return 3/0; } }");
+makeFuncExpectError("with(x ? 1e81 : (x2.constructor = 0.1)) {}", ReferenceError);
+makeFuncAndCall("while(x-=1) {var x=0; }");
+makeFuncAndCall("while((x-=false) && 0) { var x = this; }");
+makeFuncAndCall("/*infloop*/while(x4-=x) var x, x4 = x1;");
+makeFuncAndCall("/*infloop*/L:while(x+=null) { this;var x = /x/g ; }");
+makeFuncAndCall("while((x1|=0.1) && 0) { var x1 = -0, functional; }");
+makeFuncAndCall("with({}) return (eval(\"arguments\"));");
+
+evalExpectValue(<<CODE
+    var s = "(function() { return y })()";
+    (function() {
+        with({ y:1 })
+            eval(s)
+    })();
+    (function() {
+        with({
+            get y() { return "get"; }
+        })
+        return eval(s)
+    })();
+CODE, "get");
+
+// bug JDK-8047359
+// evalExpectValue("s = ' '; for (var i=0;i<31;++i) s+=s; s.length", RangeError);
+
+evalExpectValue(<<CODE
+    function f(o) {
+        var eval=0;
+        with({
+            get eval() { return o.eval }
+        })
+        return eval("1+2");
+    }
+    f(this);
+CODE, 3)
+
+evalExpectValue(<<CODE
+    function f() {
+        var a=1,e=2;
+        try {
+            throw 3
+        } catch(e) {
+            return + function g(){return eval('a+e')}()
+        }
+    }
+    f();
+CODE, 4);
+
+//evalExpectValue(
+// "function f(){var a=1; with({get a(){return false}}) return a}; f()", false);
+
+evalExpectError("function public() {\"use strict\"}", SyntaxError);
+evalExpectError("function f(public) {\"use strict\"}", SyntaxError);
+evalExpectError("function f() { switch(x) {} } f()", ReferenceError);
+
+// bug JDK-8047364
+// makeFuncAndCall("L1:try { return } finally { break L1 }");
+
+evalExpectValue(<<CODE
+    function f() {
+        function g() { return 0 }
+        function g() { return 1 }
+        function g$1() { return 2 }
+        return g$1()
+    }
+
+    f();
+CODE, 2);
+
+evalExpectValue(<<CODE
+    function f() {
+        function g() {return 0 }
+        var h = function g() { return 1 };
+        function g$1() { return 2 };
+        return h()
+    }
+
+    f()
+CODE, 1);
+
+evalExpectValue(<<CODE
+    function f() {
+        var obj = { get ":"() {} }
+        var desc = Object.getOwnPropertyDescriptor(obj, ":")
+        return desc.get.name
+    }
+
+    f()
+CODE, ":");
+
+evalExpectValue(<<CODE
+    function f() {
+        var obj = { set ":"(a) {} };
+        var desc = Object.getOwnPropertyDescriptor(obj, ":");
+        return desc.set;
+    }
+
+    f()
+CODE, "set \":\"(a) {}");
+
+// bug JDK-8047366
+// evalExpectValue("(1000000000000000128).toString()", "1000000000000000100");
+// evalExpectValue("(1000000000000000128).toFixed().toString()", "1000000000000000128");
+
+try {
+    Function("-", {
+        toString: function() {
+            throw "err"
+        }
+    })();
+} catch (e) {
+    if (e != "err") {
+        fail("Expected 'err' here, got " + e);
+    }
+}
+evalExpectError("function f() { switch(x) {} } f()", ReferenceError);
+Array.prototype.splice.call(Java.type("java.util.HashMap"))
+Array.prototype.slice.call(Java.type("java.util.HashMap"))
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8047371.js
similarity index 78%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8047371.js
index db358d2..d8fc401 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8047371.js
@@ -1,33 +1,32 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8047371: local variable declaration in TypeEvaluator should use ScriptObject.addOwnProperty instead of .set
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+print((function(){ var a=1; with({ get a() { return false } }) return a })());
 
diff --git a/nashorn/test/script/basic/JDK-8047371.js.EXPECTED b/nashorn/test/script/basic/JDK-8047371.js.EXPECTED
new file mode 100644
index 0000000..c508d53
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047371.js.EXPECTED
@@ -0,0 +1 @@
+false
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8047728.js
similarity index 63%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8047728.js
index db358d2..ba7b033 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8047728.js
@@ -1,33 +1,54 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8047728: (function(x){var o={x:0}; with(o){delete x} return o.x})() evaluates to 0 instead of undefined
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+function func(x) {
+    var o = {x:0};
+    with(o){
+       delete x;
+    }
+    return o.x
+}
 
+if (typeof func() != 'undefined') {
+    fail("expected undefined from 'func' call");
+}
+
+function func2() {
+    var x;
+    var o = {x:0};
+    with(o){
+       delete x;
+    }
+    return o.x
+}
+
+if (typeof func2() != 'undefined') {
+    fail("expected undefined from 'func2' call");
+}
diff --git a/nashorn/test/script/basic/JDK-8047959.js b/nashorn/test/script/basic/JDK-8047959.js
new file mode 100644
index 0000000..179fb88
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047959.js
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8047959: bindings created for declarations in eval code are not mutable
+ *
+ * @test
+ * @run
+ */
+
+eval("var x=10;");
+print('delete x? ' + delete x);
+print('typeof x = ' + typeof x);
+
+eval("function f() {}");
+print('delete f? ' + delete f);
+print('typeof f = ' + typeof f);
+
+var foo = 223;
+print('delete foo? ' + delete foo);
+print('typeof foo = ' + typeof foo);
+
+function func() {}
+print('delete func? ' + delete func);
+print('typeof func = ' + typeof func);
+
+eval("var foo = 33;");
+print("delete foo? " + delete foo);
+print("typeof foo? " + typeof foo);
+print("foo = " + foo);
+
+var x = "global";
+(function(){
+    eval("var x='local'");
+    print("x in function = "+ x);
+    print("delete x? = " + delete x);
+    print("x after delete = " + x);
+})();
+print("x = " + x);
diff --git a/nashorn/test/script/basic/JDK-8047959.js.EXPECTED b/nashorn/test/script/basic/JDK-8047959.js.EXPECTED
new file mode 100644
index 0000000..935f100
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8047959.js.EXPECTED
@@ -0,0 +1,15 @@
+delete x? false
+typeof x = number
+delete f? true
+typeof f = undefined
+delete foo? false
+typeof foo = number
+delete func? false
+typeof func = function
+delete foo? false
+typeof foo? number
+foo = 33
+x in function = local
+delete x? = true
+x after delete = global
+x = global
diff --git a/nashorn/test/script/basic/JDK-8048071.js b/nashorn/test/script/basic/JDK-8048071.js
new file mode 100644
index 0000000..aec0c7c
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8048071.js
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8048071: eval within 'with' statement does not use correct scope if with scope expression has a copy of eval
+ *
+ * @test
+ * @run
+ */
+
+function func() {
+   var x = 1;
+   with ({ eval: this.eval }) {
+      eval("var x = 23");
+   }
+
+   return x;
+}
+
+print(func());
+print("typeof x? " + typeof x);
+
+print((function(global){
+    var x = 1;
+    with(global) {
+        eval("eval('var x=0')");
+    }
+    return x;
+})(this));
+print("typeof x? " + typeof x);
+
+print((function(global){
+   var x = 1;
+   with({eval:  global.eval}) {
+       eval("eval('var x=0')");
+   }
+   return x;
+})(this));
+print("typeof x? " + typeof x);
+
+// not-builtin eval cases
+
+(function () {
+   function eval(str) {
+      print("local eval called: " + str);
+      print(this);
+   }
+
+   with({}) {
+     eval("hello");
+   }
+})();
+
+(function () {
+   with({
+    eval:function(str) {
+       print("with's eval called: " + str);
+       print("this = " + this);
+       print("this.foo = " + this.foo);
+    },
+    foo: 42
+   }) {
+     eval("hello")
+   }
+})();
diff --git a/nashorn/test/script/basic/JDK-8048071.js.EXPECTED b/nashorn/test/script/basic/JDK-8048071.js.EXPECTED
new file mode 100644
index 0000000..5234bb1
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8048071.js.EXPECTED
@@ -0,0 +1,11 @@
+23
+typeof x? undefined
+0
+typeof x? undefined
+0
+typeof x? undefined
+local eval called: hello
+[object global]
+with's eval called: hello
+this = [object Object]
+this.foo = 42
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8048079_1.js
similarity index 76%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8048079_1.js
index db358d2..36a1fe6 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8048079_1.js
@@ -1,33 +1,35 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8048079: Persistent code store is broken after optimistic types merge
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
  */
 
-load(__DIR__ + "runsunspider.js");
-
+load(__DIR__ + 'prototype.js');
+load(__DIR__ + 'yui.js');
diff --git a/nashorn/test/script/basic/JDK-8048079_1.js.EXPECTED b/nashorn/test/script/basic/JDK-8048079_1.js.EXPECTED
new file mode 100644
index 0000000..371f63a
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8048079_1.js.EXPECTED
@@ -0,0 +1,3 @@
+parsed and compiled ok prototype.js
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8048079_2.js
similarity index 76%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8048079_2.js
index db358d2..36a1fe6 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8048079_2.js
@@ -1,33 +1,35 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8048079: Persistent code store is broken after optimistic types merge
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
+ * @option -pcc
+ * @option -Dnashorn.persistent.code.cache=build/nashorn_code_cache
+ * @fork
  */
 
-load(__DIR__ + "runsunspider.js");
-
+load(__DIR__ + 'prototype.js');
+load(__DIR__ + 'yui.js');
diff --git a/nashorn/test/script/basic/JDK-8048079_2.js.EXPECTED b/nashorn/test/script/basic/JDK-8048079_2.js.EXPECTED
new file mode 100644
index 0000000..371f63a
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8048079_2.js.EXPECTED
@@ -0,0 +1,3 @@
+parsed and compiled ok prototype.js
+parsed and compiled ok yui-min.js
+parsed and compiled ok yui.js
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8048505.js
similarity index 64%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8048505.js
index c9182ef..4ee8fe1 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8048505.js
@@ -1,35 +1,52 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * Read fully parameter test
  *
  * @test
+ * @option -scripting
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var str = __FILE__;
+var first = readFully(str);
+print(typeof str);
+
+var str2 = __FILE__.substring(0,5);
+var str3 = __FILE__.substring(5);
+print(typeof str2);
+print(typeof str3);
+
+var cons = str2 + str3;
+print(typeof cons);
+
+var second = readFully(cons);
+
+var f = new java.io.File(str);
+print(typeof f);
+var third = readFully(f);
+
+print(first.length() == second.length());
+print(first.length() == third.length());
+
diff --git a/nashorn/test/script/basic/JDK-8048505.js.EXPECTED b/nashorn/test/script/basic/JDK-8048505.js.EXPECTED
new file mode 100644
index 0000000..ed5daae
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8048505.js.EXPECTED
@@ -0,0 +1,7 @@
+string
+string
+string
+string
+object
+true
+true
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8048586.js
similarity index 76%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8048586.js
index c9182ef..a55299a 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8048586.js
@@ -1,35 +1,41 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8048586: String concatenation with optimistic types is slow
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var body = '';
+
+for (var i = 0; i < 1024 * 1024; i++) {
+  body += 'hello world\n';
+}
+
+body = '';
+
+for (var i = 0; i < 1024 * 1024; i++) {
+  body = body + 'hello world\n';
+}
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8048718.js
similarity index 64%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8048718.js
index c9182ef..08b0e3f8 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8048718.js
@@ -1,35 +1,52 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8048718: JSON.parse('{"0":0, "64":0}') throws ArrayindexOutOfBoundsException
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var obj = JSON.parse('{"0":0, "64":0}');
+if ("1" in obj) {
+    fail("found element at index 1");
+}
+
+if ("63" in obj) {
+    fail("found element at index 63");
+}
+
+if (obj[0] != 0) {
+    fail("expected obj[0] to be 0");
+}
+
+if (obj[64] != 0) {
+    fail("expected obj[64] to be 0");
+}
+
+for (var i in obj) {
+    if (i != "0" && i != "64") {
+        fail("invalid property " + i);
+    }
+}
diff --git a/nashorn/test/script/basic/JDK-8049086.js b/nashorn/test/script/basic/JDK-8049086.js
new file mode 100644
index 0000000..da4a962
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8049086.js
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8049086: Minor API convenience functions on "Java" object
+ *
+ * @test
+ * @run
+ */
+
+var System = Java.type("java.lang.System");
+var out = System.out;
+var println = out.println;
+var getProperty = System.getProperty;
+var File = Java.type("java.io.File")["(String)"];
+
+print("println is java method? " + Java.isJavaMethod(println));
+print("println is script function? " + Java.isScriptFunction(println));
+print("getProperty is java method? " + Java.isJavaMethod(getProperty));
+print("getProperty is script function? " + Java.isScriptFunction(getProperty));
+print("File is java method? " + Java.isJavaMethod(File));
+print("File is script function? " + Java.isScriptFunction(File));
+
+print("eval is script function? " + Java.isScriptFunction(eval));
+print("eval is java method? " + Java.isJavaMethod(eval));
+function hello() {}
+print("hello is script function? " + Java.isScriptFunction(hello));
+print("hello is java method? " + Java.isJavaMethod(hello));
+
+print("out is script object? " + Java.isScriptObject(out));
+print("System is script object? " + Java.isScriptObject(System));
+print("Object is script object? " + Java.isScriptObject(Object));
+print("{} is script object? " + Java.isScriptObject({}));
+print("/foo/ is script object? " + Java.isScriptObject(/foo/));
+
+// Java function is anything whose 'typeof' is 'function' but it is not
+// a script function! This includes:
+// (a) Java methods (b) Java classes (as these respond to new)
+// (c) FunctionalInterface objects (d) JSObjects that are 'functions'
+
+print("java.awt.Color is java function? " + Java.isJavaFunction(java.awt.Color));
+print("java.lang.Runnable instance is java function? "
+    + Java.isJavaFunction(new java.lang.Runnable(function() {})));
+print("eval is java function? " + Java.isJavaFunction(eval));
+print("println is java function? " + Java.isJavaFunction(println));
+print("getProperty is java function? " + Java.isJavaFunction(getProperty));
+
+var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject");
+print("callable JSObject is function? " +
+    Java.isJavaFunction(new JSObject() {
+        isFunction: function() true,
+        call: function() {}
+    })
+);
+
+print("Non callable JSObject is function? " +
+    Java.isJavaFunction(new JSObject() {
+        isFunction: function() false,
+    })
+);
+
+// synchronized function
+var lock = new java.lang.Object();
+
+print("lock is java object? " + Java.isJavaObject(lock));
+print("eval is java object? " + Java.isJavaObject(eval));
+print("{} is java object? " + Java.isJavaObject({}));
+print("/foo/ is java object? " + Java.isJavaObject(/foo/));
+print("[] is java object? " + Java.isJavaObject([]));
+print("java.io.File is java object? " + Java.isJavaObject(java.io.File));
+
+// synchornized function checks
+Java.synchronized(function() {
+    var th = new java.lang.Thread(Java.synchronized(function() {
+        print("new thread");
+        print("notifying..");
+        lock.notifyAll();
+    }, lock));
+    th.start();
+    print("about to wait..");
+    lock.wait();
+    th.join();
+    print("done waiting!");
+}, lock)();
+
+// try Mozilla "sync" as well
+load("nashorn:mozilla_compat.js");
+sync(function() {
+    var th = new java.lang.Thread(sync(function() {
+        print("new thread");
+        print("notifying..");
+        lock.notifyAll();
+    }, lock));
+    th.start();
+    print("about to wait..");
+    lock.wait();
+    th.join();
+    print("done waiting!");
+}, lock)();
+
+function expectTypeError(func) {
+    try {
+        func();
+        throw new Error("should have thrown TypeError");
+    } catch (e) {
+        if (! (e instanceof TypeError)) {
+            fail("Expected TypeError, got " +e);
+        }
+        print(e);
+    }
+}
+
+expectTypeError(function() Java.synchronized(232));
+expectTypeError(function() sync(232));
+expectTypeError(function() Java.synchronized({}));
+expectTypeError(function() sync({}));
+expectTypeError(function() Java.synchronized([]));
+expectTypeError(function() sync([]));
+expectTypeError(function() Java.synchronized("hello"));
+expectTypeError(function() sync("hello"));
+expectTypeError(function() Java.synchronized(null));
+expectTypeError(function() sync(null));
+expectTypeError(function() Java.synchronized(undefined));
+expectTypeError(function() sync(undefined));
diff --git a/nashorn/test/script/basic/JDK-8049086.js.EXPECTED b/nashorn/test/script/basic/JDK-8049086.js.EXPECTED
new file mode 100644
index 0000000..d67db5d
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8049086.js.EXPECTED
@@ -0,0 +1,48 @@
+println is java method? true
+println is script function? false
+getProperty is java method? true
+getProperty is script function? false
+File is java method? true
+File is script function? false
+eval is script function? true
+eval is java method? false
+hello is script function? true
+hello is java method? false
+out is script object? false
+System is script object? false
+Object is script object? true
+{} is script object? true
+/foo/ is script object? true
+java.awt.Color is java function? true
+java.lang.Runnable instance is java function? true
+eval is java function? false
+println is java function? true
+getProperty is java function? true
+callable JSObject is function? true
+Non callable JSObject is function? false
+lock is java object? true
+eval is java object? false
+{} is java object? false
+/foo/ is java object? false
+[] is java object? false
+java.io.File is java object? true
+about to wait..
+new thread
+notifying..
+done waiting!
+about to wait..
+new thread
+notifying..
+done waiting!
+TypeError: 232 is not a function
+TypeError: 232 is not a function
+TypeError: [object Object] is not a function
+TypeError: [object Object] is not a function
+TypeError: [object Array] is not a function
+TypeError: [object Array] is not a function
+TypeError: hello is not a function
+TypeError: hello is not a function
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: undefined is not a function
+TypeError: undefined is not a function
diff --git a/nashorn/test/script/basic/JDK-8049242.js b/nashorn/test/script/basic/JDK-8049242.js
new file mode 100644
index 0000000..3e803b3
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8049242.js
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8049242: Explicit constructor overload selection should work with StaticClass as well
+ *
+ * @test
+ * @run
+ */
+
+// call explicit constructor
+print(new (Java.type("java.awt.Color")["(int,int,int)"])(255,0,255));
+// print the constructor itself
+print(Java.type("java.awt.Color")["(int,int,int)"]);
+
+// store constructor to call later
+var Color = Java.type("java.awt.Color")["(int,int,int)"];
+// call stored constructor
+print(new Color(33, 233, 2))
+
+// check if default constructor works
+var obj = new (Java.type("java.lang.Object")["()"])();
+if (obj.class != Java.type("java.lang.Object").class) {
+    fail("obj is a java.lang.Object");
+}
+
+// expected failure cases.
+function checkIt(func) {
+    try {
+        func();
+        throw new Error("should have thrown TypeError");
+    } catch(e) {
+        if (! (e instanceof TypeError)) {
+            fail("Expected TypeError, got " + e);
+        }
+        print(e);
+    }
+}
+
+// garbage signature string
+checkIt(function() new (Java.type("java.lang.Object")["()xxxxx"])());
+checkIt(function() new (Java.type("java.lang.Object")["("])());
+checkIt(function() new (Java.type("java.lang.Object")[")"])());
+
+// call constructor as normal method (without 'new')
+checkIt(function() Color());
+
+// try constructor on interface
+checkIt(function() new (Java.type("java.lang.Runnable"))["()"]);
+checkIt(function() new (Java.type("java.lang.Runnable"))["(int)"]);
+
+// try constructor on abstrace class
+try {
+    new (Java.type("java.io.InputStream"))["()"];
+    throw new Error("should have thrown exception!");
+} catch (e) {
+    print(e);
+}
diff --git a/nashorn/test/script/basic/JDK-8049242.js.EXPECTED b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED
new file mode 100644
index 0000000..4aa4627
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8049242.js.EXPECTED
@@ -0,0 +1,10 @@
+java.awt.Color[r=255,g=0,b=255]
+[jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)]
+java.awt.Color[r=33,g=233,b=2]
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: null is not a function
+TypeError: Constructor [jdk.internal.dynalink.beans.SimpleDynamicMethod Color java.awt.Color.java.awt.Color(int,int,int)] requires new.
+TypeError: null is not a function
+TypeError: null is not a function
+java.lang.InstantiationException: java.io.InputStream
diff --git a/nashorn/test/script/maptests/property_delete.js b/nashorn/test/script/basic/JDK-8050432.js
similarity index 63%
copy from nashorn/test/script/maptests/property_delete.js
copy to nashorn/test/script/basic/JDK-8050432.js
index e2824dd..46d22cf 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/nashorn/test/script/basic/JDK-8050432.js
@@ -1,48 +1,40 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
+ * JDK-8050432: javax.script.filename variable should not be enumerable with nashorn engine's ENGINE_SCOPE bindings
+ *
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @run
  */
 
-load(__DIR__ + "maputil.js");
+var ScriptEngine = javax.script.ScriptEngine;
+var m = new javax.script.ScriptEngineManager();
+var engine = m.getEngineByName("nashorn");
 
-function Foo() {
-    this.x = 33;
+engine.put(ScriptEngine.FILENAME, "foo");
+var desc = engine.eval("Object.getOwnPropertyDescriptor(this, '"
+   + ScriptEngine.FILENAME + "')");
+if (desc.enumerable) {
+    fail(ScriptEngine.FILENAME + " is enumerable");
 }
-
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
-}
-deleteX(obj1);
-deleteX(obj2);
-
-assertSameMap(obj1, obj2);
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8051439.js
similarity index 68%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8051439.js
index db358d2..255803d 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8051439.js
@@ -1,33 +1,52 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8051439: Wrong type calculated for ADD operator with undefined operand
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+// Test + operator
+function f1() {
+    var x;
+    for (var i = 0;i < 3; i++) {
+        x = x + i;
+    }
+    x = x + "test";
+    return x;
+}
 
+// Test += operator
+function f2() {
+    var x;
+    for (var i = 0;i < 3; i++) {
+        x += i;
+    }
+    x += "test";
+    return x;
+}
+
+print(f1());
+print(f2());
diff --git a/nashorn/test/script/basic/JDK-8051439.js.EXPECTED b/nashorn/test/script/basic/JDK-8051439.js.EXPECTED
new file mode 100644
index 0000000..5c0f70f
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8051439.js.EXPECTED
@@ -0,0 +1,2 @@
+NaNtest
+NaNtest
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8054503.js
similarity index 64%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8054503.js
index c9182ef..d11c6cd 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8054503.js
@@ -1,35 +1,50 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * 8054503: test/script/external/test262/test/suite/ch12/12.6/12.6.4/12.6.4-2.js fails with tip
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+function MyFunc() {}
+
+MyFunc.prototype.foo = 42;
+var obj = new MyFunc();
+Object.defineProperty(obj, "foo", {
+    value: "hello",
+    enumerable: false
+});
+
+for (var p in obj) {
+    if (p == "foo") {
+        fail("'foo' is not expected here!");
+    }
+}
+
+for each (var p in obj) {
+    if (p == "hello" || p == 42) {
+        fail("'foo' value is not expected here");
+    }
+}
diff --git a/nashorn/test/script/basic/JDK-8055762.js b/nashorn/test/script/basic/JDK-8055762.js
new file mode 100644
index 0000000..e772a57
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8055762.js
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8055762: Nashorn misses linker for netscape.javascript.JSObject instances
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// basic checks for special linkage for netscape.javascript.JSObject
+// instances. For this test, we just subclass that class rather than
+// involve actual browser script engine or javafx webkit objects.
+
+function main() {
+    var JSObject;
+    try {
+        JSObject = Java.type("netscape.javascript.JSObject");
+    } catch (e) {
+        if (e instanceof java.lang.ClassNotFoundException) {
+            // pass vacuously by emitting the .EXPECTED file content
+            var str = readFully(__DIR__ + "JDK-8055762.js.EXPECTED");
+            print(str.substring(0, str.length - 1));
+            return;
+        } else{
+            fail("unexpected exception for JSObject", e);
+        }
+    }
+    test(JSObject);
+}
+
+function test(JSObject) {
+    var obj = new (Java.extend(JSObject))() {
+        getMember: function(name) {
+            if (name == "func") {
+                return function(arg) {
+                    print("func called with " + arg);
+                }
+            }
+            return name.toUpperCase();
+        },
+
+        getSlot: function(index) {
+            return index^2;
+        },
+
+        setMember: function(name, value) {
+            print(name + " set to " + value);
+        },
+
+        setSlot: function(index, value) {
+            print("[" + index + "] set to " + value);
+        }
+    };
+
+    print(obj["foo"]);
+    print(obj[2]);
+    obj.bar = 23;
+    obj[3] = 23;
+    obj.func("hello");
+}
+
+main();
diff --git a/nashorn/test/script/basic/JDK-8055762.js.EXPECTED b/nashorn/test/script/basic/JDK-8055762.js.EXPECTED
new file mode 100644
index 0000000..51a0201
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8055762.js.EXPECTED
@@ -0,0 +1,5 @@
+FOO
+0
+bar set to 23
+[3] set to 23
+func called with hello
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/JDK-8055796.js
similarity index 65%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/JDK-8055796.js
index c9182ef..6728ff7 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/JDK-8055796.js
@@ -1,35 +1,37 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * JDK-8055796: JSObject and browser JSObject linkers should provide fallback to call underlying Java methods directly
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var m = new javax.script.ScriptEngineManager();
+var e = m.getEngineByName("nashorn");
+var jsobj = e.eval("({ foo: 33, valueOf: function() 42 })");
+
+print("foo =", jsobj['getMember(java.lang.String)']("foo"));
+print("eval =", jsobj['eval(String)']("this + 44"));
+print("valueOf function? =", (jsobj.valueOf)['isFunction()']());
diff --git a/nashorn/test/script/basic/JDK-8055796.js.EXPECTED b/nashorn/test/script/basic/JDK-8055796.js.EXPECTED
new file mode 100644
index 0000000..6ea4592
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8055796.js.EXPECTED
@@ -0,0 +1,3 @@
+foo = 33
+eval = 86
+valueOf function? = true
diff --git a/nashorn/test/script/basic/JDK-8055796_2.js b/nashorn/test/script/basic/JDK-8055796_2.js
new file mode 100644
index 0000000..d547a0a
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8055796_2.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8055796: JSObject and browser JSObject linkers should provide fallback to call underlying Java methods directly
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+function main() {
+    var JSObject;
+    try {
+        JSObject = Java.type("netscape.javascript.JSObject");
+    } catch (e) {
+        if (e instanceof java.lang.ClassNotFoundException) {
+            // pass vacuously by emitting the .EXPECTED file content
+            var str = readFully(__DIR__ + "JDK-8055796_2.js.EXPECTED");
+            print(str.substring(0, str.length - 1));
+            return;
+        } else {
+            fail("unexpected exception on JSObject", e);
+        }
+    }
+    test(JSObject);
+}
+
+function test(JSObject) {
+    var bjsobj = new (Java.extend(JSObject))() {
+        getMember: function(name) {
+            if (name == "func") {
+                return function(arg) {
+                    print("func called with " + arg);
+                }
+            }
+            return name.toUpperCase();
+        },
+
+        getSlot: function(index) {
+            return index*index;
+        },
+
+        setMember: function(name, value) {
+            print(name + " set to " + value);
+        },
+
+        setSlot: function(index, value) {
+            print("[" + index + "] set to " + value);
+        }
+    };
+
+    print("getMember('foo') =", bjsobj['getMember(String)']('foo'));
+    print("getSlot(6) =", bjsobj['getSlot(int)'](6));
+    bjsobj['setMember(String, Object)']('bar', 'hello');
+    bjsobj['setSlot(int, Object)'](10, 42);
+}
+
+main();
diff --git a/nashorn/test/script/basic/JDK-8055796_2.js.EXPECTED b/nashorn/test/script/basic/JDK-8055796_2.js.EXPECTED
new file mode 100644
index 0000000..dbb3756
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8055796_2.js.EXPECTED
@@ -0,0 +1,4 @@
+getMember('foo') = FOO
+getSlot(6) = 36
+bar set to hello
+[10] set to 42
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/JDK-8055870.js
similarity index 80%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/JDK-8055870.js
index db358d2..dc30840 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/JDK-8055870.js
@@ -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
@@ -22,12 +22,20 @@
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * JDK-8055870: iteration fails if index var is not used
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+function isEmpty2(v) {
+ for (var k in v) {
+   return false;
+ }
+ return true;
+}
+
+x = {test: 'test'}
+
+print(isEmpty2(x))
 
diff --git a/nashorn/test/script/basic/JDK-8055870.js.EXPECTED b/nashorn/test/script/basic/JDK-8055870.js.EXPECTED
new file mode 100644
index 0000000..c508d53
--- /dev/null
+++ b/nashorn/test/script/basic/JDK-8055870.js.EXPECTED
@@ -0,0 +1 @@
+false
diff --git a/nashorn/test/script/maptests/property_delete.js b/nashorn/test/script/basic/JDK-8056123.js
similarity index 64%
copy from nashorn/test/script/maptests/property_delete.js
copy to nashorn/test/script/basic/JDK-8056123.js
index e2824dd..08b2a6b6 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/nashorn/test/script/basic/JDK-8056123.js
@@ -1,48 +1,45 @@
 /*
- * Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
+ * JDK-8056123: Anonymous function statements leak internal function names into global scope
+ *
  * @test
- * @option -Dnashorn.debug=true
- * @fork
+ * @run
  */
 
-load(__DIR__ + "maputil.js");
-
-function Foo() {
-    this.x = 33;
+// do *not* introduce newlines before this line!
+function () { // line 32
+  print("hello function!");
 }
 
-var obj1 = new Foo();
-var obj2 = new Foo();
-
-assertSameMap(obj1, obj2);
-
-// property deletion at same callsite
-function deleteX(obj) {
-   delete obj.x;
+if (typeof this["L:32"] != 'undefined') {
+   fail("anonymous function statement leaks name in global");
 }
-deleteX(obj1);
-deleteX(obj2);
 
-assertSameMap(obj1, obj2);
+var keys = Object.keys(this);
+for (var i in keys) {
+    if (keys[i].contains("L:")) {
+        fail("found " + keys[i] + " in global scope");
+    }
+}
diff --git a/nashorn/test/script/basic/JDK_8005848.js b/nashorn/test/script/basic/JDK_8005848.js
index d2d07ea..6df6768 100644
--- a/nashorn/test/script/basic/JDK_8005848.js
+++ b/nashorn/test/script/basic/JDK_8005848.js
@@ -22,7 +22,7 @@
  */
 
 /**
- * JDK-8005848 : assigning to global toString variable affects Object.prototype.toString 
+ * JDK-8005848 : assigning to global toString variable affects Object.prototype.toString
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/NASHORN-100.js b/nashorn/test/script/basic/NASHORN-100.js
index df81284..2b10a4d 100644
--- a/nashorn/test/script/basic/NASHORN-100.js
+++ b/nashorn/test/script/basic/NASHORN-100.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-101.js b/nashorn/test/script/basic/NASHORN-101.js
index 4e83a99..c9a551b 100644
--- a/nashorn/test/script/basic/NASHORN-101.js
+++ b/nashorn/test/script/basic/NASHORN-101.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-102.js b/nashorn/test/script/basic/NASHORN-102.js
index cc388dd..25805b6 100644
--- a/nashorn/test/script/basic/NASHORN-102.js
+++ b/nashorn/test/script/basic/NASHORN-102.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-103.js b/nashorn/test/script/basic/NASHORN-103.js
index ddce596..5c51130 100644
--- a/nashorn/test/script/basic/NASHORN-103.js
+++ b/nashorn/test/script/basic/NASHORN-103.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-104.js b/nashorn/test/script/basic/NASHORN-104.js
index c97b6bc..1393388 100644
--- a/nashorn/test/script/basic/NASHORN-104.js
+++ b/nashorn/test/script/basic/NASHORN-104.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-105.js b/nashorn/test/script/basic/NASHORN-105.js
index f26710d..f6d1f14 100644
--- a/nashorn/test/script/basic/NASHORN-105.js
+++ b/nashorn/test/script/basic/NASHORN-105.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-105 :  parseFloat function is not spec. compliant.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-106.js b/nashorn/test/script/basic/NASHORN-106.js
index e5a9c61..585f133 100644
--- a/nashorn/test/script/basic/NASHORN-106.js
+++ b/nashorn/test/script/basic/NASHORN-106.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-107.js b/nashorn/test/script/basic/NASHORN-107.js
index 2aeb5dc..6bcbe1a 100644
--- a/nashorn/test/script/basic/NASHORN-107.js
+++ b/nashorn/test/script/basic/NASHORN-107.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-108.js b/nashorn/test/script/basic/NASHORN-108.js
index e12096b..419d1e0 100644
--- a/nashorn/test/script/basic/NASHORN-108.js
+++ b/nashorn/test/script/basic/NASHORN-108.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-109.js b/nashorn/test/script/basic/NASHORN-109.js
index 4667feb..bb6f08a 100644
--- a/nashorn/test/script/basic/NASHORN-109.js
+++ b/nashorn/test/script/basic/NASHORN-109.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-11.js b/nashorn/test/script/basic/NASHORN-11.js
index ca8565f..5209b2a 100644
--- a/nashorn/test/script/basic/NASHORN-11.js
+++ b/nashorn/test/script/basic/NASHORN-11.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-111.js b/nashorn/test/script/basic/NASHORN-111.js
index 4b8347c..6b6d311 100644
--- a/nashorn/test/script/basic/NASHORN-111.js
+++ b/nashorn/test/script/basic/NASHORN-111.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,7 +31,7 @@
 try {
     throw new TypeError("type error");
 } catch (e) {
-    // This used to throw ClassCastException 
+    // This used to throw ClassCastException
     // ThrowException cannot be cast to ScriptObject
     print(JSON.stringify(e));
 }
diff --git a/nashorn/test/script/basic/NASHORN-113.js b/nashorn/test/script/basic/NASHORN-113.js
index d90d1fb..1421ed8 100644
--- a/nashorn/test/script/basic/NASHORN-113.js
+++ b/nashorn/test/script/basic/NASHORN-113.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-114.js b/nashorn/test/script/basic/NASHORN-114.js
index 0326921..e84cccf 100644
--- a/nashorn/test/script/basic/NASHORN-114.js
+++ b/nashorn/test/script/basic/NASHORN-114.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-115.js b/nashorn/test/script/basic/NASHORN-115.js
index 924a9a2..1863716 100644
--- a/nashorn/test/script/basic/NASHORN-115.js
+++ b/nashorn/test/script/basic/NASHORN-115.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-117.js b/nashorn/test/script/basic/NASHORN-117.js
index 9436150..11aa3e4 100644
--- a/nashorn/test/script/basic/NASHORN-117.js
+++ b/nashorn/test/script/basic/NASHORN-117.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-// The following code results in StackOverflowError 
+// The following code results in StackOverflowError
 
 var i0 = "";
 var o0 = "";
diff --git a/nashorn/test/script/basic/NASHORN-118.js b/nashorn/test/script/basic/NASHORN-118.js
index d12d861..641e80e 100644
--- a/nashorn/test/script/basic/NASHORN-118.js
+++ b/nashorn/test/script/basic/NASHORN-118.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * NASHORN-118 :  Function.prototype.apply should accept "arguments" object 
+ * NASHORN-118 :  Function.prototype.apply should accept "arguments" object
  * of another function as second argument.
  *
  * @test
diff --git a/nashorn/test/script/basic/NASHORN-119.js b/nashorn/test/script/basic/NASHORN-119.js
index c957cdf..e543600 100644
--- a/nashorn/test/script/basic/NASHORN-119.js
+++ b/nashorn/test/script/basic/NASHORN-119.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-12.js b/nashorn/test/script/basic/NASHORN-12.js
index ed04d62..95a9e59 100644
--- a/nashorn/test/script/basic/NASHORN-12.js
+++ b/nashorn/test/script/basic/NASHORN-12.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-120.js b/nashorn/test/script/basic/NASHORN-120.js
index b424f3e..2881bc0 100644
--- a/nashorn/test/script/basic/NASHORN-120.js
+++ b/nashorn/test/script/basic/NASHORN-120.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-122.js b/nashorn/test/script/basic/NASHORN-122.js
index a8863a9..08ad77b 100644
--- a/nashorn/test/script/basic/NASHORN-122.js
+++ b/nashorn/test/script/basic/NASHORN-122.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-126.js b/nashorn/test/script/basic/NASHORN-126.js
index dc3f3b3..bd2b621 100644
--- a/nashorn/test/script/basic/NASHORN-126.js
+++ b/nashorn/test/script/basic/NASHORN-126.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -26,9 +26,9 @@
  *
  * @test
  * @run
- */ 
+ */
 
 print(String(1000000000000000000000) === "1e+21");
 print(String(0.000000000100000000000) === "1e-10");
 
-    
+
diff --git a/nashorn/test/script/basic/NASHORN-127.js b/nashorn/test/script/basic/NASHORN-127.js
index 3cd64d2..547b8e0 100644
--- a/nashorn/test/script/basic/NASHORN-127.js
+++ b/nashorn/test/script/basic/NASHORN-127.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,11 +29,11 @@
  */
 
 try {
-    try { 
+    try {
         throw ReferenceError(17);
-    } catch (e) { 
-        print(e); 
-        throw TypeError(4711); 
+    } catch (e) {
+        print(e);
+        throw TypeError(4711);
     }
-} catch (e) { print(e); 
+} catch (e) { print(e);
 }
diff --git a/nashorn/test/script/basic/NASHORN-130.js b/nashorn/test/script/basic/NASHORN-130.js
index 64f275c..3232794 100644
--- a/nashorn/test/script/basic/NASHORN-130.js
+++ b/nashorn/test/script/basic/NASHORN-130.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-132.js b/nashorn/test/script/basic/NASHORN-132.js
index f8ad281..dcb167c 100644
--- a/nashorn/test/script/basic/NASHORN-132.js
+++ b/nashorn/test/script/basic/NASHORN-132.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-133.js b/nashorn/test/script/basic/NASHORN-133.js
index f4ddbe6..80d2e88 100644
--- a/nashorn/test/script/basic/NASHORN-133.js
+++ b/nashorn/test/script/basic/NASHORN-133.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-135.js b/nashorn/test/script/basic/NASHORN-135.js
index 6ffff06..8f6fe3b 100644
--- a/nashorn/test/script/basic/NASHORN-135.js
+++ b/nashorn/test/script/basic/NASHORN-135.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-136.js b/nashorn/test/script/basic/NASHORN-136.js
index 473a3e1..f896e4d 100644
--- a/nashorn/test/script/basic/NASHORN-136.js
+++ b/nashorn/test/script/basic/NASHORN-136.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
     valueOf: function() {
         print("obj1.valueOf");
         return 1;
-    }, 
+    },
 
     toString: function() {
         print("obj1.toString");
diff --git a/nashorn/test/script/basic/NASHORN-14.js b/nashorn/test/script/basic/NASHORN-14.js
index 83a0a07..02ddc58 100644
--- a/nashorn/test/script/basic/NASHORN-14.js
+++ b/nashorn/test/script/basic/NASHORN-14.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
  */
 
 
-function callback() { 
+function callback() {
     print('callback with args ' + Array.prototype.join.apply(arguments))
 }
 
diff --git a/nashorn/test/script/basic/NASHORN-148.js b/nashorn/test/script/basic/NASHORN-148.js
index 398b09d..542ab64 100644
--- a/nashorn/test/script/basic/NASHORN-148.js
+++ b/nashorn/test/script/basic/NASHORN-148.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,13 +23,13 @@
 
 /**
  * NASHORN-148 :  arguments element deletion/resurrection does not work as expected
- * 
+ *
  * @test
  * @run
  */
 
 
-function func(x) { 
+function func(x) {
     print("func.x = " + x);
     print("func.arguments[0] = " + arguments[0]);
 
@@ -43,7 +43,7 @@
     print("func.arguments[0] = " + arguments[0]);
 
     // delete arguments[0]
-    delete arguments[0]; 
+    delete arguments[0];
     print("func.x = " + x);
     print("func.arguments[0] = " + arguments[0]);
 
diff --git a/nashorn/test/script/basic/NASHORN-15.js b/nashorn/test/script/basic/NASHORN-15.js
index 895fac6..d8bdeb6 100644
--- a/nashorn/test/script/basic/NASHORN-15.js
+++ b/nashorn/test/script/basic/NASHORN-15.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-153.js b/nashorn/test/script/basic/NASHORN-153.js
index e38c3e1..f375acd 100644
--- a/nashorn/test/script/basic/NASHORN-153.js
+++ b/nashorn/test/script/basic/NASHORN-153.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-156.js b/nashorn/test/script/basic/NASHORN-156.js
index 6a111e9..7cf19f2 100644
--- a/nashorn/test/script/basic/NASHORN-156.js
+++ b/nashorn/test/script/basic/NASHORN-156.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,8 +29,8 @@
  * @run
  */
 
-var obj = { 
-    get foo() { return 3; } 
+var obj = {
+    get foo() { return 3; }
 };
 
 if (obj.foo != 3) {
diff --git a/nashorn/test/script/basic/NASHORN-157.js b/nashorn/test/script/basic/NASHORN-157.js
index 1908d38..316b96c 100644
--- a/nashorn/test/script/basic/NASHORN-157.js
+++ b/nashorn/test/script/basic/NASHORN-157.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-try { 
+try {
     print((x, 1));
     fail("#1 ReferenceError should have been thrown");
 } catch (e) {
diff --git a/nashorn/test/script/basic/NASHORN-163.js b/nashorn/test/script/basic/NASHORN-163.js
index d431a3d..9297171 100644
--- a/nashorn/test/script/basic/NASHORN-163.js
+++ b/nashorn/test/script/basic/NASHORN-163.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-163 :  Object.keys(o) should only enumerate o's own properties
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-164.js b/nashorn/test/script/basic/NASHORN-164.js
index f1b42eb..2b24349 100644
--- a/nashorn/test/script/basic/NASHORN-164.js
+++ b/nashorn/test/script/basic/NASHORN-164.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 var obj2 = { bar: 'hello' };
 var obj = Object.create(obj2);
-obj.foo = 22; 
+obj.foo = 22;
 
 if (JSON.stringify(obj) != '{"foo":22}') {
     throw Error("expected '{\"foo\":22}' got " + JSON.stringify(obj));
diff --git a/nashorn/test/script/basic/NASHORN-165.js b/nashorn/test/script/basic/NASHORN-165.js
index fc1008e..5516b44 100644
--- a/nashorn/test/script/basic/NASHORN-165.js
+++ b/nashorn/test/script/basic/NASHORN-165.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-166.js b/nashorn/test/script/basic/NASHORN-166.js
index 465f159..95a960c 100644
--- a/nashorn/test/script/basic/NASHORN-166.js
+++ b/nashorn/test/script/basic/NASHORN-166.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-168.js b/nashorn/test/script/basic/NASHORN-168.js
index 138c352..d9b5568 100644
--- a/nashorn/test/script/basic/NASHORN-168.js
+++ b/nashorn/test/script/basic/NASHORN-168.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-169.js b/nashorn/test/script/basic/NASHORN-169.js
index 4da5276..aacec29 100644
--- a/nashorn/test/script/basic/NASHORN-169.js
+++ b/nashorn/test/script/basic/NASHORN-169.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-172.js b/nashorn/test/script/basic/NASHORN-172.js
index 607642f..26b6ed5 100644
--- a/nashorn/test/script/basic/NASHORN-172.js
+++ b/nashorn/test/script/basic/NASHORN-172.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,12 +28,12 @@
  * @run
  */
 
-if (delete x !== true) { 
+if (delete x !== true) {
     fail('#1: delete x === true');
 }
 
-if (delete this.x !== true) { 
-    fail('#2: delete this.x === true'); 
+if (delete this.x !== true) {
+    fail('#2: delete this.x === true');
 }
 
 var y = 23;
diff --git a/nashorn/test/script/basic/NASHORN-173.js b/nashorn/test/script/basic/NASHORN-173.js
index 1ee89f3..9e7a7c5 100644
--- a/nashorn/test/script/basic/NASHORN-173.js
+++ b/nashorn/test/script/basic/NASHORN-173.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-174.js b/nashorn/test/script/basic/NASHORN-174.js
index e56c258..7bc59ac 100644
--- a/nashorn/test/script/basic/NASHORN-174.js
+++ b/nashorn/test/script/basic/NASHORN-174.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,7 +33,7 @@
 if (nums.length != 4) {
     fail("#1: split result expected to be of length 4");
 }
-   
+
 function check(index, value) {
     if (nums[index] != value) {
         fail("expected value @ " + index + " is " + value);
diff --git a/nashorn/test/script/basic/NASHORN-175.js b/nashorn/test/script/basic/NASHORN-175.js
index be60d12..5ed5e06 100644
--- a/nashorn/test/script/basic/NASHORN-175.js
+++ b/nashorn/test/script/basic/NASHORN-175.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-176.js b/nashorn/test/script/basic/NASHORN-176.js
index 672362d..fe1a696 100644
--- a/nashorn/test/script/basic/NASHORN-176.js
+++ b/nashorn/test/script/basic/NASHORN-176.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-177.js b/nashorn/test/script/basic/NASHORN-177.js
index 024a9d1..4815e13 100644
--- a/nashorn/test/script/basic/NASHORN-177.js
+++ b/nashorn/test/script/basic/NASHORN-177.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * NASHORN-177 : null array elements become undefined on assignment 
+ * NASHORN-177 : null array elements become undefined on assignment
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/NASHORN-178.js b/nashorn/test/script/basic/NASHORN-178.js
index 4e1a919..70c0d66 100644
--- a/nashorn/test/script/basic/NASHORN-178.js
+++ b/nashorn/test/script/basic/NASHORN-178.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-179.js b/nashorn/test/script/basic/NASHORN-179.js
index d0b50ea..c2b33a1 100644
--- a/nashorn/test/script/basic/NASHORN-179.js
+++ b/nashorn/test/script/basic/NASHORN-179.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-18.js b/nashorn/test/script/basic/NASHORN-18.js
index 50115c9..bc7f19e 100644
--- a/nashorn/test/script/basic/NASHORN-18.js
+++ b/nashorn/test/script/basic/NASHORN-18.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-181.js b/nashorn/test/script/basic/NASHORN-181.js
index 0ad8da5..7af652f 100644
--- a/nashorn/test/script/basic/NASHORN-181.js
+++ b/nashorn/test/script/basic/NASHORN-181.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
 
 try {
     var obj = Object.create({}, props);
-    if (! obj.hasOwnProperty("foo")) { 
+    if (! obj.hasOwnProperty("foo")) {
         fail("obj does not have 'foo' property");
     }
 } catch (e) {
diff --git a/nashorn/test/script/basic/NASHORN-182.js b/nashorn/test/script/basic/NASHORN-182.js
index 0e908dd..278e3d9 100644
--- a/nashorn/test/script/basic/NASHORN-182.js
+++ b/nashorn/test/script/basic/NASHORN-182.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 function callback(prev, cur, idx, obj) {
     fail("callback with " + idx);
-}     
+}
 
 // array-like object
 var obj = { 1: 1, 2: 2, length: 3 };
diff --git a/nashorn/test/script/basic/NASHORN-183.js b/nashorn/test/script/basic/NASHORN-183.js
index c90e7ba..e64b2ea 100644
--- a/nashorn/test/script/basic/NASHORN-183.js
+++ b/nashorn/test/script/basic/NASHORN-183.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-184.js b/nashorn/test/script/basic/NASHORN-184.js
index d1524b9..69ecaf2 100644
--- a/nashorn/test/script/basic/NASHORN-184.js
+++ b/nashorn/test/script/basic/NASHORN-184.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-185.js b/nashorn/test/script/basic/NASHORN-185.js
index 508b5b3..c42eae3 100644
--- a/nashorn/test/script/basic/NASHORN-185.js
+++ b/nashorn/test/script/basic/NASHORN-185.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-187.js b/nashorn/test/script/basic/NASHORN-187.js
index 7238ecf..d253464 100644
--- a/nashorn/test/script/basic/NASHORN-187.js
+++ b/nashorn/test/script/basic/NASHORN-187.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,16 +31,16 @@
 var obj = {};
 
 try {
-    Object.defineProperty(obj, "foo", { 
-         get: function() { return 22; }, 
-         set: undefined 
+    Object.defineProperty(obj, "foo", {
+         get: function() { return 22; },
+         set: undefined
     });
 } catch (e) {
     fail("failed", e);
 }
 
 try {
-    Object.defineProperty(obj, "bar", { 
+    Object.defineProperty(obj, "bar", {
         get: undefined
     });
 } catch (e) {
diff --git a/nashorn/test/script/basic/NASHORN-188.js b/nashorn/test/script/basic/NASHORN-188.js
index ce72713..baa02f3 100644
--- a/nashorn/test/script/basic/NASHORN-188.js
+++ b/nashorn/test/script/basic/NASHORN-188.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-19.js b/nashorn/test/script/basic/NASHORN-19.js
index 71a2db0d..88c6be0 100644
--- a/nashorn/test/script/basic/NASHORN-19.js
+++ b/nashorn/test/script/basic/NASHORN-19.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -38,8 +38,8 @@
 
 do {
     with(myscope) {
-	myvalue = 12;
-	break;
+    myvalue = 12;
+    break;
     }
 } while (false);
 
@@ -62,15 +62,15 @@
 var scope2 = {value:20};
 while (true) {
     with (scope) {
-	print(value);
-	value = 11;
-	print(value);
-	with (scope2) {
-	    print(value);
-	    value = 21;
-	    print(value);
-	    break;
-	}
+    print(value);
+    value = 11;
+    print(value);
+    with (scope2) {
+        print(value);
+        value = 21;
+        print(value);
+        break;
+    }
     }
 }
 
@@ -83,19 +83,19 @@
     var scope = {value:10};
     var scope2 = {value:20};
     while (true) {
-	with (scope) {
-	    print(value);
-	    value = 11;
-	    print(value);
-	    with (scope2) {
-		print(value);
-		value = 21;
-		print(value);
-		break;
-	    }
-	}
+    with (scope) {
+        print(value);
+        value = 11;
+        print(value);
+        with (scope2) {
+        print(value);
+        value = 21;
+        print(value);
+        break;
+        }
     }
-    
+    }
+
     print(value);
 }
 
@@ -104,14 +104,14 @@
     var value = "hello";
     var scope = {value:10};
     while (true) {
-	with (scope) {
-	    print(value);
-	    value = 11;
-	    print(value);
-	    if (value > ten()) {
-		break;
-	    }
-	}
+    with (scope) {
+        print(value);
+        value = 11;
+        print(value);
+        if (value > ten()) {
+        break;
+        }
+    }
     }
     print(value);
 }
@@ -123,24 +123,24 @@
     var scope2 = {value:20};
     var outer = 0;
     while (outer < 5) {
-	var i=0;
-	while (i < 10) {
-	    with(scope) {
-		print("loop header "+i);
-		with (scope2) {
-		    value = 11;
-		    i++;
-		    if ((i & 1) != 0) {
-			print("continue");
-			continue;
-		    }
-		}
-	    }
-	    print(value);
-	}
-	outer++;
+    var i=0;
+    while (i < 10) {
+        with(scope) {
+        print("loop header "+i);
+        with (scope2) {
+            value = 11;
+            i++;
+            if ((i & 1) != 0) {
+            print("continue");
+            continue;
+            }
+        }
+        }
+        print(value);
     }
-} 
+    outer++;
+    }
+}
 
 //continue one level
 function test4() {
@@ -148,15 +148,15 @@
     var scope = {value:10};
     var i=0;
     while (i < 10) {
-	print("loop header "+i);
-	with (scope) {
-	    value = 11;
-	    i++;
-	    if ((i & 1) != 0) {
-		print("continue");
-		continue;
-	    }
-	}
+    print("loop header "+i);
+    with (scope) {
+        value = 11;
+        i++;
+        if ((i & 1) != 0) {
+        print("continue");
+        continue;
+        }
+    }
     }
     print(value);
 }
@@ -170,24 +170,24 @@
     var outer = 0;
     outer_label:
     while (outer < 5) {
-	var i=0;
-	while (i < 10) {
-	    with(scope) {
-		print("loop header "+i);
-		with (scope2) {
-		    value = 11;
-		    i++;
-		    if ((i & 1) != 0) {
-			print("continue");
-			outer++;
-			continue outer_label;
-		    }
-		}
-	    }
-	    print(value);
-	}
+    var i=0;
+    while (i < 10) {
+        with(scope) {
+        print("loop header "+i);
+        with (scope2) {
+            value = 11;
+            i++;
+            if ((i & 1) != 0) {
+            print("continue");
+            outer++;
+            continue outer_label;
+            }
+        }
+        }
+        print(value);
     }
-} 
+    }
+}
 
 //labelled break
 function test6() {
@@ -196,21 +196,21 @@
     var scope2 = {value:20};
     outer:
     {
-	var i=0;
-	while (i < 10) {
-	    with(scope) {
-		print("loop header "+i);
-		with (scope2) {
-		    value = 11;
-		    i++;
-		    if ((i & 1) != 0) {
-			print("break");
-			break outer;
-		    }
-		}
-	    }
-	    print(value);
-	}
+    var i=0;
+    while (i < 10) {
+        with(scope) {
+        print("loop header "+i);
+        with (scope2) {
+            value = 11;
+            i++;
+            if ((i & 1) != 0) {
+            print("break");
+            break outer;
+            }
+        }
+        }
+        print(value);
+    }
     }
 }
 
@@ -218,32 +218,32 @@
 function test7() {
     var value = "hello";
     var scope = {value:10};
-    var scope2 = {value:20};    
+    var scope2 = {value:20};
     var global = false;
     try {
-	with(scope) {
-	    try {
-		print(value);
-		value = 4711;
-		print(value);
-		with(scope2) {
-		    print(value);
-		    value = 17;
-		    print(value);
-		    global = true;
-		    throw "inner";
-		}
-	    } catch (ei) {
-		print(ei);
-		print(value);
-		if (global) {
-		    throw "outer";
-		}
-	    }
-	}
+    with(scope) {
+        try {
+        print(value);
+        value = 4711;
+        print(value);
+        with(scope2) {
+            print(value);
+            value = 17;
+            print(value);
+            global = true;
+            throw "inner";
+        }
+        } catch (ei) {
+        print(ei);
+        print(value);
+        if (global) {
+            throw "outer";
+        }
+        }
+    }
     } catch (eo) {
-	print(eo);
-	print(value);
+    print(eo);
+    print(value);
     }
     print(value);
 }
diff --git a/nashorn/test/script/basic/NASHORN-190.js b/nashorn/test/script/basic/NASHORN-190.js
index 06e51a3..919de57 100644
--- a/nashorn/test/script/basic/NASHORN-190.js
+++ b/nashorn/test/script/basic/NASHORN-190.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-var obj = { 
+var obj = {
     20: 'world', "2.3": 'hello'
 };
 
diff --git a/nashorn/test/script/basic/NASHORN-192.js b/nashorn/test/script/basic/NASHORN-192.js
index 8fdc82b..9cd55e7 100644
--- a/nashorn/test/script/basic/NASHORN-192.js
+++ b/nashorn/test/script/basic/NASHORN-192.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-192 :  User defined property setter or getter with extra arguments or lesser argument fails by throwing exception
- * 
+ *
  * @test
  * @run
  */
@@ -59,7 +59,7 @@
     set: function(obj1, obj2, obj3) {
         this.val = obj1;
     }
-}); 
+});
 
 try {
     obj.prop = 33;
diff --git a/nashorn/test/script/basic/NASHORN-194.js b/nashorn/test/script/basic/NASHORN-194.js
index bbbc194..21bb00d 100644
--- a/nashorn/test/script/basic/NASHORN-194.js
+++ b/nashorn/test/script/basic/NASHORN-194.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-196.js b/nashorn/test/script/basic/NASHORN-196.js
index 071da97..562e623 100644
--- a/nashorn/test/script/basic/NASHORN-196.js
+++ b/nashorn/test/script/basic/NASHORN-196.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,7 +33,7 @@
 Object.defineProperty(arr, "length", {
     value: -0
 });
-        
+
 if (arr.length !== 0) {
     fail("array length is not zero!");
 }
diff --git a/nashorn/test/script/basic/NASHORN-198.js b/nashorn/test/script/basic/NASHORN-198.js
index ea99a3b..f0b7339 100644
--- a/nashorn/test/script/basic/NASHORN-198.js
+++ b/nashorn/test/script/basic/NASHORN-198.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-20.js b/nashorn/test/script/basic/NASHORN-20.js
index b0d6cc9..7558f2b 100644
--- a/nashorn/test/script/basic/NASHORN-20.js
+++ b/nashorn/test/script/basic/NASHORN-20.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-201.js b/nashorn/test/script/basic/NASHORN-201.js
index 11bcf27..9631140 100644
--- a/nashorn/test/script/basic/NASHORN-201.js
+++ b/nashorn/test/script/basic/NASHORN-201.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-202.js b/nashorn/test/script/basic/NASHORN-202.js
index 53c7fb1..24c218d 100644
--- a/nashorn/test/script/basic/NASHORN-202.js
+++ b/nashorn/test/script/basic/NASHORN-202.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-203.js b/nashorn/test/script/basic/NASHORN-203.js
index 94acb3e..aa15d3a 100644
--- a/nashorn/test/script/basic/NASHORN-203.js
+++ b/nashorn/test/script/basic/NASHORN-203.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-204.js b/nashorn/test/script/basic/NASHORN-204.js
index 98dedba..ce8be38 100644
--- a/nashorn/test/script/basic/NASHORN-204.js
+++ b/nashorn/test/script/basic/NASHORN-204.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-205.js b/nashorn/test/script/basic/NASHORN-205.js
index 15bb389..caf05e9 100644
--- a/nashorn/test/script/basic/NASHORN-205.js
+++ b/nashorn/test/script/basic/NASHORN-205.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -54,7 +54,7 @@
 } catch (e) {
     fail("failed", e);
 }
-  
+
 var newDesc = Object.getOwnPropertyDescriptor(obj, "foo");
 if (! newDesc.hasOwnProperty("value")) {
     fail("'value' missing!!");
diff --git a/nashorn/test/script/basic/NASHORN-206.js b/nashorn/test/script/basic/NASHORN-206.js
index 537a990..df34639 100644
--- a/nashorn/test/script/basic/NASHORN-206.js
+++ b/nashorn/test/script/basic/NASHORN-206.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-207.js b/nashorn/test/script/basic/NASHORN-207.js
index b337ce3..5950b94 100644
--- a/nashorn/test/script/basic/NASHORN-207.js
+++ b/nashorn/test/script/basic/NASHORN-207.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,7 +37,7 @@
 } catch (e) {
     if (! (e instanceof SyntaxError)) {
         fail("#2 SyntaxError expected but got " + e);
-    } 
+    }
 }
 
 // cannot delete function parameter variable
@@ -47,7 +47,7 @@
 } catch(e) {
     if (! (e instanceof SyntaxError)) {
         fail("#4 SyntaxError expected but got " + e);
-    } 
+    }
 }
 
 // assignment can't be used to define as new variable
diff --git a/nashorn/test/script/basic/NASHORN-207_2.js b/nashorn/test/script/basic/NASHORN-207_2.js
index 681a3c2..76704e0 100644
--- a/nashorn/test/script/basic/NASHORN-207_2.js
+++ b/nashorn/test/script/basic/NASHORN-207_2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-208.js b/nashorn/test/script/basic/NASHORN-208.js
index f7b2861..360d0e8 100644
--- a/nashorn/test/script/basic/NASHORN-208.js
+++ b/nashorn/test/script/basic/NASHORN-208.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * NASHORN-208  
+ * NASHORN-208
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/NASHORN-209.js b/nashorn/test/script/basic/NASHORN-209.js
index 9fa781c..c3319cf 100644
--- a/nashorn/test/script/basic/NASHORN-209.js
+++ b/nashorn/test/script/basic/NASHORN-209.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,8 +28,8 @@
  * @run
  */
 
-var obj  = { 
-    in: 11, class: 'hello', try: false, 
+var obj  = {
+    in: 11, class: 'hello', try: false,
     typeof: 456, instanceof: 'world',
     catch: function() { print("catch called"); }
 };
diff --git a/nashorn/test/script/basic/NASHORN-21.js b/nashorn/test/script/basic/NASHORN-21.js
index 14db4dc..dbae299e 100644
--- a/nashorn/test/script/basic/NASHORN-21.js
+++ b/nashorn/test/script/basic/NASHORN-21.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-211.js b/nashorn/test/script/basic/NASHORN-211.js
index 681caad..5b22452 100644
--- a/nashorn/test/script/basic/NASHORN-211.js
+++ b/nashorn/test/script/basic/NASHORN-211.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-212.js b/nashorn/test/script/basic/NASHORN-212.js
index 681c775..0a74e0d 100644
--- a/nashorn/test/script/basic/NASHORN-212.js
+++ b/nashorn/test/script/basic/NASHORN-212.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-213.js b/nashorn/test/script/basic/NASHORN-213.js
index 03a37d9..366d318 100644
--- a/nashorn/test/script/basic/NASHORN-213.js
+++ b/nashorn/test/script/basic/NASHORN-213.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-215.js b/nashorn/test/script/basic/NASHORN-215.js
index 53ff42e..8d14484 100644
--- a/nashorn/test/script/basic/NASHORN-215.js
+++ b/nashorn/test/script/basic/NASHORN-215.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-216.js b/nashorn/test/script/basic/NASHORN-216.js
index e9b1aee..8e50b23 100644
--- a/nashorn/test/script/basic/NASHORN-216.js
+++ b/nashorn/test/script/basic/NASHORN-216.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-217.js b/nashorn/test/script/basic/NASHORN-217.js
index 3885c70..97cde44 100644
--- a/nashorn/test/script/basic/NASHORN-217.js
+++ b/nashorn/test/script/basic/NASHORN-217.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-219.js b/nashorn/test/script/basic/NASHORN-219.js
index b7da209..bb3b25e 100644
--- a/nashorn/test/script/basic/NASHORN-219.js
+++ b/nashorn/test/script/basic/NASHORN-219.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-22.js b/nashorn/test/script/basic/NASHORN-22.js
index 89f677c..e96be95 100644
--- a/nashorn/test/script/basic/NASHORN-22.js
+++ b/nashorn/test/script/basic/NASHORN-22.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-221.js b/nashorn/test/script/basic/NASHORN-221.js
index 87132bc..e743cec 100644
--- a/nashorn/test/script/basic/NASHORN-221.js
+++ b/nashorn/test/script/basic/NASHORN-221.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-222.js b/nashorn/test/script/basic/NASHORN-222.js
index a5a61f0..c1809b9 100644
--- a/nashorn/test/script/basic/NASHORN-222.js
+++ b/nashorn/test/script/basic/NASHORN-222.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-223.js b/nashorn/test/script/basic/NASHORN-223.js
index dd862d5..f5baa97 100644
--- a/nashorn/test/script/basic/NASHORN-223.js
+++ b/nashorn/test/script/basic/NASHORN-223.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-225.js b/nashorn/test/script/basic/NASHORN-225.js
index c7744c3..bc2e1d5 100644
--- a/nashorn/test/script/basic/NASHORN-225.js
+++ b/nashorn/test/script/basic/NASHORN-225.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-226.js b/nashorn/test/script/basic/NASHORN-226.js
index 521c3a6..6ea30f9 100644
--- a/nashorn/test/script/basic/NASHORN-226.js
+++ b/nashorn/test/script/basic/NASHORN-226.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-227.js b/nashorn/test/script/basic/NASHORN-227.js
index 787bdfa..bb2b0fe 100644
--- a/nashorn/test/script/basic/NASHORN-227.js
+++ b/nashorn/test/script/basic/NASHORN-227.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-228.js b/nashorn/test/script/basic/NASHORN-228.js
index bb3bd8b..26ce832 100644
--- a/nashorn/test/script/basic/NASHORN-228.js
+++ b/nashorn/test/script/basic/NASHORN-228.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -51,4 +51,4 @@
         fail("typeof key of a string is not 'string'");
     }
 }
-    
+
diff --git a/nashorn/test/script/basic/NASHORN-229.js b/nashorn/test/script/basic/NASHORN-229.js
index fefc318..63bcdd6 100644
--- a/nashorn/test/script/basic/NASHORN-229.js
+++ b/nashorn/test/script/basic/NASHORN-229.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -39,4 +39,4 @@
 }
 
 load(__DIR__ + 'NASHORN-229_subtest.js');
-    
+
diff --git a/nashorn/test/script/basic/NASHORN-229_subtest.js b/nashorn/test/script/basic/NASHORN-229_subtest.js
index a722a98..f3854471 100644
--- a/nashorn/test/script/basic/NASHORN-229_subtest.js
+++ b/nashorn/test/script/basic/NASHORN-229_subtest.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 function func2() {
     var obj2 = {
         get bar() { return 343; }
-    }; 
+    };
 
     return (obj2.bar === 343);
 }
diff --git a/nashorn/test/script/basic/NASHORN-23.js b/nashorn/test/script/basic/NASHORN-23.js
index eab229e..98f0a46 100644
--- a/nashorn/test/script/basic/NASHORN-23.js
+++ b/nashorn/test/script/basic/NASHORN-23.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-23:  calling function valued global variable before it is initialized should fail.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-232.js b/nashorn/test/script/basic/NASHORN-232.js
index a2033ba..d977dc5 100644
--- a/nashorn/test/script/basic/NASHORN-232.js
+++ b/nashorn/test/script/basic/NASHORN-232.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-234.js b/nashorn/test/script/basic/NASHORN-234.js
index 87fec55..7c5bd2d 100644
--- a/nashorn/test/script/basic/NASHORN-234.js
+++ b/nashorn/test/script/basic/NASHORN-234.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-235.js b/nashorn/test/script/basic/NASHORN-235.js
index f01d3f4..98fe94c 100644
--- a/nashorn/test/script/basic/NASHORN-235.js
+++ b/nashorn/test/script/basic/NASHORN-235.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-236.js b/nashorn/test/script/basic/NASHORN-236.js
index 5fdb7f8..b4082eb 100644
--- a/nashorn/test/script/basic/NASHORN-236.js
+++ b/nashorn/test/script/basic/NASHORN-236.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-237.js b/nashorn/test/script/basic/NASHORN-237.js
index 37b07b3..23559f4 100644
--- a/nashorn/test/script/basic/NASHORN-237.js
+++ b/nashorn/test/script/basic/NASHORN-237.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-239.js b/nashorn/test/script/basic/NASHORN-239.js
index ca94bcc..918049a 100644
--- a/nashorn/test/script/basic/NASHORN-239.js
+++ b/nashorn/test/script/basic/NASHORN-239.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-24.js b/nashorn/test/script/basic/NASHORN-24.js
index 9f4f66d..e612d21 100644
--- a/nashorn/test/script/basic/NASHORN-24.js
+++ b/nashorn/test/script/basic/NASHORN-24.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-24: function local var assignments should resolve to 'with' scope if found in scope.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-241.js b/nashorn/test/script/basic/NASHORN-241.js
index 7d887a6..1fb3e9a 100644
--- a/nashorn/test/script/basic/NASHORN-241.js
+++ b/nashorn/test/script/basic/NASHORN-241.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 try {
     new 1;
-    fail('new "1" should have thrown TypeError');	
+    fail('new "1" should have thrown TypeError');
 } catch (e) {
     if (! (e instanceof TypeError)) {
         fail('expected TypeError, got ' + e, e);
@@ -40,7 +40,7 @@
 try {
     var x = "1";
     new x;
-    fail('var x = "1"; new x should have thrown TypeError');	
+    fail('var x = "1"; new x should have thrown TypeError');
 } catch (e) {
     if (! (e instanceof TypeError)) {
         fail('var x = "1"; new x - expected TypeError, got ' + e, e);
@@ -50,10 +50,10 @@
 try {
     var x = "1";
     new x();
-    fail('var x = "1"; new x() should have thrown TypeError'); 
+    fail('var x = "1"; new x() should have thrown TypeError');
 } catch (e) {
     if (! (e instanceof TypeError)) {
-        fail('var x = "1"; new x() - expected TypeError, got ' + e); 
+        fail('var x = "1"; new x() - expected TypeError, got ' + e);
     }
 }
 
diff --git a/nashorn/test/script/basic/NASHORN-242.js b/nashorn/test/script/basic/NASHORN-242.js
index 3e362bc..edbc3bb 100644
--- a/nashorn/test/script/basic/NASHORN-242.js
+++ b/nashorn/test/script/basic/NASHORN-242.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-245.js b/nashorn/test/script/basic/NASHORN-245.js
index ced3e39..3c43b92 100644
--- a/nashorn/test/script/basic/NASHORN-245.js
+++ b/nashorn/test/script/basic/NASHORN-245.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-247.js b/nashorn/test/script/basic/NASHORN-247.js
index b05db7e..1187c0c 100644
--- a/nashorn/test/script/basic/NASHORN-247.js
+++ b/nashorn/test/script/basic/NASHORN-247.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-25.js b/nashorn/test/script/basic/NASHORN-25.js
index 0d40ffe..d1bacaa 100644
--- a/nashorn/test/script/basic/NASHORN-25.js
+++ b/nashorn/test/script/basic/NASHORN-25.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-251.js b/nashorn/test/script/basic/NASHORN-251.js
index bc5147f..abe6c1c 100644
--- a/nashorn/test/script/basic/NASHORN-251.js
+++ b/nashorn/test/script/basic/NASHORN-251.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-252.js b/nashorn/test/script/basic/NASHORN-252.js
index 5e0a652..7b59d97 100644
--- a/nashorn/test/script/basic/NASHORN-252.js
+++ b/nashorn/test/script/basic/NASHORN-252.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-253.js b/nashorn/test/script/basic/NASHORN-253.js
index f562c97..518344e 100644
--- a/nashorn/test/script/basic/NASHORN-253.js
+++ b/nashorn/test/script/basic/NASHORN-253.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-256.js b/nashorn/test/script/basic/NASHORN-256.js
index 1885873..47bf128 100644
--- a/nashorn/test/script/basic/NASHORN-256.js
+++ b/nashorn/test/script/basic/NASHORN-256.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-258.js b/nashorn/test/script/basic/NASHORN-258.js
index 6d71266..c3f614f 100644
--- a/nashorn/test/script/basic/NASHORN-258.js
+++ b/nashorn/test/script/basic/NASHORN-258.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,28 +30,28 @@
 
 function test3(a) {
     for (i = 0; i < a.length ; i++) {
-	for (j = 0; j < a[i].length ; j++) {
-	    for (k = 0; k < a[i][j].length ; k++) {
-		a[i][j][k] *= 8;
-	    }
-	}
+    for (j = 0; j < a[i].length ; j++) {
+        for (k = 0; k < a[i][j].length ; k++) {
+        a[i][j][k] *= 8;
+        }
+    }
     }
 }
 
 function test3local(a) {
     for (var i = 0; i < a.length ; i++) {
-	for (var j = 0; j < a[i].length ; j++) {
-	    for (var k = 0; k < a[i][j].length ; k++) {
-		a[i][j][k] *= 8;
-	    }
-	}
+    for (var j = 0; j < a[i].length ; j++) {
+        for (var k = 0; k < a[i][j].length ; k++) {
+        a[i][j][k] *= 8;
+        }
+    }
     }
 }
 
 var array = [ [[1,1,1],[1,1,1],[1,1,1]],
-	      [[1,1,1],[1,1,1],[1,1,1]],
-	      [[1,1,1],[1,1,1],[1,1,1]] ];
-	      
+          [[1,1,1],[1,1,1],[1,1,1]],
+          [[1,1,1],[1,1,1],[1,1,1]] ];
+
 test3(array);
 print(array);
 
@@ -59,17 +59,17 @@
 print(array);
 
 function outer() {
-    
+
     var array2 = [ [[1,1,1],[1,1,1],[1,1,1]],
-		   [[1,1,1],[1,1,1],[1,1,1]],
-		   [[1,1,1],[1,1,1],[1,1,1]] ];
-    
+           [[1,1,1],[1,1,1],[1,1,1]],
+           [[1,1,1],[1,1,1],[1,1,1]] ];
+
     var f =  function inner() {
-	for (var i = 0; i < array2.length ; i++) {
-	    for (var j = 0; j < array2[i].length ; j++) {
-		array2[i][j][2] *= 8;
-	    }
-	}	
+    for (var i = 0; i < array2.length ; i++) {
+        for (var j = 0; j < array2[i].length ; j++) {
+        array2[i][j][2] *= 8;
+        }
+    }
     };
 
     f();
diff --git a/nashorn/test/script/basic/NASHORN-26.js b/nashorn/test/script/basic/NASHORN-26.js
index d4525a3..e6bb65e 100644
--- a/nashorn/test/script/basic/NASHORN-26.js
+++ b/nashorn/test/script/basic/NASHORN-26.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-260.js b/nashorn/test/script/basic/NASHORN-260.js
index d1f1fcc..172fc1e 100644
--- a/nashorn/test/script/basic/NASHORN-260.js
+++ b/nashorn/test/script/basic/NASHORN-260.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-261.js b/nashorn/test/script/basic/NASHORN-261.js
index c53facf..4bab60b 100644
--- a/nashorn/test/script/basic/NASHORN-261.js
+++ b/nashorn/test/script/basic/NASHORN-261.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -75,7 +75,7 @@
     }
 }
 
-// pass no args to our overwritten eval 
+// pass no args to our overwritten eval
 // the new eval should not print anything (no hidden args passed)
 eval();
 
diff --git a/nashorn/test/script/basic/NASHORN-262.js b/nashorn/test/script/basic/NASHORN-262.js
index 42eba1c..8e0adad 100644
--- a/nashorn/test/script/basic/NASHORN-262.js
+++ b/nashorn/test/script/basic/NASHORN-262.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-262 : for statement iterator variable is not checked in strict mode
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-263.js b/nashorn/test/script/basic/NASHORN-263.js
index 62ce47b..2ee2221 100644
--- a/nashorn/test/script/basic/NASHORN-263.js
+++ b/nashorn/test/script/basic/NASHORN-263.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-264.js b/nashorn/test/script/basic/NASHORN-264.js
index 88cd2b3..4e19600 100644
--- a/nashorn/test/script/basic/NASHORN-264.js
+++ b/nashorn/test/script/basic/NASHORN-264.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-265.js b/nashorn/test/script/basic/NASHORN-265.js
index 88344f5..52371ce 100644
--- a/nashorn/test/script/basic/NASHORN-265.js
+++ b/nashorn/test/script/basic/NASHORN-265.js
@@ -1,27 +1,27 @@
 /*
  * 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.
  */
 
-/** 
+/**
  * NASHORN-265 with scope access within a nested function can't access global var
  *
  * @test
diff --git a/nashorn/test/script/basic/NASHORN-266.js b/nashorn/test/script/basic/NASHORN-266.js
index bfc600f..a612558 100644
--- a/nashorn/test/script/basic/NASHORN-266.js
+++ b/nashorn/test/script/basic/NASHORN-266.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-269.js b/nashorn/test/script/basic/NASHORN-269.js
index 92feb76..113e89d 100644
--- a/nashorn/test/script/basic/NASHORN-269.js
+++ b/nashorn/test/script/basic/NASHORN-269.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-27.js b/nashorn/test/script/basic/NASHORN-27.js
index b949b34..0253f1a 100644
--- a/nashorn/test/script/basic/NASHORN-27.js
+++ b/nashorn/test/script/basic/NASHORN-27.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-270.js b/nashorn/test/script/basic/NASHORN-270.js
index 89ef0d8..8fd01e5 100644
--- a/nashorn/test/script/basic/NASHORN-270.js
+++ b/nashorn/test/script/basic/NASHORN-270.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-271.js b/nashorn/test/script/basic/NASHORN-271.js
index 75c480d..def14fe 100644
--- a/nashorn/test/script/basic/NASHORN-271.js
+++ b/nashorn/test/script/basic/NASHORN-271.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-var res = JSON.stringify(23, function(k,v) { 
+var res = JSON.stringify(23, function(k,v) {
     return (v == 23)? [1, 2] : v;
 });
 
@@ -36,8 +36,8 @@
     fail("#1 expected '[1,2]' got " + res);
 }
 
-var res = JSON.stringify(23, function(k,v) { 
-    return (v == 23)? { x: 1, y: 'hello' } : v; 
+var res = JSON.stringify(23, function(k,v) {
+    return (v == 23)? { x: 1, y: 'hello' } : v;
 });
 
 if (res !== '{"x":1,"y":"hello"}') {
diff --git a/nashorn/test/script/basic/NASHORN-275.js b/nashorn/test/script/basic/NASHORN-275.js
index 46c88fe..90fe399 100644
--- a/nashorn/test/script/basic/NASHORN-275.js
+++ b/nashorn/test/script/basic/NASHORN-275.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-276.js b/nashorn/test/script/basic/NASHORN-276.js
index 3bce88f..95a190f 100644
--- a/nashorn/test/script/basic/NASHORN-276.js
+++ b/nashorn/test/script/basic/NASHORN-276.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-277.js b/nashorn/test/script/basic/NASHORN-277.js
index 38724b3..f05aed0 100644
--- a/nashorn/test/script/basic/NASHORN-277.js
+++ b/nashorn/test/script/basic/NASHORN-277.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-278.js b/nashorn/test/script/basic/NASHORN-278.js
index c8bf46e..6196de4 100644
--- a/nashorn/test/script/basic/NASHORN-278.js
+++ b/nashorn/test/script/basic/NASHORN-278.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-28.js b/nashorn/test/script/basic/NASHORN-28.js
index dc964c3..c3dc102 100644
--- a/nashorn/test/script/basic/NASHORN-28.js
+++ b/nashorn/test/script/basic/NASHORN-28.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-281.js b/nashorn/test/script/basic/NASHORN-281.js
index 77abe81..e70288b 100644
--- a/nashorn/test/script/basic/NASHORN-281.js
+++ b/nashorn/test/script/basic/NASHORN-281.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-284.js b/nashorn/test/script/basic/NASHORN-284.js
index 41f210e..3768e41 100644
--- a/nashorn/test/script/basic/NASHORN-284.js
+++ b/nashorn/test/script/basic/NASHORN-284.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-285.js b/nashorn/test/script/basic/NASHORN-285.js
index a7d586e..4401766 100644
--- a/nashorn/test/script/basic/NASHORN-285.js
+++ b/nashorn/test/script/basic/NASHORN-285.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,31 +28,31 @@
  * @run
  */
 
-function do_not_loop_forever() {   
+function do_not_loop_forever() {
     var sum = 0;
-    for (var i = 0; i < 4711; i++) {            
-	sum += i;
-	if (i >= 0) {
-            continue;                                                           
-        }  
-	return sum;
-    }  
+    for (var i = 0; i < 4711; i++) {
+    sum += i;
+    if (i >= 0) {
+            continue;
+        }
+    return sum;
+    }
     return sum;
 }
 
 
 function still_tag_terminal() {
     var sum = 0;
-    for (var i = 0; i < 4711; i++) {            
-	sum += i;
-	for (var j = 0; j < 4712; j++) {
-	    sum += j;
-	    if (j & 1) {
-		continue;
-	    }
-	}
-	return sum;
-    }  
+    for (var i = 0; i < 4711; i++) {
+    sum += i;
+    for (var j = 0; j < 4712; j++) {
+        sum += j;
+        if (j & 1) {
+        continue;
+        }
+    }
+    return sum;
+    }
     return sum;
 }
 
diff --git a/nashorn/test/script/basic/NASHORN-288.js b/nashorn/test/script/basic/NASHORN-288.js
index b0c43a9..175db50 100644
--- a/nashorn/test/script/basic/NASHORN-288.js
+++ b/nashorn/test/script/basic/NASHORN-288.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-29.js b/nashorn/test/script/basic/NASHORN-29.js
index 2455fa9..5cc8547 100644
--- a/nashorn/test/script/basic/NASHORN-29.js
+++ b/nashorn/test/script/basic/NASHORN-29.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-293.js b/nashorn/test/script/basic/NASHORN-293.js
index 013714b..016215f 100644
--- a/nashorn/test/script/basic/NASHORN-293.js
+++ b/nashorn/test/script/basic/NASHORN-293.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-294.js b/nashorn/test/script/basic/NASHORN-294.js
index 5de3f90..b2f6e52 100644
--- a/nashorn/test/script/basic/NASHORN-294.js
+++ b/nashorn/test/script/basic/NASHORN-294.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-296.js b/nashorn/test/script/basic/NASHORN-296.js
index 26338e6..dfc1ab9 100644
--- a/nashorn/test/script/basic/NASHORN-296.js
+++ b/nashorn/test/script/basic/NASHORN-296.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-297.js b/nashorn/test/script/basic/NASHORN-297.js
index 5486a13..1915646 100644
--- a/nashorn/test/script/basic/NASHORN-297.js
+++ b/nashorn/test/script/basic/NASHORN-297.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-30.js b/nashorn/test/script/basic/NASHORN-30.js
index 95676cf..fb68c73 100644
--- a/nashorn/test/script/basic/NASHORN-30.js
+++ b/nashorn/test/script/basic/NASHORN-30.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,11 +30,11 @@
 
 var obj = {
     valueOf: function() {
-        print("valueOf call"); 
-        return -2 
+        print("valueOf call");
+        return -2
     },
 
-    toString: function() { 
+    toString: function() {
         print("toString call");
         return "-2";
     }
diff --git a/nashorn/test/script/basic/NASHORN-300.js b/nashorn/test/script/basic/NASHORN-300.js
index fce230a..0d8f1ba 100644
--- a/nashorn/test/script/basic/NASHORN-300.js
+++ b/nashorn/test/script/basic/NASHORN-300.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,9 +29,9 @@
  */
 
 function func1(foo) {
-    if (foo) {  
+    if (foo) {
        var encoding = arguments[3];
-    }  
+    }
 
     var s = encoding;
 }
diff --git a/nashorn/test/script/basic/NASHORN-301.js b/nashorn/test/script/basic/NASHORN-301.js
index b00b78d..9625273 100644
--- a/nashorn/test/script/basic/NASHORN-301.js
+++ b/nashorn/test/script/basic/NASHORN-301.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-304.js b/nashorn/test/script/basic/NASHORN-304.js
index 4d740e0..fac3be0 100644
--- a/nashorn/test/script/basic/NASHORN-304.js
+++ b/nashorn/test/script/basic/NASHORN-304.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-310.js b/nashorn/test/script/basic/NASHORN-310.js
index c49c2b4..9b5c94e 100644
--- a/nashorn/test/script/basic/NASHORN-310.js
+++ b/nashorn/test/script/basic/NASHORN-310.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-318.js b/nashorn/test/script/basic/NASHORN-318.js
index 209a6bd..16bbe5a 100644
--- a/nashorn/test/script/basic/NASHORN-318.js
+++ b/nashorn/test/script/basic/NASHORN-318.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-32.js b/nashorn/test/script/basic/NASHORN-32.js
index 0fd625b..7b958f6 100644
--- a/nashorn/test/script/basic/NASHORN-32.js
+++ b/nashorn/test/script/basic/NASHORN-32.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-321.js b/nashorn/test/script/basic/NASHORN-321.js
index 9510c17..56b427a 100644
--- a/nashorn/test/script/basic/NASHORN-321.js
+++ b/nashorn/test/script/basic/NASHORN-321.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-323.js b/nashorn/test/script/basic/NASHORN-323.js
index c1715c0..f3e344e 100644
--- a/nashorn/test/script/basic/NASHORN-323.js
+++ b/nashorn/test/script/basic/NASHORN-323.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-324.js b/nashorn/test/script/basic/NASHORN-324.js
index 11aa51c..929c9f3 100644
--- a/nashorn/test/script/basic/NASHORN-324.js
+++ b/nashorn/test/script/basic/NASHORN-324.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-33.js b/nashorn/test/script/basic/NASHORN-33.js
index 2ed87e4..af77f21 100644
--- a/nashorn/test/script/basic/NASHORN-33.js
+++ b/nashorn/test/script/basic/NASHORN-33.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-331.js b/nashorn/test/script/basic/NASHORN-331.js
index 41ce529..46b61b6 100644
--- a/nashorn/test/script/basic/NASHORN-331.js
+++ b/nashorn/test/script/basic/NASHORN-331.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * NASHORN-331 : Nan compares 
+ * NASHORN-331 : Nan compares
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/NASHORN-337.js b/nashorn/test/script/basic/NASHORN-337.js
index dc8bac1..9361eb9 100644
--- a/nashorn/test/script/basic/NASHORN-337.js
+++ b/nashorn/test/script/basic/NASHORN-337.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-337 - Erroneous DCMPL/DCMPG instructions were generated
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-34.js b/nashorn/test/script/basic/NASHORN-34.js
index 267768d..c835a3d 100644
--- a/nashorn/test/script/basic/NASHORN-34.js
+++ b/nashorn/test/script/basic/NASHORN-34.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-340.js b/nashorn/test/script/basic/NASHORN-340.js
index c20ceab..a458e08 100644
--- a/nashorn/test/script/basic/NASHORN-340.js
+++ b/nashorn/test/script/basic/NASHORN-340.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-349.js b/nashorn/test/script/basic/NASHORN-349.js
index a611a58..bf17f3e 100644
--- a/nashorn/test/script/basic/NASHORN-349.js
+++ b/nashorn/test/script/basic/NASHORN-349.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-354.js b/nashorn/test/script/basic/NASHORN-354.js
index 506a032..f019885 100644
--- a/nashorn/test/script/basic/NASHORN-354.js
+++ b/nashorn/test/script/basic/NASHORN-354.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-355.js b/nashorn/test/script/basic/NASHORN-355.js
index f036072..0dc17cb 100644
--- a/nashorn/test/script/basic/NASHORN-355.js
+++ b/nashorn/test/script/basic/NASHORN-355.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-36.js b/nashorn/test/script/basic/NASHORN-36.js
index 3a8a0c9..4c93c68 100644
--- a/nashorn/test/script/basic/NASHORN-36.js
+++ b/nashorn/test/script/basic/NASHORN-36.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-365.js b/nashorn/test/script/basic/NASHORN-365.js
index fe79e8c..74018f2 100644
--- a/nashorn/test/script/basic/NASHORN-365.js
+++ b/nashorn/test/script/basic/NASHORN-365.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-366.js b/nashorn/test/script/basic/NASHORN-366.js
index fae219b..1c5626e 100644
--- a/nashorn/test/script/basic/NASHORN-366.js
+++ b/nashorn/test/script/basic/NASHORN-366.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-368.js b/nashorn/test/script/basic/NASHORN-368.js
index a1b1ba2..d84d94f 100644
--- a/nashorn/test/script/basic/NASHORN-368.js
+++ b/nashorn/test/script/basic/NASHORN-368.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-37.js b/nashorn/test/script/basic/NASHORN-37.js
index 74ee037..8120c9d 100644
--- a/nashorn/test/script/basic/NASHORN-37.js
+++ b/nashorn/test/script/basic/NASHORN-37.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-37 :  object and array properties defined with special keys can be accessed be by special or string keys
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-375.js b/nashorn/test/script/basic/NASHORN-375.js
index 6f84148..be19af1 100644
--- a/nashorn/test/script/basic/NASHORN-375.js
+++ b/nashorn/test/script/basic/NASHORN-375.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-376.js b/nashorn/test/script/basic/NASHORN-376.js
index 37aa345..7ad0117 100644
--- a/nashorn/test/script/basic/NASHORN-376.js
+++ b/nashorn/test/script/basic/NASHORN-376.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-377.js b/nashorn/test/script/basic/NASHORN-377.js
index 31d4df4..968e46e 100644
--- a/nashorn/test/script/basic/NASHORN-377.js
+++ b/nashorn/test/script/basic/NASHORN-377.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -194,7 +194,7 @@
 })();
 
 (function test_slice() {
-  var b = ArrayBuffer(16);
+  var b = new ArrayBuffer(16);
   fillArray(new Int8Array(b));
   print(bufstr(b));
   print("slice(4,8)=" + bufstr(b.slice(4, 8)), "slice(-8,-4)=" + bufstr(b.slice(-8, -4))); // negative index refers from the end of the array
diff --git a/nashorn/test/script/basic/NASHORN-378.js b/nashorn/test/script/basic/NASHORN-378.js
index 0bf2a74..3508d29 100644
--- a/nashorn/test/script/basic/NASHORN-378.js
+++ b/nashorn/test/script/basic/NASHORN-378.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 
 var obj = {};
-Object.defineProperty(obj, "foo", 
+Object.defineProperty(obj, "foo",
     { get: function() { return 42; },
       configurable: true});
 
diff --git a/nashorn/test/script/basic/NASHORN-38.js b/nashorn/test/script/basic/NASHORN-38.js
index b02ecf7..915b64d 100644
--- a/nashorn/test/script/basic/NASHORN-38.js
+++ b/nashorn/test/script/basic/NASHORN-38.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,7 +33,7 @@
     // defined later in lexical order (see below)
     print(typeof f);
     return f;
-  
+
     function f(){
         print("inside function 'f'");
     }
diff --git a/nashorn/test/script/basic/NASHORN-380.js b/nashorn/test/script/basic/NASHORN-380.js
index e41380e..252d8bb 100644
--- a/nashorn/test/script/basic/NASHORN-380.js
+++ b/nashorn/test/script/basic/NASHORN-380.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-381.js b/nashorn/test/script/basic/NASHORN-381.js
index 53237fa..f3e83d0 100644
--- a/nashorn/test/script/basic/NASHORN-381.js
+++ b/nashorn/test/script/basic/NASHORN-381.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-382.js b/nashorn/test/script/basic/NASHORN-382.js
index 71ab3a5..f288255 100644
--- a/nashorn/test/script/basic/NASHORN-382.js
+++ b/nashorn/test/script/basic/NASHORN-382.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-383.js b/nashorn/test/script/basic/NASHORN-383.js
index ae1a06e..5e329bc 100644
--- a/nashorn/test/script/basic/NASHORN-383.js
+++ b/nashorn/test/script/basic/NASHORN-383.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-384.js b/nashorn/test/script/basic/NASHORN-384.js
index 4c40050..3eedf6b 100644
--- a/nashorn/test/script/basic/NASHORN-384.js
+++ b/nashorn/test/script/basic/NASHORN-384.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-385.js b/nashorn/test/script/basic/NASHORN-385.js
index 27b328e..0584717 100644
--- a/nashorn/test/script/basic/NASHORN-385.js
+++ b/nashorn/test/script/basic/NASHORN-385.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,7 +37,7 @@
 
 function checkSetter() {
     o.bar = 44;
-} 
+}
 
 function checkCall() {
     try {
@@ -51,8 +51,8 @@
 checkSetter();
 checkCall();
 
-proto.__get__ = function(name) { 
-    print("in __get__: " + name); 
+proto.__get__ = function(name) {
+    print("in __get__: " + name);
     return name;
 };
 
diff --git a/nashorn/test/script/basic/NASHORN-389.js b/nashorn/test/script/basic/NASHORN-389.js
index 71f9731..555eb2e 100644
--- a/nashorn/test/script/basic/NASHORN-389.js
+++ b/nashorn/test/script/basic/NASHORN-389.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-393.js b/nashorn/test/script/basic/NASHORN-393.js
index 80f4083..e8b1119 100644
--- a/nashorn/test/script/basic/NASHORN-393.js
+++ b/nashorn/test/script/basic/NASHORN-393.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-394.js b/nashorn/test/script/basic/NASHORN-394.js
index a265f16..259b888 100644
--- a/nashorn/test/script/basic/NASHORN-394.js
+++ b/nashorn/test/script/basic/NASHORN-394.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-396.js b/nashorn/test/script/basic/NASHORN-396.js
index 46bcf77..63b8ec2 100644
--- a/nashorn/test/script/basic/NASHORN-396.js
+++ b/nashorn/test/script/basic/NASHORN-396.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,17 +27,17 @@
  * @test
  * @run
  */
- 
-Object.defineProperty(Number.prototype, 
-    "foo", 
+
+Object.defineProperty(Number.prototype,
+    "foo",
     { get: function () { 'use strict'; return this; }
-}); 
+});
 
 if(!((5).foo === 5)) {
     fail("#1 ToObject conversion on 'thisArg' for strict getter");
 }
 
-Number.prototype.func = function() { 
+Number.prototype.func = function() {
     'use strict';
     return this;
 };
diff --git a/nashorn/test/script/basic/NASHORN-397.js b/nashorn/test/script/basic/NASHORN-397.js
index 63e7b3a..fcfc5d8 100644
--- a/nashorn/test/script/basic/NASHORN-397.js
+++ b/nashorn/test/script/basic/NASHORN-397.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-398.js b/nashorn/test/script/basic/NASHORN-398.js
index 6a0535f..1246900 100644
--- a/nashorn/test/script/basic/NASHORN-398.js
+++ b/nashorn/test/script/basic/NASHORN-398.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-40.js b/nashorn/test/script/basic/NASHORN-40.js
index 34331ef..6a5b3d5 100644
--- a/nashorn/test/script/basic/NASHORN-40.js
+++ b/nashorn/test/script/basic/NASHORN-40.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-400.js b/nashorn/test/script/basic/NASHORN-400.js
index eabb8ad..272e360 100644
--- a/nashorn/test/script/basic/NASHORN-400.js
+++ b/nashorn/test/script/basic/NASHORN-400.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-401.js b/nashorn/test/script/basic/NASHORN-401.js
index 6a663e1..eef1617 100644
--- a/nashorn/test/script/basic/NASHORN-401.js
+++ b/nashorn/test/script/basic/NASHORN-401.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-402.js b/nashorn/test/script/basic/NASHORN-402.js
index 33c02a1..8586219 100644
--- a/nashorn/test/script/basic/NASHORN-402.js
+++ b/nashorn/test/script/basic/NASHORN-402.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-404.js b/nashorn/test/script/basic/NASHORN-404.js
index 672fe89..2e4ab89 100644
--- a/nashorn/test/script/basic/NASHORN-404.js
+++ b/nashorn/test/script/basic/NASHORN-404.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-405.js b/nashorn/test/script/basic/NASHORN-405.js
index c104924..5c304c5 100644
--- a/nashorn/test/script/basic/NASHORN-405.js
+++ b/nashorn/test/script/basic/NASHORN-405.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,13 +23,13 @@
 
 /**
  * NASHORN-405 make sure slice does not modify arrays
- * 
+ *
  * @test
  * @run
  */
 
 var x = ['foo', '%zx'];
-var s = x.slice(1); 
+var s = x.slice(1);
 print(s);
 print(x);
 
diff --git a/nashorn/test/script/basic/NASHORN-406.js b/nashorn/test/script/basic/NASHORN-406.js
index a1f362f..09f677c 100644
--- a/nashorn/test/script/basic/NASHORN-406.js
+++ b/nashorn/test/script/basic/NASHORN-406.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * NASHORN-406 : Property descriptor properties should be enumerable 
+ * NASHORN-406 : Property descriptor properties should be enumerable
  *
  * @test
  * @run
@@ -36,7 +36,7 @@
 
 function checkData() {
    var desc = Object.getOwnPropertyDescriptor(obj, "foo");
-   var enumSeen = false, writeSeen = false, 
+   var enumSeen = false, writeSeen = false,
        configSeen = false, valueSeen = false;
    for (i in desc) {
        switch(i) {
@@ -50,7 +50,7 @@
                valueSeen = true; break;
        }
    }
-   
+
    return enumSeen && writeSeen && configSeen && valueSeen;
 }
 
@@ -60,7 +60,7 @@
 
 function checkAccessor() {
    var desc = Object.getOwnPropertyDescriptor(obj, "bar");
-   var enumSeen = false, getterSeen = false, 
+   var enumSeen = false, getterSeen = false,
        configSeen = false, setterSeen = false;
    for (i in desc) {
        switch(i) {
diff --git a/nashorn/test/script/basic/NASHORN-408.js b/nashorn/test/script/basic/NASHORN-408.js
index 1c3375c..4251ed6 100644
--- a/nashorn/test/script/basic/NASHORN-408.js
+++ b/nashorn/test/script/basic/NASHORN-408.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-415.js b/nashorn/test/script/basic/NASHORN-415.js
index 6f29f1a..f2533bc 100644
--- a/nashorn/test/script/basic/NASHORN-415.js
+++ b/nashorn/test/script/basic/NASHORN-415.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-416.js b/nashorn/test/script/basic/NASHORN-416.js
index 387629a..86e2640 100644
--- a/nashorn/test/script/basic/NASHORN-416.js
+++ b/nashorn/test/script/basic/NASHORN-416.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
 
 function getter() { return 32; }
 
-Object.defineProperty(obj, "foo", 
+Object.defineProperty(obj, "foo",
   { get: getter, configurable: true });
 
 function setter(x) { print(x); }
diff --git a/nashorn/test/script/basic/NASHORN-417.js b/nashorn/test/script/basic/NASHORN-417.js
index 6148f06..5a4f441 100644
--- a/nashorn/test/script/basic/NASHORN-417.js
+++ b/nashorn/test/script/basic/NASHORN-417.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-418.js b/nashorn/test/script/basic/NASHORN-418.js
index b42bd83..563b3d7 100644
--- a/nashorn/test/script/basic/NASHORN-418.js
+++ b/nashorn/test/script/basic/NASHORN-418.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-420.js b/nashorn/test/script/basic/NASHORN-420.js
index 741b940..7ccb919 100644
--- a/nashorn/test/script/basic/NASHORN-420.js
+++ b/nashorn/test/script/basic/NASHORN-420.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-421.js b/nashorn/test/script/basic/NASHORN-421.js
index 3a81fe6..9899eae 100644
--- a/nashorn/test/script/basic/NASHORN-421.js
+++ b/nashorn/test/script/basic/NASHORN-421.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -52,9 +52,9 @@
     }
 }
 
-var methods = [ "concat", "join", "pop", "push", "reverse", 
+var methods = [ "concat", "join", "pop", "push", "reverse",
     "shift", "unshift", "slice", "sort", "splice",
-    "indexOf", "lastIndexOf", "every", "some", "forEach", 
+    "indexOf", "lastIndexOf", "every", "some", "forEach",
     "map", "filter", "reduce", "reduceRight" ];
 
 for (var m in methods) {
diff --git a/nashorn/test/script/basic/NASHORN-423.js b/nashorn/test/script/basic/NASHORN-423.js
index 7fa1b00..62ab476 100644
--- a/nashorn/test/script/basic/NASHORN-423.js
+++ b/nashorn/test/script/basic/NASHORN-423.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-423a.js b/nashorn/test/script/basic/NASHORN-423a.js
index bbab24f..7aebefb 100644
--- a/nashorn/test/script/basic/NASHORN-423a.js
+++ b/nashorn/test/script/basic/NASHORN-423a.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-424.js b/nashorn/test/script/basic/NASHORN-424.js
index 1bcbe19..86d293b 100644
--- a/nashorn/test/script/basic/NASHORN-424.js
+++ b/nashorn/test/script/basic/NASHORN-424.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-425.js b/nashorn/test/script/basic/NASHORN-425.js
index c81aea2..d1467bb 100644
--- a/nashorn/test/script/basic/NASHORN-425.js
+++ b/nashorn/test/script/basic/NASHORN-425.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-426.js b/nashorn/test/script/basic/NASHORN-426.js
index 2d4ee7e..4ddf29e 100644
--- a/nashorn/test/script/basic/NASHORN-426.js
+++ b/nashorn/test/script/basic/NASHORN-426.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-427.js b/nashorn/test/script/basic/NASHORN-427.js
index 0169ce8..bbebfe4 100644
--- a/nashorn/test/script/basic/NASHORN-427.js
+++ b/nashorn/test/script/basic/NASHORN-427.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-428.js b/nashorn/test/script/basic/NASHORN-428.js
index 3d692d1..ff3390d 100644
--- a/nashorn/test/script/basic/NASHORN-428.js
+++ b/nashorn/test/script/basic/NASHORN-428.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-429.js b/nashorn/test/script/basic/NASHORN-429.js
index 4591705..b58bff2 100644
--- a/nashorn/test/script/basic/NASHORN-429.js
+++ b/nashorn/test/script/basic/NASHORN-429.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-432.js b/nashorn/test/script/basic/NASHORN-432.js
index d14ee73..6f6e7f1 100644
--- a/nashorn/test/script/basic/NASHORN-432.js
+++ b/nashorn/test/script/basic/NASHORN-432.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-433.js b/nashorn/test/script/basic/NASHORN-433.js
index 99b88a8..25850bb 100644
--- a/nashorn/test/script/basic/NASHORN-433.js
+++ b/nashorn/test/script/basic/NASHORN-433.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-434.js b/nashorn/test/script/basic/NASHORN-434.js
index 413746905..03f0f57 100644
--- a/nashorn/test/script/basic/NASHORN-434.js
+++ b/nashorn/test/script/basic/NASHORN-434.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -34,7 +34,7 @@
     if (this !== global) {
         fail("#1 callback got 'this' different from global");
     }
-} 
+}
 
 function strictFunc(val, idx, obj) {
     'use strict';
@@ -49,7 +49,7 @@
 }
 
 var arr = [1];
-arr.forEach(func); 
+arr.forEach(func);
 arr.forEach(strictFunc);
 
 var callbackThis = {};
diff --git a/nashorn/test/script/basic/NASHORN-435.js b/nashorn/test/script/basic/NASHORN-435.js
index 15d7bf0..91a64e6 100644
--- a/nashorn/test/script/basic/NASHORN-435.js
+++ b/nashorn/test/script/basic/NASHORN-435.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-437.js b/nashorn/test/script/basic/NASHORN-437.js
index cf23361..59c1e74 100644
--- a/nashorn/test/script/basic/NASHORN-437.js
+++ b/nashorn/test/script/basic/NASHORN-437.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-44.js b/nashorn/test/script/basic/NASHORN-44.js
index 10b58c2..9e82e1b 100644
--- a/nashorn/test/script/basic/NASHORN-44.js
+++ b/nashorn/test/script/basic/NASHORN-44.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,9 +29,9 @@
  */
 function loop1() {
     print("loop1");
-    for (var i = 0; i < 5; i++) { 
-	print(i); 
-	continue;
+    for (var i = 0; i < 5; i++) {
+    print(i);
+    continue;
     }
     print(i);
     print("done1");
@@ -40,8 +40,8 @@
 function loop2() {
     print("loop2");
     for (var i = 0; i < 5; i++) {
-	print(i);
-	break;
+    print(i);
+    break;
     }
     print(i);
     print("done2");
diff --git a/nashorn/test/script/basic/NASHORN-441.js b/nashorn/test/script/basic/NASHORN-441.js
index 8c51ea9..7e9d316 100644
--- a/nashorn/test/script/basic/NASHORN-441.js
+++ b/nashorn/test/script/basic/NASHORN-441.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-442.js b/nashorn/test/script/basic/NASHORN-442.js
index 9a5128a..13f3c34 100644
--- a/nashorn/test/script/basic/NASHORN-442.js
+++ b/nashorn/test/script/basic/NASHORN-442.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-443.js b/nashorn/test/script/basic/NASHORN-443.js
index ab91820..d585ebc 100644
--- a/nashorn/test/script/basic/NASHORN-443.js
+++ b/nashorn/test/script/basic/NASHORN-443.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-444.js b/nashorn/test/script/basic/NASHORN-444.js
index 27811af..24546f4 100644
--- a/nashorn/test/script/basic/NASHORN-444.js
+++ b/nashorn/test/script/basic/NASHORN-444.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-445.js b/nashorn/test/script/basic/NASHORN-445.js
index 89a1b72..c615c23 100644
--- a/nashorn/test/script/basic/NASHORN-445.js
+++ b/nashorn/test/script/basic/NASHORN-445.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-446.js b/nashorn/test/script/basic/NASHORN-446.js
index f8ba093..20ee683 100644
--- a/nashorn/test/script/basic/NASHORN-446.js
+++ b/nashorn/test/script/basic/NASHORN-446.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-447.js b/nashorn/test/script/basic/NASHORN-447.js
index e817c7f..8f6100e 100644
--- a/nashorn/test/script/basic/NASHORN-447.js
+++ b/nashorn/test/script/basic/NASHORN-447.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-448.js b/nashorn/test/script/basic/NASHORN-448.js
index a79adf9..5618c36 100644
--- a/nashorn/test/script/basic/NASHORN-448.js
+++ b/nashorn/test/script/basic/NASHORN-448.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-449.js b/nashorn/test/script/basic/NASHORN-449.js
index ef7171a..27a19db 100644
--- a/nashorn/test/script/basic/NASHORN-449.js
+++ b/nashorn/test/script/basic/NASHORN-449.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-449 :  defineProperty on arguments object does not work element in question was deleted earlier
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/NASHORN-45.js b/nashorn/test/script/basic/NASHORN-45.js
index 29105b7..9d532dc 100644
--- a/nashorn/test/script/basic/NASHORN-45.js
+++ b/nashorn/test/script/basic/NASHORN-45.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-450.js b/nashorn/test/script/basic/NASHORN-450.js
index eb3776d..77c25a0 100644
--- a/nashorn/test/script/basic/NASHORN-450.js
+++ b/nashorn/test/script/basic/NASHORN-450.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-452.js b/nashorn/test/script/basic/NASHORN-452.js
index aa2ef5c..83d7747 100644
--- a/nashorn/test/script/basic/NASHORN-452.js
+++ b/nashorn/test/script/basic/NASHORN-452.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-459.js b/nashorn/test/script/basic/NASHORN-459.js
index 6d9258e..f6bcc54 100644
--- a/nashorn/test/script/basic/NASHORN-459.js
+++ b/nashorn/test/script/basic/NASHORN-459.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-46.js b/nashorn/test/script/basic/NASHORN-46.js
index a23a2a0..008992a 100644
--- a/nashorn/test/script/basic/NASHORN-46.js
+++ b/nashorn/test/script/basic/NASHORN-46.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-462.js b/nashorn/test/script/basic/NASHORN-462.js
index 6cfbb83..078a85f 100644
--- a/nashorn/test/script/basic/NASHORN-462.js
+++ b/nashorn/test/script/basic/NASHORN-462.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,8 +31,8 @@
 function Foo() {};
 Object.defineProperty(Foo.prototype, "bar", { value: 19 });
 
-var fooObj = new Foo(); 
-fooObj.bar = "overridden"; 
+var fooObj = new Foo();
+fooObj.bar = "overridden";
 if (fooObj.hasOwnProperty("bar")) {
     fail("inherited non-writable property can be overridden");
 }
diff --git a/nashorn/test/script/basic/NASHORN-463.js b/nashorn/test/script/basic/NASHORN-463.js
index 41ca3fb..5b58f5a 100644
--- a/nashorn/test/script/basic/NASHORN-463.js
+++ b/nashorn/test/script/basic/NASHORN-463.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-468.js b/nashorn/test/script/basic/NASHORN-468.js
index 10a36f9..392fd09 100644
--- a/nashorn/test/script/basic/NASHORN-468.js
+++ b/nashorn/test/script/basic/NASHORN-468.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-47.js b/nashorn/test/script/basic/NASHORN-47.js
index 1454db0..43210e7 100644
--- a/nashorn/test/script/basic/NASHORN-47.js
+++ b/nashorn/test/script/basic/NASHORN-47.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-473.js b/nashorn/test/script/basic/NASHORN-473.js
index 1b935ae..79615e5 100644
--- a/nashorn/test/script/basic/NASHORN-473.js
+++ b/nashorn/test/script/basic/NASHORN-473.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-474.js b/nashorn/test/script/basic/NASHORN-474.js
index 3df4aa4d..69b351f 100644
--- a/nashorn/test/script/basic/NASHORN-474.js
+++ b/nashorn/test/script/basic/NASHORN-474.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-478.js b/nashorn/test/script/basic/NASHORN-478.js
index 945d2b5..dd851bc 100644
--- a/nashorn/test/script/basic/NASHORN-478.js
+++ b/nashorn/test/script/basic/NASHORN-478.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-48.js b/nashorn/test/script/basic/NASHORN-48.js
index 1bbba13..9fe4076 100644
--- a/nashorn/test/script/basic/NASHORN-48.js
+++ b/nashorn/test/script/basic/NASHORN-48.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,9 +29,9 @@
  */
 
 function loop3() {
-    for (var i = 0; i < 5; i++) { 
-	print(i);
-	throw "ERROR";
+    for (var i = 0; i < 5; i++) {
+    print(i);
+    throw "ERROR";
     }
     print("dead");
 }
@@ -41,17 +41,17 @@
 } catch (e) {
     print(e);
 }
- 
+
 function loop4() {
     var i = 0;
     while (i++ < 5) {
-	print(i);
-	throw "ERROR";
+    print(i);
+    throw "ERROR";
     }
     print("dead");
 }
 
-try {    
+try {
     loop4();
 } catch (e) {
     print(e);
@@ -60,13 +60,13 @@
 function loop5() {
     var i = 0;
     do {
-	print(i);
-	throw "ERROR";
+    print(i);
+    throw "ERROR";
     } while (i++ < 5);
     print("dead");
 }
 
-try {    
+try {
     loop5();
 } catch (e) {
     print(e);
diff --git a/nashorn/test/script/basic/NASHORN-481.js b/nashorn/test/script/basic/NASHORN-481.js
index 42295fa..571b7bf 100644
--- a/nashorn/test/script/basic/NASHORN-481.js
+++ b/nashorn/test/script/basic/NASHORN-481.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -10029,7 +10029,7 @@
     "tag": "mesoventral",
     "popularity": 4096
   }];
-  
+
 var entry = largeTable[1000];
 print(entry.tag, entry.popularity);
 
diff --git a/nashorn/test/script/basic/NASHORN-482.js b/nashorn/test/script/basic/NASHORN-482.js
index 76afb59..b3e0344 100644
--- a/nashorn/test/script/basic/NASHORN-482.js
+++ b/nashorn/test/script/basic/NASHORN-482.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-484.js b/nashorn/test/script/basic/NASHORN-484.js
index b1f0a0e..ec8a20f 100644
--- a/nashorn/test/script/basic/NASHORN-484.js
+++ b/nashorn/test/script/basic/NASHORN-484.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-486.js b/nashorn/test/script/basic/NASHORN-486.js
index f03f096..e0d7bda 100644
--- a/nashorn/test/script/basic/NASHORN-486.js
+++ b/nashorn/test/script/basic/NASHORN-486.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
 
 try {
     // save line number and force ReferenceError for 'foo'
-    var lineNumber = __LINE__; print(foo); 
+    var lineNumber = __LINE__; print(foo);
     fail("#1 should have thrown ReferenceError");
 } catch (e) {
     if (! (e instanceof ReferenceError)) {
diff --git a/nashorn/test/script/basic/NASHORN-487.js b/nashorn/test/script/basic/NASHORN-487.js
index c568591..38d020d 100644
--- a/nashorn/test/script/basic/NASHORN-487.js
+++ b/nashorn/test/script/basic/NASHORN-487.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-488.js b/nashorn/test/script/basic/NASHORN-488.js
index 53bb888..342630f 100644
--- a/nashorn/test/script/basic/NASHORN-488.js
+++ b/nashorn/test/script/basic/NASHORN-488.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -34,7 +34,7 @@
 }
 
 Object.defineProperty(Function.prototype, "prototype", {
-    set: undefined, get: function() { return 32; }, 
+    set: undefined, get: function() { return 32; },
     configurable: true
 });
 
diff --git a/nashorn/test/script/basic/NASHORN-49.js b/nashorn/test/script/basic/NASHORN-49.js
index 1b4a68c..e90444a 100644
--- a/nashorn/test/script/basic/NASHORN-49.js
+++ b/nashorn/test/script/basic/NASHORN-49.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-490.js b/nashorn/test/script/basic/NASHORN-490.js
index e9bdd93..1966d37 100644
--- a/nashorn/test/script/basic/NASHORN-490.js
+++ b/nashorn/test/script/basic/NASHORN-490.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-494.js b/nashorn/test/script/basic/NASHORN-494.js
index 18d19c8..ac652da 100644
--- a/nashorn/test/script/basic/NASHORN-494.js
+++ b/nashorn/test/script/basic/NASHORN-494.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-497.js b/nashorn/test/script/basic/NASHORN-497.js
index ad8b4eb..294bdb2 100644
--- a/nashorn/test/script/basic/NASHORN-497.js
+++ b/nashorn/test/script/basic/NASHORN-497.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-498.js b/nashorn/test/script/basic/NASHORN-498.js
index 6304788..ad156db 100644
--- a/nashorn/test/script/basic/NASHORN-498.js
+++ b/nashorn/test/script/basic/NASHORN-498.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,13 +30,13 @@
 
 // no syntax error expected for the following functions
 function func() {
-    // Parser thinks it is a for-in statement! But 'in' used in 
+    // Parser thinks it is a for-in statement! But 'in' used in
     // cond. expression. This is a normal for statement
     for (var x = a ? b in c : 3;;) {}
 }
 
 function func2() {
-    // for-in statement but init is cond. expression with 'in' 
+    // for-in statement but init is cond. expression with 'in'
     // This is same as "for (var x = (a? b in c : e) in {} )"
     for (var x = a ? b in c : e in {}) {}
 }
diff --git a/nashorn/test/script/basic/NASHORN-499.js b/nashorn/test/script/basic/NASHORN-499.js
index bbedb05..3483775 100644
--- a/nashorn/test/script/basic/NASHORN-499.js
+++ b/nashorn/test/script/basic/NASHORN-499.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-50.js b/nashorn/test/script/basic/NASHORN-50.js
index 7292b95..08f8fdd 100644
--- a/nashorn/test/script/basic/NASHORN-50.js
+++ b/nashorn/test/script/basic/NASHORN-50.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 try {
     for (var y in null)  {
-	y = 2;
+    y = 2;
     }
 } catch (e) {
     print(e);
@@ -38,7 +38,7 @@
 
 try {
     for (var y in undefined) {
-	y = 2;
+    y = 2;
     }
 } catch (e) {
     print(e);
diff --git a/nashorn/test/script/basic/NASHORN-500.js b/nashorn/test/script/basic/NASHORN-500.js
index 30546e8..62444b9 100644
--- a/nashorn/test/script/basic/NASHORN-500.js
+++ b/nashorn/test/script/basic/NASHORN-500.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,7 +29,7 @@
  */
 
 var origToString = Object.prototype.toString;
-Object.prototype.toString = function () { 
+Object.prototype.toString = function () {
     return this.myStr();
 }
 
diff --git a/nashorn/test/script/basic/NASHORN-503.js b/nashorn/test/script/basic/NASHORN-503.js
index 5083881..f1a01d8 100644
--- a/nashorn/test/script/basic/NASHORN-503.js
+++ b/nashorn/test/script/basic/NASHORN-503.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-51.js b/nashorn/test/script/basic/NASHORN-51.js
index 45d00e9..6cf68a4 100644
--- a/nashorn/test/script/basic/NASHORN-51.js
+++ b/nashorn/test/script/basic/NASHORN-51.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-511.js b/nashorn/test/script/basic/NASHORN-511.js
index edac1a9..c382468 100644
--- a/nashorn/test/script/basic/NASHORN-511.js
+++ b/nashorn/test/script/basic/NASHORN-511.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-515.js b/nashorn/test/script/basic/NASHORN-515.js
index 198be1f..09a6b7a 100644
--- a/nashorn/test/script/basic/NASHORN-515.js
+++ b/nashorn/test/script/basic/NASHORN-515.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,17 +30,17 @@
 
 function a() {
     var x = (3.14-2.14);
-    
+
     switch (x) {
     case 1:
-	print("--1"); 
-	break;
+    print("--1");
+    break;
     case 2:
-	print("--2"); 
-	break;
+    print("--2");
+    break;
     default:
-	print("default");
-	break;
+    print("default");
+    break;
     }
 }
 
@@ -50,11 +50,11 @@
     switch (index) {
     case 0x00:
     case 0x01:
-	print("one zero");
-	break;
+    print("one zero");
+    break;
     default:
-	print("default");
-	break;
+    print("default");
+    break;
     }
 }
 
@@ -64,76 +64,76 @@
     switch (index) {
     case 0x00:
     case 0x01:
-	print("one zero");
-	break;
+    print("one zero");
+    break;
     default:
-	print("default");
+    print("default");
     }
     --index;
 }
 
 function d() {
     var x = (3.14-1.14);
-    
+
     switch(x) {
     case 1:
-	print("--1"); break;
+    print("--1"); break;
     case 2:
-	print("--2"); break;
+    print("--2"); break;
     case 3:
-	print("--3"); break;
+    print("--3"); break;
     case 4:
-	print("--4"); break;
+    print("--4"); break;
     default:
-	print("default");
+    print("default");
     }
 }
 
 function e() {
     var y = 2147483647;
-    
+
     switch(y) {
     case -2147483648:
-	print("MIN_INT"); break;
+    print("MIN_INT"); break;
     case -2147483647:
-	print("MIN_INT+1"); break;
+    print("MIN_INT+1"); break;
     case 2147483647:
-	print("MAX_INT"); break;
+    print("MAX_INT"); break;
     case 1:
-	print("--1"); break;
+    print("--1"); break;
     case 2:
-	print("--2"); break;
+    print("--2"); break;
     case 3:
-	print("--3"); break;
+    print("--3"); break;
     case 4:
-	print("--4"); break;
+    print("--4"); break;
     default:
-	print("default");
+    print("default");
     }
 }
 
 function f() {
     var z = 2;
-    
+
     switch(z) {
     case -2147483648:
-	print("MIN_INT"); break;
+    print("MIN_INT"); break;
     case -2147483647:
-	print("MIN_INT+1"); break;
+    print("MIN_INT+1"); break;
     case 2147483647:
-	print("MAX_INT"); break;
+    print("MAX_INT"); break;
     case 1:
-	print("--1"); break;
+    print("--1"); break;
     case 2:
-	print("--2 first"); break;
+    print("--2 first"); break;
     case 2:
-	print("--2 second"); break;
+    print("--2 second"); break;
     case 3:
-	print("--3"); break;
+    print("--3"); break;
     case 4:
-	print("--4"); break;
+    print("--4"); break;
     default:
-	print("default");
+    print("default");
     }
 }
 
diff --git a/nashorn/test/script/basic/NASHORN-516.js b/nashorn/test/script/basic/NASHORN-516.js
index f369b9c..04d2bfd 100644
--- a/nashorn/test/script/basic/NASHORN-516.js
+++ b/nashorn/test/script/basic/NASHORN-516.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-52.js b/nashorn/test/script/basic/NASHORN-52.js
index 1727e02..2dc449e 100644
--- a/nashorn/test/script/basic/NASHORN-52.js
+++ b/nashorn/test/script/basic/NASHORN-52.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-534.js b/nashorn/test/script/basic/NASHORN-534.js
index ab7a9b9..3124f43 100644
--- a/nashorn/test/script/basic/NASHORN-534.js
+++ b/nashorn/test/script/basic/NASHORN-534.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-535.js b/nashorn/test/script/basic/NASHORN-535.js
index 57abfc4..93ae82f 100644
--- a/nashorn/test/script/basic/NASHORN-535.js
+++ b/nashorn/test/script/basic/NASHORN-535.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-544.js b/nashorn/test/script/basic/NASHORN-544.js
index 87c6cae..34f46ca 100644
--- a/nashorn/test/script/basic/NASHORN-544.js
+++ b/nashorn/test/script/basic/NASHORN-544.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-55.js b/nashorn/test/script/basic/NASHORN-55.js
index 58576a1..0d7fa07 100644
--- a/nashorn/test/script/basic/NASHORN-55.js
+++ b/nashorn/test/script/basic/NASHORN-55.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-554.js b/nashorn/test/script/basic/NASHORN-554.js
index 4c7ae87..87d49ec 100644
--- a/nashorn/test/script/basic/NASHORN-554.js
+++ b/nashorn/test/script/basic/NASHORN-554.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-556.js b/nashorn/test/script/basic/NASHORN-556.js
index 1332d02..3ddd20b 100644
--- a/nashorn/test/script/basic/NASHORN-556.js
+++ b/nashorn/test/script/basic/NASHORN-556.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-56.js b/nashorn/test/script/basic/NASHORN-56.js
index 4722845..7895a8e 100644
--- a/nashorn/test/script/basic/NASHORN-56.js
+++ b/nashorn/test/script/basic/NASHORN-56.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-562.js b/nashorn/test/script/basic/NASHORN-562.js
index 2754cba..4fd9dc3 100644
--- a/nashorn/test/script/basic/NASHORN-562.js
+++ b/nashorn/test/script/basic/NASHORN-562.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-565.js b/nashorn/test/script/basic/NASHORN-565.js
index ad789ce..79bd012 100644
--- a/nashorn/test/script/basic/NASHORN-565.js
+++ b/nashorn/test/script/basic/NASHORN-565.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-575.js b/nashorn/test/script/basic/NASHORN-575.js
index 4eda079..6341ffe 100644
--- a/nashorn/test/script/basic/NASHORN-575.js
+++ b/nashorn/test/script/basic/NASHORN-575.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-58.js b/nashorn/test/script/basic/NASHORN-58.js
index b0aeaa4..1a55c3b 100644
--- a/nashorn/test/script/basic/NASHORN-58.js
+++ b/nashorn/test/script/basic/NASHORN-58.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,14 +30,14 @@
 
 function test1() {
     var x = 1;
-    try { 
-	print('try'); 
-	x = 2; 
+    try {
+    print('try');
+    x = 2;
     } catch(e) {
-	print('catch');
-    } finally { 
-	print('finally');
-	x = 3; 
+    print('catch');
+    } finally {
+    print('finally');
+    x = 3;
     }
     print(x);
 }
@@ -45,81 +45,81 @@
 function test2() {
     var x = 1;
     try {
-	print('try');
+    print('try');
     } finally {
-	print('finally');
-	x = 2;
+    print('finally');
+    x = 2;
     }
     print(x);
 }
 
 function test3() {
     try {
-	return 2;
+    return 2;
     } finally {
-	return 3;
+    return 3;
     }
 }
 
 function test4() {
     try {
-	x = 1;
-	print(x);
-	try {
-	    x = 2;
-	    print(x);
-	} finally {
-	    x = 3;
-	    print(x)
-	    try {
-		x = 4;
-		print(x);
-	    } finally {
-		x = 5;
-		print(x);
-	    }
-	}
-	print(x)
+    x = 1;
+    print(x);
+    try {
+        x = 2;
+        print(x);
     } finally {
-	x = 6;
-	print(x);
+        x = 3;
+        print(x)
+        try {
+        x = 4;
+        print(x);
+        } finally {
+        x = 5;
+        print(x);
+        }
+    }
+    print(x)
+    } finally {
+    x = 6;
+    print(x);
     }
     print(x);
 }
 
 function test5() {
     try {
-	x = 1;
-	print(x);
-	try {
-	    x = 2;
-	    print(x);
-	} finally {
-	    x = 3;
-	    print(x)
-	    try {
-		x = 4;
-		print(x);
-	    } finally {
-		x = 5;
-		return x;
-	    }
-	}
-	print(x)
+    x = 1;
+    print(x);
+    try {
+        x = 2;
+        print(x);
     } finally {
-	x = 6;
-	return x;
+        x = 3;
+        print(x)
+        try {
+        x = 4;
+        print(x);
+        } finally {
+        x = 5;
+        return x;
+        }
+    }
+    print(x)
+    } finally {
+    x = 6;
+    return x;
     }
 }
 
 function test6() {
     try {
-	throw new Error("testing");
+    throw new Error("testing");
     } catch (ex) {
-	print(ex);
-	return;
+    print(ex);
+    return;
     } finally {
-	print("finally");
+    print("finally");
     }
 }
 
@@ -133,7 +133,7 @@
         i++;
     }
     if (i != 4) {
-	print("FAIL");
+    print("FAIL");
     }
     print("SUCCESS");
 }
diff --git a/nashorn/test/script/basic/NASHORN-59.js b/nashorn/test/script/basic/NASHORN-59.js
index 1379fa6..3a1c6eb 100644
--- a/nashorn/test/script/basic/NASHORN-59.js
+++ b/nashorn/test/script/basic/NASHORN-59.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-592-dual.js b/nashorn/test/script/basic/NASHORN-592-dual.js
index 73dd815..e7c5ed3 100644
--- a/nashorn/test/script/basic/NASHORN-592-dual.js
+++ b/nashorn/test/script/basic/NASHORN-592-dual.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-592.js b/nashorn/test/script/basic/NASHORN-592.js
index cbc2984..99a2006 100644
--- a/nashorn/test/script/basic/NASHORN-592.js
+++ b/nashorn/test/script/basic/NASHORN-592.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-597.js b/nashorn/test/script/basic/NASHORN-597.js
index 7195b05..f413d5f 100644
--- a/nashorn/test/script/basic/NASHORN-597.js
+++ b/nashorn/test/script/basic/NASHORN-597.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-60.js b/nashorn/test/script/basic/NASHORN-60.js
index 338c237..e1a5e72 100644
--- a/nashorn/test/script/basic/NASHORN-60.js
+++ b/nashorn/test/script/basic/NASHORN-60.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-609.js b/nashorn/test/script/basic/NASHORN-609.js
index 5c84f01..d6c22a0 100644
--- a/nashorn/test/script/basic/NASHORN-609.js
+++ b/nashorn/test/script/basic/NASHORN-609.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-61.js b/nashorn/test/script/basic/NASHORN-61.js
index 0c7f235..4444b50 100644
--- a/nashorn/test/script/basic/NASHORN-61.js
+++ b/nashorn/test/script/basic/NASHORN-61.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-62.js b/nashorn/test/script/basic/NASHORN-62.js
index a3ba6e2..bb8a650 100644
--- a/nashorn/test/script/basic/NASHORN-62.js
+++ b/nashorn/test/script/basic/NASHORN-62.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-620.js b/nashorn/test/script/basic/NASHORN-620.js
index ce99528..94ee9c6 100644
--- a/nashorn/test/script/basic/NASHORN-620.js
+++ b/nashorn/test/script/basic/NASHORN-620.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-623.js b/nashorn/test/script/basic/NASHORN-623.js
index 8ecdb13..31c6f71 100644
--- a/nashorn/test/script/basic/NASHORN-623.js
+++ b/nashorn/test/script/basic/NASHORN-623.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-627.js b/nashorn/test/script/basic/NASHORN-627.js
index 07662ff..995cb4f 100644
--- a/nashorn/test/script/basic/NASHORN-627.js
+++ b/nashorn/test/script/basic/NASHORN-627.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-63.js b/nashorn/test/script/basic/NASHORN-63.js
index f1178de..83df17e 100644
--- a/nashorn/test/script/basic/NASHORN-63.js
+++ b/nashorn/test/script/basic/NASHORN-63.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -64,7 +64,7 @@
     error('Different Objects are equal');
 }
 
-var obj1 = {}; 
+var obj1 = {};
 var obj2 = obj1;
 if (obj1 != obj2) {
     error(' Same object literals are not equal');
diff --git a/nashorn/test/script/basic/NASHORN-637.js b/nashorn/test/script/basic/NASHORN-637.js
index 606d893..00134a4 100644
--- a/nashorn/test/script/basic/NASHORN-637.js
+++ b/nashorn/test/script/basic/NASHORN-637.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-639.js b/nashorn/test/script/basic/NASHORN-639.js
index fcc02e0..6047b02 100644
--- a/nashorn/test/script/basic/NASHORN-639.js
+++ b/nashorn/test/script/basic/NASHORN-639.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-64.js b/nashorn/test/script/basic/NASHORN-64.js
index 03d95b2..de062ef 100644
--- a/nashorn/test/script/basic/NASHORN-64.js
+++ b/nashorn/test/script/basic/NASHORN-64.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-642.js b/nashorn/test/script/basic/NASHORN-642.js
index acbd602..a751c18 100644
--- a/nashorn/test/script/basic/NASHORN-642.js
+++ b/nashorn/test/script/basic/NASHORN-642.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-646.js b/nashorn/test/script/basic/NASHORN-646.js
index 493a798..3702288 100644
--- a/nashorn/test/script/basic/NASHORN-646.js
+++ b/nashorn/test/script/basic/NASHORN-646.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-658.js b/nashorn/test/script/basic/NASHORN-658.js
index 13e5e29..2d5a8ad 100644
--- a/nashorn/test/script/basic/NASHORN-658.js
+++ b/nashorn/test/script/basic/NASHORN-658.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-659.js b/nashorn/test/script/basic/NASHORN-659.js
index 7c6c150..2abe992 100644
--- a/nashorn/test/script/basic/NASHORN-659.js
+++ b/nashorn/test/script/basic/NASHORN-659.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-66.js b/nashorn/test/script/basic/NASHORN-66.js
index f1455ff..8860853 100644
--- a/nashorn/test/script/basic/NASHORN-66.js
+++ b/nashorn/test/script/basic/NASHORN-66.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-664.js b/nashorn/test/script/basic/NASHORN-664.js
index 268d5df..4856004 100644
--- a/nashorn/test/script/basic/NASHORN-664.js
+++ b/nashorn/test/script/basic/NASHORN-664.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -34,11 +34,11 @@
     e.fileName = "foo";
     if (e.fileName !== 'foo') {
         fail("can not set e.fileName");
-    } 
+    }
     e.lineNumber = 100;
     if (e.lineNumber !== 100) {
         fail("can not set e.lineNumber");
-    } 
+    }
     e.columnNumber = 33;
     if (e.columnNumber !== 33) {
         fail("can not set e.columnNumber");
diff --git a/nashorn/test/script/basic/NASHORN-665.js b/nashorn/test/script/basic/NASHORN-665.js
index 54e7f08..c1b8a28 100644
--- a/nashorn/test/script/basic/NASHORN-665.js
+++ b/nashorn/test/script/basic/NASHORN-665.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-67.js b/nashorn/test/script/basic/NASHORN-67.js
index b273b42..33fbd49 100644
--- a/nashorn/test/script/basic/NASHORN-67.js
+++ b/nashorn/test/script/basic/NASHORN-67.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,15 +30,15 @@
 
 function test_nested() {
       try {
-	  try {	      
-	      throw new Error("bam!");
-	  } catch (e) {
-	      print("SUCCESS")
-	  }
+      try {
+          throw new Error("bam!");
+      } catch (e) {
+          print("SUCCESS")
+      }
       } catch (e2) {
-	  fail("inner catch should have caught the exception");
-      } 
-      
+      fail("inner catch should have caught the exception");
+      }
+
 }
 
 test_nested()
diff --git a/nashorn/test/script/basic/NASHORN-678.js b/nashorn/test/script/basic/NASHORN-678.js
index e585eb8..e40ef17 100644
--- a/nashorn/test/script/basic/NASHORN-678.js
+++ b/nashorn/test/script/basic/NASHORN-678.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -41,7 +41,7 @@
 
 try {
     33();
-    fail("should have thrown error"); 
+    fail("should have thrown error");
 } catch (e) {
     if (! (e instanceof TypeError)) {
         fail("expected TypeError, got " + e);
diff --git a/nashorn/test/script/basic/NASHORN-68.js b/nashorn/test/script/basic/NASHORN-68.js
index d56da36..31fa3e5 100644
--- a/nashorn/test/script/basic/NASHORN-68.js
+++ b/nashorn/test/script/basic/NASHORN-68.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-689.js b/nashorn/test/script/basic/NASHORN-689.js
index 938b111..1a49e8e 100644
--- a/nashorn/test/script/basic/NASHORN-689.js
+++ b/nashorn/test/script/basic/NASHORN-689.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-69.js b/nashorn/test/script/basic/NASHORN-69.js
index 9ec39a3..aeefaf0 100644
--- a/nashorn/test/script/basic/NASHORN-69.js
+++ b/nashorn/test/script/basic/NASHORN-69.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-691.js b/nashorn/test/script/basic/NASHORN-691.js
index ec36eed..3a7b9f3 100644
--- a/nashorn/test/script/basic/NASHORN-691.js
+++ b/nashorn/test/script/basic/NASHORN-691.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-694.js b/nashorn/test/script/basic/NASHORN-694.js
index eb1d294..3beb281 100644
--- a/nashorn/test/script/basic/NASHORN-694.js
+++ b/nashorn/test/script/basic/NASHORN-694.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-697.js b/nashorn/test/script/basic/NASHORN-697.js
index 012f33b..f88e271 100644
--- a/nashorn/test/script/basic/NASHORN-697.js
+++ b/nashorn/test/script/basic/NASHORN-697.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-703.js b/nashorn/test/script/basic/NASHORN-703.js
index 41d3570..4d74976b 100644
--- a/nashorn/test/script/basic/NASHORN-703.js
+++ b/nashorn/test/script/basic/NASHORN-703.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
  * This file is split into two tests as the presence of eval affects the whole script
  *
  * @test
- * @run 
+ * @run
  */
 
 function template() {
diff --git a/nashorn/test/script/basic/NASHORN-703a.js b/nashorn/test/script/basic/NASHORN-703a.js
index 18c26a4..d24d2bd 100644
--- a/nashorn/test/script/basic/NASHORN-703a.js
+++ b/nashorn/test/script/basic/NASHORN-703a.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
  * This file is split into two tests as the presence of eval affects the whole script
  *
  * @test
- * @run 
+ * @run
  */
 
 function template() {
diff --git a/nashorn/test/script/basic/NASHORN-705.js b/nashorn/test/script/basic/NASHORN-705.js
index a65ef84..de84c4b 100644
--- a/nashorn/test/script/basic/NASHORN-705.js
+++ b/nashorn/test/script/basic/NASHORN-705.js
@@ -2,21 +2,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-71.js b/nashorn/test/script/basic/NASHORN-71.js
index 913ff76..5daf359 100644
--- a/nashorn/test/script/basic/NASHORN-71.js
+++ b/nashorn/test/script/basic/NASHORN-71.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-710.js b/nashorn/test/script/basic/NASHORN-710.js
index 83b1778..9aecf60 100644
--- a/nashorn/test/script/basic/NASHORN-710.js
+++ b/nashorn/test/script/basic/NASHORN-710.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-711.js b/nashorn/test/script/basic/NASHORN-711.js
index af6e9c8..ce0cafe 100644
--- a/nashorn/test/script/basic/NASHORN-711.js
+++ b/nashorn/test/script/basic/NASHORN-711.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-72.js b/nashorn/test/script/basic/NASHORN-72.js
index edf0a23..548844b 100644
--- a/nashorn/test/script/basic/NASHORN-72.js
+++ b/nashorn/test/script/basic/NASHORN-72.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-722.js b/nashorn/test/script/basic/NASHORN-722.js
index e1584ab..f51d5dd 100644
--- a/nashorn/test/script/basic/NASHORN-722.js
+++ b/nashorn/test/script/basic/NASHORN-722.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-73.js b/nashorn/test/script/basic/NASHORN-73.js
index 04c9690..d565c1d 100644
--- a/nashorn/test/script/basic/NASHORN-73.js
+++ b/nashorn/test/script/basic/NASHORN-73.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -50,8 +50,8 @@
 
 while (true) {
     break;
-    if (true) { 
-	var s; 
+    if (true) {
+    var s;
     }
 }
 
@@ -61,20 +61,20 @@
 for ( ; ; ) {
     break;
     while (true) {
-	do {
-	    var u;
-	} while (true);
-    }    
+    do {
+        var u;
+    } while (true);
+    }
 }
 
 function terminal() {
     print("r = "+r);
     print("t = "+t);
     for (;;) {
-	var r;
-	return;
-	var t;
-	print("THIS SHOULD NEVER BE PRINTED!");
+    var r;
+    return;
+    var t;
+    print("THIS SHOULD NEVER BE PRINTED!");
     }
     print("NEITHER SHOULD THIS");
 }
@@ -84,13 +84,13 @@
 function terminal2() {
     print("q = "+q);
     for (;;) {
-	return;
-	print("THIS SHOULD NEVER BE PRINTED!");
+    return;
+    print("THIS SHOULD NEVER BE PRINTED!");
     }
     print("NEITHER SHOULD THIS");
 }
 
-try { 
+try {
     terminal2();
 } catch (e) {
     print(e);
@@ -108,13 +108,13 @@
 }  catch (e) {
     print(e);
 }
-	
+
 
 function disp_a() {
     var a = 20;
     print("Value of 'a' inside the function " + a);
 }
-	
+
 var a = 10;
 
 disp_a();
diff --git a/nashorn/test/script/basic/NASHORN-737.js b/nashorn/test/script/basic/NASHORN-737.js
index 3db4891..146da9d 100644
--- a/nashorn/test/script/basic/NASHORN-737.js
+++ b/nashorn/test/script/basic/NASHORN-737.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-737.js.EXPECTED b/nashorn/test/script/basic/NASHORN-737.js.EXPECTED
index 77c7965..3a33d9f 100644
--- a/nashorn/test/script/basic/NASHORN-737.js.EXPECTED
+++ b/nashorn/test/script/basic/NASHORN-737.js.EXPECTED
@@ -3,10 +3,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "label"
-            },
+            "label": "label",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -21,10 +18,7 @@
                             "body": [
                                 {
                                     "type": "BreakStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "label"
-                                    }
+                                    "label": "label"
                                 }
                             ]
                         }
diff --git a/nashorn/test/script/basic/NASHORN-74.js b/nashorn/test/script/basic/NASHORN-74.js
index 1d44e06..9a384ac 100644
--- a/nashorn/test/script/basic/NASHORN-74.js
+++ b/nashorn/test/script/basic/NASHORN-74.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-740.js b/nashorn/test/script/basic/NASHORN-740.js
index 553efdd..589777b 100644
--- a/nashorn/test/script/basic/NASHORN-740.js
+++ b/nashorn/test/script/basic/NASHORN-740.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-75.js b/nashorn/test/script/basic/NASHORN-75.js
index ebcd782..8e446ff 100644
--- a/nashorn/test/script/basic/NASHORN-75.js
+++ b/nashorn/test/script/basic/NASHORN-75.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-758.js b/nashorn/test/script/basic/NASHORN-758.js
index f57eaf1..2942161 100644
--- a/nashorn/test/script/basic/NASHORN-758.js
+++ b/nashorn/test/script/basic/NASHORN-758.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-759.js b/nashorn/test/script/basic/NASHORN-759.js
index 09d2b3e..41c5974 100644
--- a/nashorn/test/script/basic/NASHORN-759.js
+++ b/nashorn/test/script/basic/NASHORN-759.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-760.js b/nashorn/test/script/basic/NASHORN-760.js
index 1974dde..d8492b7 100644
--- a/nashorn/test/script/basic/NASHORN-760.js
+++ b/nashorn/test/script/basic/NASHORN-760.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,8 +29,8 @@
  */
 // problem 1
 // the conversions in TernaryNode are not necessary, but they should not cause problems. They did
-// this was because the result of Global.allocate(Object[])Object which returns a NativeObject. 
-// was tracked as an object type on our stack. The type system did not recognize this as an array. 
+// this was because the result of Global.allocate(Object[])Object which returns a NativeObject.
+// was tracked as an object type on our stack. The type system did not recognize this as an array.
 // Then the explicit conversions became "convert NativeArray->Object[]" which is a checkccast Object[]
 // which naturally failed.
 
diff --git a/nashorn/test/script/basic/NASHORN-768.js b/nashorn/test/script/basic/NASHORN-768.js
index 5723d6d..a3bea4f 100644
--- a/nashorn/test/script/basic/NASHORN-768.js
+++ b/nashorn/test/script/basic/NASHORN-768.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -46,7 +46,7 @@
 // global object
 var obj = {
     foo: 42,
-    bar: function(x) { 
+    bar: function(x) {
         if (id != "engine-global-id") {
             throw "id != 'engine-global-id'";
         }
diff --git a/nashorn/test/script/basic/NASHORN-778.js b/nashorn/test/script/basic/NASHORN-778.js
index b165882..654a877 100644
--- a/nashorn/test/script/basic/NASHORN-778.js
+++ b/nashorn/test/script/basic/NASHORN-778.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-78.js b/nashorn/test/script/basic/NASHORN-78.js
index 549164d..3f6ff08 100644
--- a/nashorn/test/script/basic/NASHORN-78.js
+++ b/nashorn/test/script/basic/NASHORN-78.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-79.js b/nashorn/test/script/basic/NASHORN-79.js
index d6f1e05..d2893b3 100644
--- a/nashorn/test/script/basic/NASHORN-79.js
+++ b/nashorn/test/script/basic/NASHORN-79.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,8 +32,8 @@
 print((function f(a) {
     return a == 0? 1 : a*f(a-1);
 })(4));
- 
- 
+
+
 print((function g(a) {
     function g(a) { return 1000; }
     return a == 0? 1 : a*g(a-1);
diff --git a/nashorn/test/script/basic/NASHORN-792.js b/nashorn/test/script/basic/NASHORN-792.js
index 3ba0102..3b38777 100644
--- a/nashorn/test/script/basic/NASHORN-792.js
+++ b/nashorn/test/script/basic/NASHORN-792.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-80.js b/nashorn/test/script/basic/NASHORN-80.js
index aeb496f..e6505c4d 100644
--- a/nashorn/test/script/basic/NASHORN-80.js
+++ b/nashorn/test/script/basic/NASHORN-80.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-81.js b/nashorn/test/script/basic/NASHORN-81.js
index 44cda68..e0b9bdf 100644
--- a/nashorn/test/script/basic/NASHORN-81.js
+++ b/nashorn/test/script/basic/NASHORN-81.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-833.js b/nashorn/test/script/basic/NASHORN-833.js
index b3d0d31..dc25d2d 100644
--- a/nashorn/test/script/basic/NASHORN-833.js
+++ b/nashorn/test/script/basic/NASHORN-833.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-837.js b/nashorn/test/script/basic/NASHORN-837.js
index ef9ec64..9991270 100644
--- a/nashorn/test/script/basic/NASHORN-837.js
+++ b/nashorn/test/script/basic/NASHORN-837.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-85.js b/nashorn/test/script/basic/NASHORN-85.js
index bdad20f..3d6d3e8 100644
--- a/nashorn/test/script/basic/NASHORN-85.js
+++ b/nashorn/test/script/basic/NASHORN-85.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-86.js b/nashorn/test/script/basic/NASHORN-86.js
index 0723726..67711d5 100644
--- a/nashorn/test/script/basic/NASHORN-86.js
+++ b/nashorn/test/script/basic/NASHORN-86.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-87.js b/nashorn/test/script/basic/NASHORN-87.js
index 2283dcd..63896b7 100644
--- a/nashorn/test/script/basic/NASHORN-87.js
+++ b/nashorn/test/script/basic/NASHORN-87.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-89.js b/nashorn/test/script/basic/NASHORN-89.js
index 5491239..470d5b0 100644
--- a/nashorn/test/script/basic/NASHORN-89.js
+++ b/nashorn/test/script/basic/NASHORN-89.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-90.js b/nashorn/test/script/basic/NASHORN-90.js
index 99c2a4a..3fc3729 100644
--- a/nashorn/test/script/basic/NASHORN-90.js
+++ b/nashorn/test/script/basic/NASHORN-90.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-91.js b/nashorn/test/script/basic/NASHORN-91.js
index 1e1df61..4aab313 100644
--- a/nashorn/test/script/basic/NASHORN-91.js
+++ b/nashorn/test/script/basic/NASHORN-91.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-92.js b/nashorn/test/script/basic/NASHORN-92.js
index a05997f..715505a 100644
--- a/nashorn/test/script/basic/NASHORN-92.js
+++ b/nashorn/test/script/basic/NASHORN-92.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-93.js b/nashorn/test/script/basic/NASHORN-93.js
index c424728..ba4c056 100644
--- a/nashorn/test/script/basic/NASHORN-93.js
+++ b/nashorn/test/script/basic/NASHORN-93.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-95.js b/nashorn/test/script/basic/NASHORN-95.js
index 38d7285..2ba9403 100644
--- a/nashorn/test/script/basic/NASHORN-95.js
+++ b/nashorn/test/script/basic/NASHORN-95.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-96.js b/nashorn/test/script/basic/NASHORN-96.js
index 451b018..159e2b2 100644
--- a/nashorn/test/script/basic/NASHORN-96.js
+++ b/nashorn/test/script/basic/NASHORN-96.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-97.js b/nashorn/test/script/basic/NASHORN-97.js
index 0f7128a..d103ff5 100644
--- a/nashorn/test/script/basic/NASHORN-97.js
+++ b/nashorn/test/script/basic/NASHORN-97.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/NASHORN-98.js b/nashorn/test/script/basic/NASHORN-98.js
index 9e341e0..9c23c08 100644
--- a/nashorn/test/script/basic/NASHORN-98.js
+++ b/nashorn/test/script/basic/NASHORN-98.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -35,7 +35,7 @@
        fail("syntax error expected here got " + e);
     }
     printError(e);
-} 
+}
 
 try {
     eval("var x = { foo: 33 bar: 'hello' }");
@@ -44,4 +44,4 @@
        fail("syntax error expected here got " + e);
     }
     printError(e);
-} 
+}
diff --git a/nashorn/test/script/basic/NASHORN-99.js b/nashorn/test/script/basic/NASHORN-99.js
index eaf717a..7c14e4e 100644
--- a/nashorn/test/script/basic/NASHORN-99.js
+++ b/nashorn/test/script/basic/NASHORN-99.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/access-specializer.js b/nashorn/test/script/basic/access-specializer.js
index d60260a..7163318 100644
--- a/nashorn/test/script/basic/access-specializer.js
+++ b/nashorn/test/script/basic/access-specializer.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,9 +24,9 @@
 /**
  * This is a simple test that checks that access specialization in FinalizeTypes is consistent.
  * Here, a2 = 0 will be turned int {I}a2 = 0, and all would be fine and well, only we can't change
- * the symbol type for a2 from double, and we can't as it's not a temporary. Either we have to put 
+ * the symbol type for a2 from double, and we can't as it's not a temporary. Either we have to put
  * a temporary in at the late finalize stage and add another assignment, or we genericize the check
- * in CodeGenerator#Store so we detect whether a target is of the wrong type before storing. It 
+ * in CodeGenerator#Store so we detect whether a target is of the wrong type before storing. It
  * is hopefully very rare, and will only be a problem when assignment results that have been
  * specialized live on the stack
  *
diff --git a/nashorn/test/script/basic/addition.js b/nashorn/test/script/basic/addition.js
index 6f8d099..31ea6f2 100644
--- a/nashorn/test/script/basic/addition.js
+++ b/nashorn/test/script/basic/addition.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/allgettersetters.js b/nashorn/test/script/basic/allgettersetters.js
index 1cb9562..c6e3425 100644
--- a/nashorn/test/script/basic/allgettersetters.js
+++ b/nashorn/test/script/basic/allgettersetters.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/andor.js b/nashorn/test/script/basic/andor.js
index 7d65ee1..9a1ff8b 100644
--- a/nashorn/test/script/basic/andor.js
+++ b/nashorn/test/script/basic/andor.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * and or test.
  *
  * @test
- * @run 
+ * @run
  */
 
 print("a" && "b");
diff --git a/nashorn/test/script/basic/anonrecur.js b/nashorn/test/script/basic/anonrecur.js
index 393a2ac..3f5dd71 100644
--- a/nashorn/test/script/basic/anonrecur.js
+++ b/nashorn/test/script/basic/anonrecur.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call1.js b/nashorn/test/script/basic/apply_to_call/apply_to_call1.js
new file mode 100644
index 0000000..74ebb2f
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call1.js
@@ -0,0 +1,66 @@
+/*
+* 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.
+ */
+
+/**
+ * apply_to_call1.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+    a : 0,
+    b : 0,
+    c : 0,
+    initialize : function(x,y,z) {
+    this.a = x;
+    this.b = y;
+    this.c = z;
+    }
+};
+
+function test() {
+    x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting apply now");
+
+x.initialize = {
+    apply : function() {
+    for (var i=0;i<arguments.length;i++) {
+        print("I am not who you think " + arguments[i]);
+    }
+    x.a = arguments[1][0];
+    }
+};
+
+test(4712);
+print(x.a);
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED b/nashorn/test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED
new file mode 100644
index 0000000..1d2a655
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call1.js.EXPECTED
@@ -0,0 +1,8 @@
+start
+4711
+23
+17
+Overwriting apply now
+I am not who you think [object Object]
+I am not who you think [object Arguments]
+4712
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call2.js b/nashorn/test/script/basic/apply_to_call/apply_to_call2.js
new file mode 100644
index 0000000..7356f2c
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call2.js
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ */
+
+/**
+ * apply_to_call2.js - do one apply to call specialization, then override call and make sure it reverts (i.e. stops
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+    a : 0,
+    b : 0,
+    c : 0,
+    initialize : function(x,y,z) {
+    this.a = x;
+    this.b = y;
+    this.c = z;
+    }
+};
+
+function test() {
+    x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting call now");
+
+Function.prototype.call = function() {
+    throw "this should never be thrown - test should revert to builtin apply";
+};
+
+test(1,2,3);
+print(x.a);
+print(x.b);
+print(x.c);
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED b/nashorn/test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED
new file mode 100644
index 0000000..651fbb4
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call2.js.EXPECTED
@@ -0,0 +1,8 @@
+start
+4711
+23
+17
+Overwriting call now
+1
+2
+3
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call3.js b/nashorn/test/script/basic/apply_to_call/apply_to_call3.js
new file mode 100644
index 0000000..f08c91b
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call3.js
@@ -0,0 +1,67 @@
+/*
+ * 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.
+ */
+
+/**
+ * apply_to_call3.js - do one apply to call specialization, then override, apply and make sure it reverts (i.e. stops
+ * calling call). Then apply should break and throw exception
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+    a : 0,
+    b : 0,
+    c : 0,
+    initialize : function(x,y,z) {
+    this.a = x;
+    this.b = y;
+    this.c = z;
+    }
+};
+
+function test() {
+    x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Overwriting apply now");
+
+Function.prototype.apply = function() {
+    throw "This should be thrown, as the test call transform is no longer valid";
+};
+
+try {
+    test(1,2,3);
+} catch (e) {
+    print(e);
+}
+print(x.a);
+print(x.b);
+print(x.c);
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED b/nashorn/test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED
new file mode 100644
index 0000000..b1007bd
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call3.js.EXPECTED
@@ -0,0 +1,9 @@
+start
+4711
+23
+17
+Overwriting apply now
+This should be thrown, as the test call transform is no longer valid
+4711
+23
+17
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call4.js b/nashorn/test/script/basic/apply_to_call/apply_to_call4.js
new file mode 100644
index 0000000..27067cc
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call4.js
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+/**
+ * apply_to_call4.js - various escaping args patterns that prevent the optimization from being applied
+ * calling call)
+ *
+ * @test
+ * @run
+ */
+
+print("start");
+
+var x = {
+    a : 0,
+    b : 0,
+    c : 0,
+    initialize : function(x,y,z) {
+    this.a = x;
+    this.b = y;
+    this.c = z;
+    }
+};
+
+function f(x) {
+    print("this is a black hole - arguments escape");
+}
+
+function test() {
+    f(arguments);
+    x.initialize.apply(x, arguments);
+}
+
+test(4711,23,17);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test2() {
+    arguments[0] = 17;
+    x.initialize.apply(x, arguments);
+}
+
+test2(1,2,3);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test3() {
+    var escape = arguments[0];
+    f(escape);
+    x.initialize.apply(x, arguments);
+}
+
+test3("alpha", "beta", "gamma");
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test4() {
+    var escape = arguments.length;
+    f(escape);
+    x.initialize.apply(x, arguments);
+}
+
+test4(1.2, 2.3, 3.4);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test5() {
+    x.initialize.apply(x, arguments, 17);
+}
+
+print("test 5 done");
+test5(11, 22);
+print("a="+typeof(x.a));
+print(x.b);
+print(x.c);
+
+print("Now it's time for transforms");
+
+function test6() {
+    x.initialize.apply(x, arguments);
+}
+
+test6(19, 20, 21);
+print(x.a);
+print(x.b);
+print(x.c);
+
+function test7() {
+    x.initialize.apply(x, arguments);
+}
+
+test7(1, 2.2, 17, 18);
+print(x.a);
+print(x.b);
+print(x.c);
+
+print("Should have transformed");
+
+function test8() {
+    var apply = f;
+    x.initialize.apply(x, arguments);
+}
+
+test8(7,8,9);
+print(x.a);
+print(x.b);
+print(x.c);
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED b/nashorn/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED
new file mode 100644
index 0000000..ce3b360
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call4.js.EXPECTED
@@ -0,0 +1,31 @@
+start
+this is a black hole - arguments escape
+4711
+23
+17
+17
+2
+3
+this is a black hole - arguments escape
+alpha
+beta
+gamma
+this is a black hole - arguments escape
+1.2
+2.3
+3.4
+test 5 done
+a=object
+17
+undefined
+Now it's time for transforms
+19
+20
+21
+1
+2.2
+17
+Should have transformed
+7
+8
+9
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/apply_to_call/apply_to_call_recompile.js
similarity index 66%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/apply_to_call/apply_to_call_recompile.js
index db358d2..29c44a6 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call_recompile.js
@@ -1,33 +1,44 @@
 /*
- * 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
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * apply_to_recompile.js - make sure that recompilations of methods are
+ * transform equivalent when it comes to apply2call, or we will have
+ * erroneous contiunation info generation
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+function K() {
+    K.b2BoundValues.apply(this, arguments);
+    this.constructor === K && K.b2BoundValues.apply(this, arguments)
+}
 
+K.b2BoundValues = function(a,b,c) {
+    print(a);
+    print(b);
+    print(c);
+};
+
+new K(11,12,13,14,15,16);
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED b/nashorn/test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED
new file mode 100644
index 0000000..44d695b
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call_recompile.js.EXPECTED
@@ -0,0 +1,6 @@
+11
+12
+13
+11
+12
+13
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call_varargs.js b/nashorn/test/script/basic/apply_to_call/apply_to_call_varargs.js
new file mode 100644
index 0000000..4d629f6
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call_varargs.js
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+/**
+ * apply_to_call_varars - make sure that apply to call transform works
+ * even when supplying too few arguments
+ *
+ * @test
+ * @run
+ */
+
+var Class = {
+  create: function() {
+    return function() { //vararg
+        this.initialize.apply(this, arguments);
+    }
+  }
+};
+
+Color = Class.create();
+Color.prototype = {
+    red: 0, green: 0, blue: 0,
+    initialize: function(r) {
+    this.red = r;
+    this.green = 255;
+    this.blue = 255;
+    },
+    toString: function() {
+    print("[red=" + this.red + ", green=" + this.green + ", blue=" + this.blue + "]");
+    }
+};
+
+var colors = new Array(16);
+function run() {
+    for (var i = 0; i < colors.length; i++) {
+    colors[i&0xf] = (new Color(i));
+    }
+}
+
+run();
+for (var i = 0; i < colors.length; i++) {
+    print(colors[i]);
+}
+
+print("Swapping out call");
+Function.prototype.call = function() {
+    throw "This should not happen, apply should be called instead";
+};
+
+run();
+for (var i = 0; i < colors.length; i++) {
+    print(colors[i]);
+}
+
+print("All done!");
diff --git a/nashorn/test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED b/nashorn/test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED
new file mode 100644
index 0000000..d8f338b
--- /dev/null
+++ b/nashorn/test/script/basic/apply_to_call/apply_to_call_varargs.js.EXPECTED
@@ -0,0 +1,66 @@
+[red=0, green=255, blue=255]
+undefined
+[red=1, green=255, blue=255]
+undefined
+[red=2, green=255, blue=255]
+undefined
+[red=3, green=255, blue=255]
+undefined
+[red=4, green=255, blue=255]
+undefined
+[red=5, green=255, blue=255]
+undefined
+[red=6, green=255, blue=255]
+undefined
+[red=7, green=255, blue=255]
+undefined
+[red=8, green=255, blue=255]
+undefined
+[red=9, green=255, blue=255]
+undefined
+[red=10, green=255, blue=255]
+undefined
+[red=11, green=255, blue=255]
+undefined
+[red=12, green=255, blue=255]
+undefined
+[red=13, green=255, blue=255]
+undefined
+[red=14, green=255, blue=255]
+undefined
+[red=15, green=255, blue=255]
+undefined
+Swapping out call
+[red=0, green=255, blue=255]
+undefined
+[red=1, green=255, blue=255]
+undefined
+[red=2, green=255, blue=255]
+undefined
+[red=3, green=255, blue=255]
+undefined
+[red=4, green=255, blue=255]
+undefined
+[red=5, green=255, blue=255]
+undefined
+[red=6, green=255, blue=255]
+undefined
+[red=7, green=255, blue=255]
+undefined
+[red=8, green=255, blue=255]
+undefined
+[red=9, green=255, blue=255]
+undefined
+[red=10, green=255, blue=255]
+undefined
+[red=11, green=255, blue=255]
+undefined
+[red=12, green=255, blue=255]
+undefined
+[red=13, green=255, blue=255]
+undefined
+[red=14, green=255, blue=255]
+undefined
+[red=15, green=255, blue=255]
+undefined
+All done!
diff --git a/nashorn/test/script/basic/applycall.js b/nashorn/test/script/basic/applycall.js
index 6756ead..b49cfd5 100644
--- a/nashorn/test/script/basic/applycall.js
+++ b/nashorn/test/script/basic/applycall.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/args.js b/nashorn/test/script/basic/args.js
index 7b8ff0a..3d4451c 100644
--- a/nashorn/test/script/basic/args.js
+++ b/nashorn/test/script/basic/args.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/arity.js b/nashorn/test/script/basic/arity.js
index b53b298..554961e 100644
--- a/nashorn/test/script/basic/arity.js
+++ b/nashorn/test/script/basic/arity.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * arity test.
  *
  * @test
- * @run 
+ * @run
  */
 
 function func1(a) { print(a); }
diff --git a/nashorn/test/script/basic/arrayprotoclass.js b/nashorn/test/script/basic/arrayprotoclass.js
index f5993c0..bc7a56c 100644
--- a/nashorn/test/script/basic/arrayprotoclass.js
+++ b/nashorn/test/script/basic/arrayprotoclass.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/arrays.js b/nashorn/test/script/basic/arrays.js
index 6cab375..03ad431 100644
--- a/nashorn/test/script/basic/arrays.js
+++ b/nashorn/test/script/basic/arrays.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -155,6 +155,6 @@
 print(Array.prototype.reduce.call("hello", function() {}));
 print(Array.prototype.toString.call(new java.lang.Object()));
 print(Array.prototype.toLocaleString.call(new java.lang.Object()));
-print(Array.prototype.reduceRight.call(new java.lang.Object(), 
+print(Array.prototype.reduceRight.call(new java.lang.Object(),
       function() {}, 33));
 
diff --git a/nashorn/test/script/basic/arrays2.js b/nashorn/test/script/basic/arrays2.js
index 1342c17..8856dab 100644
--- a/nashorn/test/script/basic/arrays2.js
+++ b/nashorn/test/script/basic/arrays2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/arrays_int_key.js
similarity index 98%
rename from nashorn/test/script/basic/arraysIntKey.js
rename to nashorn/test/script/basic/arrays_int_key.js
index c9182ef..0ba18d2 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/arrays_int_key.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 var o = [0];
 Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
diff --git a/nashorn/test/script/basic/arraysIntKey.js.EXPECTED b/nashorn/test/script/basic/arrays_int_key.js.EXPECTED
similarity index 100%
rename from nashorn/test/script/basic/arraysIntKey.js.EXPECTED
rename to nashorn/test/script/basic/arrays_int_key.js.EXPECTED
diff --git a/nashorn/test/script/basic/arrayset.js b/nashorn/test/script/basic/arrayset.js
index 2fbd2bc..1f2fd52 100644
--- a/nashorn/test/script/basic/arrayset.js
+++ b/nashorn/test/script/basic/arrayset.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-var arr = []; 
+var arr = [];
 print(arr.length);
 print(arr.hasOwnProperty(10000));
 print(arr.hasOwnProperty(10));
diff --git a/nashorn/test/script/basic/arrayundefined.js b/nashorn/test/script/basic/arrayundefined.js
index 3866c85..5cf2463 100644
--- a/nashorn/test/script/basic/arrayundefined.js
+++ b/nashorn/test/script/basic/arrayundefined.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/assign.js b/nashorn/test/script/basic/assign.js
index abcc504..04a9625 100644
--- a/nashorn/test/script/basic/assign.js
+++ b/nashorn/test/script/basic/assign.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Assign test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var x = 10;
diff --git a/nashorn/test/script/basic/bitwise_and.js b/nashorn/test/script/basic/bitwise_and.js
index 32583d4..716fa90 100644
--- a/nashorn/test/script/basic/bitwise_and.js
+++ b/nashorn/test/script/basic/bitwise_and.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/boolean_arithmetic.js b/nashorn/test/script/basic/boolean_arithmetic.js
new file mode 100644
index 0000000..8811040
--- /dev/null
+++ b/nashorn/test/script/basic/boolean_arithmetic.js
@@ -0,0 +1,113 @@
+/*
+ * 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.
+ */
+
+/**
+ * test arithmetic operations on boolean variables
+ *
+ * @test
+ * @run
+ */
+
+function printOp(text, value) {
+    print(text + value);
+}
+
+(function () {
+var t = true;
+var f = false;
+
+print("+")
+printOp("f, f: ", (f + f))
+printOp("f, t: ", (f + t))
+printOp("t, f: ", (t + f))
+printOp("t, t: ", (t + t))
+
+print("-")
+printOp("f, f: ", (f - f))
+printOp("f, t: ", (f - t))
+printOp("t, f: ", (t - f))
+printOp("t, t: ", (t - t))
+
+print("*")
+printOp("f, f: ", (f * f))
+printOp("f, t: ", (f * t))
+printOp("t, f: ", (t * f))
+printOp("t, t: ", (t * t))
+
+print("/")
+printOp("f, f: ", (f / f))
+printOp("f, t: ", (f / t))
+printOp("t, f: ", (t / f))
+printOp("t, t: ", (t / t))
+
+print("<<")
+printOp("f, f: ", (f << f))
+printOp("f, t: ", (f << t))
+printOp("t, f: ", (t << f))
+printOp("t, t: ", (t << t))
+
+print(">>")
+printOp("f, f: ", (f >> f))
+printOp("f, t: ", (f >> t))
+printOp("t, f: ", (t >> f))
+printOp("t, t: ", (t >> t))
+
+print(">>>")
+printOp("f, f: ", (f >>> f))
+printOp("f, t: ", (f >>> t))
+printOp("t, f: ", (t >>> f))
+printOp("t, t: ", (t >>> t))
+
+print("|")
+printOp("f, f: ", (f | f))
+printOp("f, t: ", (f | t))
+printOp("t, f: ", (t | f))
+printOp("t, t: ", (t | t))
+
+print("&")
+printOp("f, f: ", (f & f))
+printOp("f, t: ", (f & t))
+printOp("t, f: ", (t & f))
+printOp("t, t: ", (t & t))
+
+print("^")
+printOp("f, f: ", (f ^ f))
+printOp("f, t: ", (f ^ t))
+printOp("t, f: ", (t ^ f))
+printOp("t, t: ", (t ^ t))
+
+print("~")
+printOp("f: ", (~f))
+printOp("t: ", (~t))
+
+print("+")
+printOp("f: ", (+f))
+printOp("t: ", (+t))
+
+print("-")
+printOp("f: ", (-f))
+printOp("t: ", (-t))
+
+printOp("1/-f: ", (1/-f))
+
+})();
diff --git a/nashorn/test/script/basic/boolean_arithmetic.js.EXPECTED b/nashorn/test/script/basic/boolean_arithmetic.js.EXPECTED
new file mode 100644
index 0000000..7020ac3
--- /dev/null
+++ b/nashorn/test/script/basic/boolean_arithmetic.js.EXPECTED
@@ -0,0 +1,60 @@
++
+f, f: 0
+f, t: 1
+t, f: 1
+t, t: 2
+-
+f, f: 0
+f, t: -1
+t, f: 1
+t, t: 0
+*
+f, f: 0
+f, t: 0
+t, f: 0
+t, t: 1
+/
+f, f: NaN
+f, t: 0
+t, f: Infinity
+t, t: 1
+<<
+f, f: 0
+f, t: 0
+t, f: 1
+t, t: 2
+>>
+f, f: 0
+f, t: 0
+t, f: 1
+t, t: 0
+>>>
+f, f: 0
+f, t: 0
+t, f: 1
+t, t: 0
+|
+f, f: 0
+f, t: 1
+t, f: 1
+t, t: 1
+&
+f, f: 0
+f, t: 0
+t, f: 0
+t, t: 1
+^
+f, f: 0
+f, t: 1
+t, f: 1
+t, t: 0
+~
+f: -1
+t: -2
++
+f: 0
+t: 1
+-
+f: 0
+t: -1
+1/-f: -Infinity
diff --git a/nashorn/test/script/basic/booleangetter.js b/nashorn/test/script/basic/booleangetter.js
index 3f16b74..237edbe 100644
--- a/nashorn/test/script/basic/booleangetter.js
+++ b/nashorn/test/script/basic/booleangetter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/builtin.js b/nashorn/test/script/basic/builtin.js
index 4d48bff..5693c85 100644
--- a/nashorn/test/script/basic/builtin.js
+++ b/nashorn/test/script/basic/builtin.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/builtin_assign.js b/nashorn/test/script/basic/builtin_assign.js
index 7520cb7..02a9544 100644
--- a/nashorn/test/script/basic/builtin_assign.js
+++ b/nashorn/test/script/basic/builtin_assign.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/builtinchain.js b/nashorn/test/script/basic/builtinchain.js
index a5e672e..05011b7 100644
--- a/nashorn/test/script/basic/builtinchain.js
+++ b/nashorn/test/script/basic/builtinchain.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/calllink.js b/nashorn/test/script/basic/calllink.js
index 06e546c..0d27ba9 100644
--- a/nashorn/test/script/basic/calllink.js
+++ b/nashorn/test/script/basic/calllink.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -60,7 +60,7 @@
 var obj5 = new MyConstructor();
 var obj6 = new MyConstructor();
 
-var arr = [ obj1, obj2, obj3, obj4, obj5, obj6, 
+var arr = [ obj1, obj2, obj3, obj4, obj5, obj6,
             obj1, obj2, obj3, obj4, obj5, obj6 ];
 
 var myObj;
@@ -69,8 +69,8 @@
         obj3.func = function() {
             print("new obj3.func called");
         }
-        obj4.func = function() { 
-            print("new obj4.func called"); 
+        obj4.func = function() {
+            print("new obj4.func called");
         }
         MyConstructor.prototype.func = function() {
             print("all new MyConstructor.prototype.func");
diff --git a/nashorn/test/script/basic/classloader.js b/nashorn/test/script/basic/classloader.js
index 7676496..b46d23e 100644
--- a/nashorn/test/script/basic/classloader.js
+++ b/nashorn/test/script/basic/classloader.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/closure.js b/nashorn/test/script/basic/closure.js
index f601375..30af72f 100644
--- a/nashorn/test/script/basic/closure.js
+++ b/nashorn/test/script/basic/closure.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,14 +25,14 @@
  * Closure test.
  *
  * @test
- * @run 
+ * @run
  */
- 
+
 (function test1(a, b){ print(a, b); })(10, 20);
 (function test2(a, b){ print(a, b); })(10);
 (function test3(a, b){ print(a, b); })(10, 20, 30);
-(function test4(a, b){ 
-    print(arguments[0] + "," + arguments[1]); 
+(function test4(a, b){
+    print(arguments[0] + "," + arguments[1]);
     print(arguments.callee);
 })(10, 20);
 
diff --git a/nashorn/test/script/basic/closure.js.EXPECTED b/nashorn/test/script/basic/closure.js.EXPECTED
index d039115..e6b807f 100644
--- a/nashorn/test/script/basic/closure.js.EXPECTED
+++ b/nashorn/test/script/basic/closure.js.EXPECTED
@@ -2,7 +2,7 @@
 10 undefined
 10 20
 10,20
-function test4(a, b){ 
-    print(arguments[0] + "," + arguments[1]); 
+function test4(a, b){
+    print(arguments[0] + "," + arguments[1]);
     print(arguments.callee);
 }
diff --git a/nashorn/test/script/basic/commandargs.js b/nashorn/test/script/basic/commandargs.js
index 733b679..ac28a43 100644
--- a/nashorn/test/script/basic/commandargs.js
+++ b/nashorn/test/script/basic/commandargs.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Simple test to check command line arguments for scripts.
  *
  * @test
- * @argument hello 
+ * @argument hello
  * @argument world
  * @run
  */
@@ -33,4 +33,4 @@
 for (i in arguments) {
     print(arguments[i]);
 }
- 
+
diff --git a/nashorn/test/script/basic/JDK-8010697.js b/nashorn/test/script/basic/compile-octane-normal.js
similarity index 62%
copy from nashorn/test/script/basic/JDK-8010697.js
copy to nashorn/test/script/basic/compile-octane-normal.js
index c1b8e57..769f00b 100644
--- a/nashorn/test/script/basic/JDK-8010697.js
+++ b/nashorn/test/script/basic/compile-octane-normal.js
@@ -22,38 +22,21 @@
  */
 
 /**
- * JDK-8010697: DeletedArrayFilter seems to leak memory
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
  *
  * @test
- * @run
+ * @fork
+ * @runif external.octane
+ * @option -scripting
+ * @option -Dnashorn.typeInfo.disabled=true
+ * @option --class-cache-size=0
+ * @option --persistent-code-cache=false
  */
 
-var N = 1000;
-
-var array = new Array(N);
-var WeakReferenceArray = Java.type("java.lang.ref.WeakReference[]");
-var refArray = new WeakReferenceArray(N);
-
-for (var i = 0; i < N; i ++) {
-    var object = new java.lang.Object();
-    array[i] = object;
-    refArray[i] = new java.lang.ref.WeakReference(object);
-}
-
-object = null;
-
-for (var i = 0; i < N; i ++) {
-    delete array[i];
-}
-
-java.lang.System.gc();
-java.lang.System.gc();
-
-for (var i = 0; i < N; i ++) {
-    if (refArray[i].get() != null) {
-        print("Reference found at " + i);
-        exit(0);
-    }
-}
-
-print("All references gone");
+var fn  = __DIR__ + 'compile-octane.js';
+var url = "file://" + fn;
+loadWithNewGlobal(new java.net.URL(url));
diff --git a/nashorn/test/script/basic/compile-octane-normal.js.EXPECTED b/nashorn/test/script/basic/compile-octane-normal.js.EXPECTED
new file mode 100644
index 0000000..5577bcc
--- /dev/null
+++ b/nashorn/test/script/basic/compile-octane-normal.js.EXPECTED
@@ -0,0 +1,30 @@
+Compiling 'box2d'...
+Done.
+Compiling 'code-load'...
+Done.
+Compiling 'crypto'...
+Done.
+Compiling 'deltablue'...
+Done.
+Compiling 'earley-boyer'...
+Done.
+Compiling 'gbemu'... (2 files)
+Done.
+Compiling 'mandreel'...
+Done.
+Compiling 'navier-stokes'...
+Done.
+Compiling 'pdfjs'...
+Done.
+Compiling 'raytrace'...
+Done.
+Compiling 'regexp'...
+Done.
+Compiling 'richards'...
+Done.
+Compiling 'splay'...
+Done.
+Compiling 'typescript'... (3 files)
+Done.
+Compiling 'zlib'... (2 files)
+Done.
diff --git a/nashorn/test/script/basic/compile-octane-splitter.js b/nashorn/test/script/basic/compile-octane-splitter.js
index 497b5ab..5b4f0e1 100644
--- a/nashorn/test/script/basic/compile-octane-splitter.js
+++ b/nashorn/test/script/basic/compile-octane-splitter.js
@@ -1,32 +1,44 @@
 /*
  * 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.
  */
 
 /**
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
  * @test
+ * @fork
  * @option -Dnashorn.compiler.splitter.threshold=1000
  * @fork
  * @runif external.octane
- */ 
+ * @option -scripting
+ * @option -Dnashorn.typeInfo.disabled=true
+ * @option --class-cache-size=0
+ * @option --persistent-code-cache=false
+ */
 
-compile_only = true;
-load(__DIR__ + 'run-octane.js');
+var fn  = __DIR__ + 'compile-octane.js';
+var url = "file://" + fn;
+loadWithNewGlobal(new java.net.URL(url));
diff --git a/nashorn/test/script/basic/compile-octane-splitter.js.EXPECTED b/nashorn/test/script/basic/compile-octane-splitter.js.EXPECTED
index 9e4920d..5577bcc 100644
--- a/nashorn/test/script/basic/compile-octane-splitter.js.EXPECTED
+++ b/nashorn/test/script/basic/compile-octane-splitter.js.EXPECTED
@@ -1,14 +1,30 @@
-[box2d] Compiled OK
-[code-load] Compiled OK
-[crypto] Compiled OK
-[deltablue] Compiled OK
-[earley-boyer] Compiled OK
-[gbemu] Compiled OK
-[mandreel] Compiled OK
-[navier-stokes] Compiled OK
-[pdfjs] Compiled OK
-[raytrace] Compiled OK
-[regexp] Compiled OK
-[richards] Compiled OK
-[splay] Compiled OK
-[typescript] Compiled OK
+Compiling 'box2d'...
+Done.
+Compiling 'code-load'...
+Done.
+Compiling 'crypto'...
+Done.
+Compiling 'deltablue'...
+Done.
+Compiling 'earley-boyer'...
+Done.
+Compiling 'gbemu'... (2 files)
+Done.
+Compiling 'mandreel'...
+Done.
+Compiling 'navier-stokes'...
+Done.
+Compiling 'pdfjs'...
+Done.
+Compiling 'raytrace'...
+Done.
+Compiling 'regexp'...
+Done.
+Compiling 'richards'...
+Done.
+Compiling 'splay'...
+Done.
+Compiling 'typescript'... (3 files)
+Done.
+Compiling 'zlib'... (2 files)
+Done.
diff --git a/nashorn/test/script/basic/compile-octane.js b/nashorn/test/script/basic/compile-octane.js
index da40d5e..aee105a 100644
--- a/nashorn/test/script/basic/compile-octane.js
+++ b/nashorn/test/script/basic/compile-octane.js
@@ -1,30 +1,143 @@
 /*
  * 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.
  */
 
 /**
- * @test
- * @runif external.octane
- */ 
+ * Make sure that we run with the class cache off to so that every
+ * run produces compile time and with optimistic type info caching
+ * and persistent code store off, for the same reasons. These last two
+ * are currently default, but this is not guaranteed to be the case
+ * forever, so make this test future safe, we specify them explicitly
+ *
+ * This means that if you use this subtest as a compilation test
+ * harness, pass the arguments:
+ *
+ * -scripting -Dnashorn.typeInfo.disabled=true --class-cache-size=0
+ * --persistent-code-cache=false
+ *
+ * @subtest
+ */
 
-compile_only = true;
-load(__DIR__ + 'run-octane.js');
+load(__DIR__ + 'octane-payload.js');
+
+var DEFAULT_ITERS = 1; //default is one iteration through each benchmark
+var iters = DEFAULT_ITERS;
+var args = [];
+
+if (typeof $ARGS !== 'undefined') {
+    args = $ARGS;
+} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
+    args = arguments;
+}
+
+var onlyTheseTests = [];
+var verbose = false;
+
+for (var i = 0; i < args.length; ) {
+    var arg = args[i];
+    if (arg === '--iterations') {
+    iters = +args[++i];
+    } else if (arg === '--verbose') {
+    verbose = true;
+    } else {
+    onlyTheseTests.push(arg);
+    }
+    i++;
+}
+
+if (isNaN(iters)) {
+    iters = DEFAULT_ITERS;
+}
+
+if (iters != DEFAULT_ITERS) {
+    print("Running " + iters + " iterations of each compilation.");
+}
+
+function print_if_verbose(x) {
+    if (verbose) {
+    print(x);
+    }
+}
+
+function contains(a, obj) {
+    for (var i = 0; i < a.length; i++) {
+        if (a[i] === obj) {
+            return true;
+        }
+    }
+    return false;
+}
+
+var testsCompiled = [];
+
+for (var j in tests) {
+    var test_name = tests[j].name;
+    var files = tests[j].files;
+
+    if (onlyTheseTests.length > 0 && !contains(onlyTheseTests, test_name)) {
+    print_if_verbose("Skipping " + test_name);
+    continue;
+    }
+
+    if (!contains(testsCompiled, test_name)) {
+    testsCompiled.push(test_name);
+    }
+
+    var str = "Compiling '" + test_name + "'...";
+    if (files.length > 1) {
+    str += " (" + files.length + " files)";
+    }
+    if (iters != 1) {
+    str += " (" + iters + " times)";
+    }
+    str + "...";
+    print(str);
+
+    for (var iteration = 0; iteration < iters; iteration++) {
+
+    //get a new global to avoid symbol pollution and reloads of base
+    //in the same namespace
+    var newGlobal = loadWithNewGlobal({script:'this', name:'test'});
+
+    //load base into the new global so we get BenchmarkSuite etc
+    newGlobal.load(base);
+
+    //load all files in the single benchmark
+    for (var k in files) {
+        var file = files[k];
+        if (iteration >= 0) { //only display message on first iteration
+        var str2 = "\t";
+        if (iters > 1) {
+            str2 += " [iteration " + (iteration + 1) + "]";
+        }
+        str2 += " processing file: " + file + "...";
+        print_if_verbose(str2);
+        }
+        newGlobal.load("file://" + path + file);
+    }
+    }
+    print("Done.");
+}
+
+if (testsCompiled.length == 0) {
+    print("Error: no tests given to compile");
+}
diff --git a/nashorn/test/script/basic/compile-octane.js.EXPECTED b/nashorn/test/script/basic/compile-octane.js.EXPECTED
deleted file mode 100644
index 9e4920d..0000000
--- a/nashorn/test/script/basic/compile-octane.js.EXPECTED
+++ /dev/null
@@ -1,14 +0,0 @@
-[box2d] Compiled OK
-[code-load] Compiled OK
-[crypto] Compiled OK
-[deltablue] Compiled OK
-[earley-boyer] Compiled OK
-[gbemu] Compiled OK
-[mandreel] Compiled OK
-[navier-stokes] Compiled OK
-[pdfjs] Compiled OK
-[raytrace] Compiled OK
-[regexp] Compiled OK
-[richards] Compiled OK
-[splay] Compiled OK
-[typescript] Compiled OK
diff --git a/nashorn/test/script/basic/condassign.js b/nashorn/test/script/basic/condassign.js
index a70f5a4..6b5d6ff 100644
--- a/nashorn/test/script/basic/condassign.js
+++ b/nashorn/test/script/basic/condassign.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/construct.js b/nashorn/test/script/basic/construct.js
index 66e3d41..2a268ed 100644
--- a/nashorn/test/script/basic/construct.js
+++ b/nashorn/test/script/basic/construct.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,19 +25,19 @@
  * Constructor test.
  *
  * @test
- * @run 
+ * @run
  */
 
 function Test() {
     this.A = "A big fat string";
     this.B = 123;
-    
+
     this.F = function(x) { return x; }
-   
-    var proto = Object.getPrototypeOf(this); 
+
+    var proto = Object.getPrototypeOf(this);
     proto.R = "A big fat string";
     proto.S = 123;
-    
+
     proto.T = function(x) { return x; }
 
     return "monkey";
diff --git a/nashorn/test/script/basic/constructorname.js b/nashorn/test/script/basic/constructorname.js
index 16e3aec..ee3e25f 100644
--- a/nashorn/test/script/basic/constructorname.js
+++ b/nashorn/test/script/basic/constructorname.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/convert.js b/nashorn/test/script/basic/convert.js
index 8d11d12..3a1bca0 100644
--- a/nashorn/test/script/basic/convert.js
+++ b/nashorn/test/script/basic/convert.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/dataview_endian.js b/nashorn/test/script/basic/dataview_endian.js
index f7607c0..668167a 100644
--- a/nashorn/test/script/basic/dataview_endian.js
+++ b/nashorn/test/script/basic/dataview_endian.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/dataview_getset.js b/nashorn/test/script/basic/dataview_getset.js
index 8c7a994..97fc1f4 100644
--- a/nashorn/test/script/basic/dataview_getset.js
+++ b/nashorn/test/script/basic/dataview_getset.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/dataview_new.js b/nashorn/test/script/basic/dataview_new.js
index 78f8183..54ebc9f 100644
--- a/nashorn/test/script/basic/dataview_new.js
+++ b/nashorn/test/script/basic/dataview_new.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -57,7 +57,8 @@
         fail("Should have thrown " + ErrorType.name);
     } catch (e) {
         if (! (e instanceof ErrorType)) {
-            fail("Expected " + ErrorType.name + " got " + e);
+            print("Expected " + ErrorType.name + " got " + e);
+            e.printStackTrace()
         }
     }
 }
diff --git a/nashorn/test/script/basic/date.js b/nashorn/test/script/basic/date.js
index ea77089..22a38db 100644
--- a/nashorn/test/script/basic/date.js
+++ b/nashorn/test/script/basic/date.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/dateparse.js b/nashorn/test/script/basic/dateparse.js
index 919a681..fe29d4b 100644
--- a/nashorn/test/script/basic/dateparse.js
+++ b/nashorn/test/script/basic/dateparse.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/decinc.js b/nashorn/test/script/basic/decinc.js
index 3ee1ac1..b77c624 100644
--- a/nashorn/test/script/basic/decinc.js
+++ b/nashorn/test/script/basic/decinc.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/delete.js b/nashorn/test/script/basic/delete.js
index 6d7f884..ea70013 100644
--- a/nashorn/test/script/basic/delete.js
+++ b/nashorn/test/script/basic/delete.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/delete2.js b/nashorn/test/script/basic/delete2.js
index 3d14847..1ca48a8 100644
--- a/nashorn/test/script/basic/delete2.js
+++ b/nashorn/test/script/basic/delete2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -26,7 +26,7 @@
  * throws VerifyError!!
  *
  * @test
- * @run 
+ * @run
  */
 
 var a = 10;
@@ -39,7 +39,7 @@
 
 function e(g) {
     var f = 10;
-    
+
     print(delete f);
     print(f);
     print(delete g);
diff --git a/nashorn/test/script/basic/dotpropname.js b/nashorn/test/script/basic/dotpropname.js
index 03704ec..6df361c 100644
--- a/nashorn/test/script/basic/dotpropname.js
+++ b/nashorn/test/script/basic/dotpropname.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/doublecache.js b/nashorn/test/script/basic/doublecache.js
index 91ac845..c42c8a9 100644
--- a/nashorn/test/script/basic/doublecache.js
+++ b/nashorn/test/script/basic/doublecache.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -39,7 +39,7 @@
         0.5,
         100,
         200,
-        
+
         -200,
         -100,
         -0.5,
@@ -50,5 +50,5 @@
         100,
         200
         ];
-        
+
 for (i in x) print(x[i]);
diff --git a/nashorn/test/script/basic/enumeration.js b/nashorn/test/script/basic/enumeration.js
index 3746dfe..7453dcb 100644
--- a/nashorn/test/script/basic/enumeration.js
+++ b/nashorn/test/script/basic/enumeration.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * Make sure that there are no-enumerable items on standard objects. 
+ * Make sure that there are no-enumerable items on standard objects.
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/errors.js b/nashorn/test/script/basic/errors.js
index c698ef8..ee56d76 100644
--- a/nashorn/test/script/basic/errors.js
+++ b/nashorn/test/script/basic/errors.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Basic checks for Error constructors.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/errorstack.js b/nashorn/test/script/basic/errorstack.js
index 8fcd25a..d0e7ea6 100644
--- a/nashorn/test/script/basic/errorstack.js
+++ b/nashorn/test/script/basic/errorstack.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -26,7 +26,7 @@
  *
  * @test
  * @run
- */ 
+ */
 
 function func1() {
    func2();
diff --git a/nashorn/test/script/basic/eval.js b/nashorn/test/script/basic/eval.js
index 3d66c02..59402d4 100644
--- a/nashorn/test/script/basic/eval.js
+++ b/nashorn/test/script/basic/eval.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * eval test.
  *
  * @test
- * @run 
+ * @run
  */
 
 print("eval.length " + eval.length);
@@ -33,7 +33,7 @@
 function test1() {
     var x = 200;
     y = x + 2000;
-    
+
     print(x);
     print(y);
 }
@@ -41,7 +41,7 @@
 function test2() {
     eval("var x = 300;");
     eval("y = x + 3000;");
-    
+
     print(x);
     print(y);
 }
diff --git a/nashorn/test/script/basic/evalreturn.js b/nashorn/test/script/basic/evalreturn.js
index 3f523cc..75d02a8 100644
--- a/nashorn/test/script/basic/evalreturn.js
+++ b/nashorn/test/script/basic/evalreturn.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * eval return values test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var x = 0;
@@ -65,7 +65,7 @@
 var g = eval("function cake() { print('moist and delicious!'); } function cookie() { print('sweet and crunchy!'); }");
 print(g);
 g();
- 
+
 
 
 
diff --git a/nashorn/test/script/basic/exprclosure.js b/nashorn/test/script/basic/exprclosure.js
index ad1c396..45bc908 100644
--- a/nashorn/test/script/basic/exprclosure.js
+++ b/nashorn/test/script/basic/exprclosure.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/exprclosure.js.EXPECTED b/nashorn/test/script/basic/exprclosure.js.EXPECTED
index ae80338..9afb92a 100644
--- a/nashorn/test/script/basic/exprclosure.js.EXPECTED
+++ b/nashorn/test/script/basic/exprclosure.js.EXPECTED
@@ -1,4 +1,4 @@
-function(x) x*x;
+function(x) x*x
 625
-function fun(x) x * (x + 1) / 2;
+function fun(x) x * (x + 1) / 2
 55
diff --git a/nashorn/test/script/basic/extensibility.js b/nashorn/test/script/basic/extensibility.js
index 0904466..2cf7652 100644
--- a/nashorn/test/script/basic/extensibility.js
+++ b/nashorn/test/script/basic/extensibility.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/fileline.js b/nashorn/test/script/basic/fileline.js
index ccf879b..90b3d58 100644
--- a/nashorn/test/script/basic/fileline.js
+++ b/nashorn/test/script/basic/fileline.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/finally-catchalls.js b/nashorn/test/script/basic/finally-catchalls.js
index dac9cee..f6f3896 100644
--- a/nashorn/test/script/basic/finally-catchalls.js
+++ b/nashorn/test/script/basic/finally-catchalls.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,75 +30,75 @@
 
 function test1() {
     try {
-	print("try");
-	throw "ex";
+    print("try");
+    throw "ex";
     } finally {
-	print("finally");
+    print("finally");
     }
 }
 
-function test2() {   
+function test2() {
     try {
-	print("try");
+    print("try");
     } finally {
-	print("finally");
+    print("finally");
     }
 }
 
-function test3() {   
+function test3() {
     try {
-	print("try");
-	return;
+    print("try");
+    return;
     } finally {
-	print("finally");
+    print("finally");
     }
 }
 
-function test4() {   
+function test4() {
     var i = 0;
     while (i<10) {
-	try {
-	    print("try "+i);
-	    i++;
-	    continue;
-	} finally {
-	    print("finally "+i);
-	}
+    try {
+        print("try "+i);
+        i++;
+        continue;
+    } finally {
+        print("finally "+i);
+    }
     }
     print(i);
 }
 
-function test5() {   
+function test5() {
     var i = 0;
     while (i<10) {
-	try {
-	    print("try "+i);
-	    i++;
-	    break;
-	} finally {
-	    print("finally "+i);
-	}
+    try {
+        print("try "+i);
+        i++;
+        break;
+    } finally {
+        print("finally "+i);
+    }
     }
     print(i);
 }
 
-function test6() {   
+function test6() {
     var i = 0;
     while (i<10) {
-	try {
-	    print("try "+i);
-	    if (i == 5)
-		break;
-	    i++;
-	} finally {
-	    print("finally "+i);
-	}
+    try {
+        print("try "+i);
+        if (i == 5)
+        break;
+        i++;
+    } finally {
+        print("finally "+i);
+    }
     }
     print(i);
 }
 
 print("\ntest 1\n");
-try { 
+try {
     test1();
 } catch (e) {
     print("got e");
diff --git a/nashorn/test/script/basic/finallyreturn.js b/nashorn/test/script/basic/finallyreturn.js
index 79c9f71..6593f17 100644
--- a/nashorn/test/script/basic/finallyreturn.js
+++ b/nashorn/test/script/basic/finallyreturn.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/forin.js b/nashorn/test/script/basic/forin.js
index 2a60a66..4b1b85a 100644
--- a/nashorn/test/script/basic/forin.js
+++ b/nashorn/test/script/basic/forin.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/forin2.js b/nashorn/test/script/basic/forin2.js
index be47bec..0401062 100644
--- a/nashorn/test/script/basic/forin2.js
+++ b/nashorn/test/script/basic/forin2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -37,7 +37,7 @@
     print("error 1");
 } catch(e) {
     if ((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
@@ -46,30 +46,30 @@
     print("error 2");
 } catch(e) {
     if((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
-try {  
-    for (var y in null) { 
-	y = 2;
+try {
+    for (var y in null) {
+    y = 2;
     }
     print("this is ok 1");
 } catch(e) {
     if ((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
 // CHECK#4
 try {
-    for (var z in 'bbb'.match(/aaa/)) { 
-	z = 2;
+    for (var z in 'bbb'.match(/aaa/)) {
+    z = 2;
     }
     print("this is ok 2");
 } catch(e) {
     if((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
@@ -79,7 +79,7 @@
     print("error 5");
 } catch(e) {
     if ((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
@@ -88,29 +88,29 @@
     print("error 6");
 } catch (e) {
     if ((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
 // CHECK#3
 try {
-    for (var y in undefined) { 
-	y = 2;
+    for (var y in undefined) {
+    y = 2;
     }
     print("this is ok 3");
-} catch (e) { 
+} catch (e) {
     if ((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
 
 try {
-    for (var z in this.foo) { 
-	z = 2;
+    for (var z in this.foo) {
+    z = 2;
     }
     print("this is ok 4");
 } catch (e) {
     if ((e instanceof TypeError) !== true) {
-	print(e);
+    print(e);
     }
 }
diff --git a/nashorn/test/script/basic/funcarray.js b/nashorn/test/script/basic/funcarray.js
index 7ffd5f5..a55443a 100644
--- a/nashorn/test/script/basic/funcarray.js
+++ b/nashorn/test/script/basic/funcarray.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,9 +25,9 @@
  * Function array test.
  *
  * @test
- * @run 
+ * @run
  */
- 
+
 
 var funcs = [
                 function() { print("first"); },
@@ -35,7 +35,7 @@
                 function() { print("third"); },
                 function() { print("fourth"); }
             ];
-            
+
 funcs[0]();
 funcs[1]();
 funcs[2]();
diff --git a/nashorn/test/script/basic/funcbind.js b/nashorn/test/script/basic/funcbind.js
index 2b97b0e..bb13953 100644
--- a/nashorn/test/script/basic/funcbind.js
+++ b/nashorn/test/script/basic/funcbind.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -34,10 +34,10 @@
     print("global foo");
 }
 
-function func(x, y) { 
+function func(x, y) {
     print(this == global);
-    print(x); 
-    print(y); 
+    print(x);
+    print(y);
     this.foo();
 }
 
diff --git a/nashorn/test/script/basic/funcbind2.js b/nashorn/test/script/basic/funcbind2.js
index 697ee52..16016b5 100644
--- a/nashorn/test/script/basic/funcbind2.js
+++ b/nashorn/test/script/basic/funcbind2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/funcbind3.js b/nashorn/test/script/basic/funcbind3.js
index 25f448d..10cf9ca 100644
--- a/nashorn/test/script/basic/funcbind3.js
+++ b/nashorn/test/script/basic/funcbind3.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/funcconstructor.js b/nashorn/test/script/basic/funcconstructor.js
index 038031c..4fc096a 100644
--- a/nashorn/test/script/basic/funcconstructor.js
+++ b/nashorn/test/script/basic/funcconstructor.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/getclassname.js b/nashorn/test/script/basic/getclassname.js
index 3e29bc6..dd94b03 100644
--- a/nashorn/test/script/basic/getclassname.js
+++ b/nashorn/test/script/basic/getclassname.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/getter_callsite.js b/nashorn/test/script/basic/getter_callsite.js
index 1e0800f..0d72344 100644
--- a/nashorn/test/script/basic/getter_callsite.js
+++ b/nashorn/test/script/basic/getter_callsite.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Check that getter property is properly invoked by a callsite
- * 
+ *
  * @test
  * @run
  */
@@ -32,7 +32,7 @@
   return { get foo() { return a }};
 }
 
-function printFoo(obj) { 
+function printFoo(obj) {
     print("obj.foo is " + obj.foo);
 }
 
diff --git a/nashorn/test/script/basic/gettercalls.js b/nashorn/test/script/basic/gettercalls.js
index 200f1ce..fe69e67 100644
--- a/nashorn/test/script/basic/gettercalls.js
+++ b/nashorn/test/script/basic/gettercalls.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/getterfunc.js b/nashorn/test/script/basic/getterfunc.js
index 2c2cc4b..d3ce6f3 100644
--- a/nashorn/test/script/basic/getterfunc.js
+++ b/nashorn/test/script/basic/getterfunc.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/gettersetter.js b/nashorn/test/script/basic/gettersetter.js
index 68106bc..ff5e75a 100644
--- a/nashorn/test/script/basic/gettersetter.js
+++ b/nashorn/test/script/basic/gettersetter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Getter/Setter test.
  *
  * @test
- * @run 
+ * @run
  */
 
 'use strict';
@@ -39,7 +39,7 @@
                 this._x = x;
             }
         };
-        
+
 var b = {
             _x : "default",
             get x() {
@@ -47,7 +47,7 @@
             }
         };
 
-        
+
 var c = {
             _x : "default",
             set x(x) {
diff --git a/nashorn/test/script/basic/globalaccess.js b/nashorn/test/script/basic/globalaccess.js
index 6e18cfa..282775a 100644
--- a/nashorn/test/script/basic/globalaccess.js
+++ b/nashorn/test/script/basic/globalaccess.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/globals.js b/nashorn/test/script/basic/globals.js
index 4e2b47f..b3acfe2 100644
--- a/nashorn/test/script/basic/globals.js
+++ b/nashorn/test/script/basic/globals.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/globalscope.js b/nashorn/test/script/basic/globalscope.js
index 7e87bdf..db72045 100644
--- a/nashorn/test/script/basic/globalscope.js
+++ b/nashorn/test/script/basic/globalscope.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Global scope test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var g = this;
diff --git a/nashorn/test/script/basic/hello.js b/nashorn/test/script/basic/hello.js
index 19fca9f..278887b 100644
--- a/nashorn/test/script/basic/hello.js
+++ b/nashorn/test/script/basic/hello.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Simple "hello world" test
  *
  * @test
- * @run 
+ * @run
  */
 
 print("hello world");
diff --git a/nashorn/test/script/basic/herestr_operator.js b/nashorn/test/script/basic/herestr_operator.js
index 0e5b8af..25d898c 100644
--- a/nashorn/test/script/basic/herestr_operator.js
+++ b/nashorn/test/script/basic/herestr_operator.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/hideLocationProperties.js
similarity index 69%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/hideLocationProperties.js
index db358d2..62c1ec06 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/hideLocationProperties.js
@@ -1,33 +1,57 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Tests the hiding of location properties by local variables etc.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
+function x(__FILE__) {
+    print(__FILE__);
+}
 
+function y(__FILE__) {
+    print(__FILE__);
+    function y1() { __FILE__ }
+}
+
+function w(__FILE__) {
+    print(__FILE__);
+    return arguments;
+}
+
+function z(__FILE__) {
+    (function() { print(__FILE__) })()
+}
+
+print(__FILE__.replace(/\\/g, "/"))
+
+var o = { __FILE__: "woot" }
+with(o) { print(__FILE__) }
+
+x("foo")
+y("bar")
+w("boo")
+z("baz")
diff --git a/nashorn/test/script/basic/hideLocationProperties.js.EXPECTED b/nashorn/test/script/basic/hideLocationProperties.js.EXPECTED
new file mode 100644
index 0000000..3af2a38
--- /dev/null
+++ b/nashorn/test/script/basic/hideLocationProperties.js.EXPECTED
@@ -0,0 +1,6 @@
+test/script/basic/hideLocationProperties.js
+woot
+foo
+bar
+boo
+baz
diff --git a/nashorn/test/script/basic/illegaljavaname.js b/nashorn/test/script/basic/illegaljavaname.js
index 20ccc5a..44186cc 100644
--- a/nashorn/test/script/basic/illegaljavaname.js
+++ b/nashorn/test/script/basic/illegaljavaname.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/importpackage.js b/nashorn/test/script/basic/importpackage.js
index 9a2b3a3..35b3a1f 100644
--- a/nashorn/test/script/basic/importpackage.js
+++ b/nashorn/test/script/basic/importpackage.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/incheck.js b/nashorn/test/script/basic/incheck.js
index 1571b62..db366e0 100644
--- a/nashorn/test/script/basic/incheck.js
+++ b/nashorn/test/script/basic/incheck.js
@@ -1,30 +1,30 @@
 /*
  * 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.
  */
 
 /**
- * Check that the expression ("property" in obj) works for own property as 
+ * Check that the expression ("property" in obj) works for own property as
  * well as properties 'inherited' from proto chain.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/indexedcall.js b/nashorn/test/script/basic/indexedcall.js
index b3f651b..f0e5d65 100644
--- a/nashorn/test/script/basic/indexedcall.js
+++ b/nashorn/test/script/basic/indexedcall.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/info.js b/nashorn/test/script/basic/info.js
index 958572c..3d27f8f 100644
--- a/nashorn/test/script/basic/info.js
+++ b/nashorn/test/script/basic/info.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/inherited_nonwritable.js b/nashorn/test/script/basic/inherited_nonwritable.js
index c794332..db82658 100644
--- a/nashorn/test/script/basic/inherited_nonwritable.js
+++ b/nashorn/test/script/basic/inherited_nonwritable.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/instanceof.js b/nashorn/test/script/basic/instanceof.js
index 31878b5..05b9142 100644
--- a/nashorn/test/script/basic/instanceof.js
+++ b/nashorn/test/script/basic/instanceof.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/instanceof2.js b/nashorn/test/script/basic/instanceof2.js
index a6c07c2..84c9b59 100644
--- a/nashorn/test/script/basic/instanceof2.js
+++ b/nashorn/test/script/basic/instanceof2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Instanceof test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var x = { a: 1, b: "string", c: [1, 2, 3], d: function() {} };
diff --git a/nashorn/test/script/basic/interfaces.js b/nashorn/test/script/basic/interfaces.js
index 1c42e9d..bb668a6 100644
--- a/nashorn/test/script/basic/interfaces.js
+++ b/nashorn/test/script/basic/interfaces.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -28,7 +28,7 @@
  * @run
  */
 
-// implement java.lang.Runnable interface 
+// implement java.lang.Runnable interface
 var runnable = new java.lang.Runnable({
     run: function() {
         print("Inside run function");
diff --git a/nashorn/test/script/basic/iterator.js b/nashorn/test/script/basic/iterator.js
index 0b70db4..6f8f0f1 100644
--- a/nashorn/test/script/basic/iterator.js
+++ b/nashorn/test/script/basic/iterator.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Verify that basic for..in works for objects, arrays.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/java.js b/nashorn/test/script/basic/java.js
index b3aaea1..af4b360 100644
--- a/nashorn/test/script/basic/java.js
+++ b/nashorn/test/script/basic/java.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/javaadapter.js b/nashorn/test/script/basic/javaadapter.js
index 484a5d2..e8c9551 100644
--- a/nashorn/test/script/basic/javaadapter.js
+++ b/nashorn/test/script/basic/javaadapter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/javaarray.js b/nashorn/test/script/basic/javaarray.js
index 5a15888..727b926 100644
--- a/nashorn/test/script/basic/javaarray.js
+++ b/nashorn/test/script/basic/javaarray.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/javaarrayconversion.js b/nashorn/test/script/basic/javaarrayconversion.js
index 96ebe90..6168247 100644
--- a/nashorn/test/script/basic/javaarrayconversion.js
+++ b/nashorn/test/script/basic/javaarrayconversion.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Tests for conversion of JavaScript arrays to Java arrays and the other
- * way round. Also generally useful as a JavaScript-to-Java type conversion 
+ * way round. Also generally useful as a JavaScript-to-Java type conversion
  * test.
  *
  * @test
@@ -49,9 +49,9 @@
   testF(inputValue, type, isNaN)
 }
 
-// Those labeled "Correct?" are not clearly correct conversions. Those 
-// labeled "TypeError maybe?" could actually throw a TypeError, or only 
-// throw a TypeError when in strict mode. 
+// Those labeled "Correct?" are not clearly correct conversions. Those
+// labeled "TypeError maybe?" could actually throw a TypeError, or only
+// throw a TypeError when in strict mode.
 // The case of ("false", "boolean") => true is particularly amusing.
 
 test(x, "int", 0) // Correct? TypeError maybe?
diff --git a/nashorn/test/script/basic/javaclassoverrides.js b/nashorn/test/script/basic/javaclassoverrides.js
index 2fa7a85..e931192 100644
--- a/nashorn/test/script/basic/javaclassoverrides.js
+++ b/nashorn/test/script/basic/javaclassoverrides.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/javaexceptions.js b/nashorn/test/script/basic/javaexceptions.js
index 3f81f69..5afc443 100644
--- a/nashorn/test/script/basic/javaexceptions.js
+++ b/nashorn/test/script/basic/javaexceptions.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * Basic checks for throwing and catching java exceptions from script.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/javaimporter.js b/nashorn/test/script/basic/javaimporter.js
index 42551d1..5a198c8 100644
--- a/nashorn/test/script/basic/javaimporter.js
+++ b/nashorn/test/script/basic/javaimporter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -42,7 +42,7 @@
 print("java=" + map.get("java"));
 print("cpp=" + map.get("cpp"));
 
-var imports2 = new JavaImporter(java.io, java.util); 
+var imports2 = new JavaImporter(java.io, java.util);
 with (imports2) {
    print(File);
 }
diff --git a/nashorn/test/script/basic/javainnerclasses.js b/nashorn/test/script/basic/javainnerclasses.js
index c84571d..3038969 100644
--- a/nashorn/test/script/basic/javainnerclasses.js
+++ b/nashorn/test/script/basic/javainnerclasses.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 // Do it with Java.type()
 var outer = new (Java.type("jdk.nashorn.test.models.OuterClass"))("apple")
 print(outer)
diff --git a/nashorn/test/script/basic/javasigcall.js b/nashorn/test/script/basic/javasigcall.js
index c1a2df7..14c62f8 100644
--- a/nashorn/test/script/basic/javasigcall.js
+++ b/nashorn/test/script/basic/javasigcall.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/jquery.js b/nashorn/test/script/basic/jquery.js
index f88d94b..646aee6 100644
--- a/nashorn/test/script/basic/jquery.js
+++ b/nashorn/test/script/basic/jquery.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,49 +29,49 @@
  */
 
 var urls = [
-	    'http://code.jquery.com/jquery-1.7.2.min.js',
-	    'http://code.jquery.com/jquery-1.7.2.js'
-	    ];
-	    
+        'http://code.jquery.com/jquery-1.7.2.min.js',
+        'http://code.jquery.com/jquery-1.7.2.js'
+        ];
+
 function test_jquery(url) {
-    
+
     //bug one repro - this should compile
     function a() {
-	var c;
-	if (func1(zz) || (c = func2(zz)) ) {
-	    if (c) {
-	    } 
-	} 
-	return target;
+    var c;
+    if (func1(zz) || (c = func2(zz)) ) {
+        if (c) {
+        }
     }
-    
+    return target;
+    }
+
     //bug two repro - this should compile
     function b() {
-	return ((v ? i : "") + "str");
+    return ((v ? i : "") + "str");
     }
-    
+
     function checkWindow(e) {
-	if (e instanceof ReferenceError && e.toString().indexOf('window') != -1) {
-	    return;
-	}
-	throw e;
+    if (e instanceof ReferenceError && e.toString().indexOf('window') != -1) {
+        return;
     }
-    
+    throw e;
+    }
+
     var name;
-    
-    try {    
-	var split = url.split('/');
-	name = split[split.length - 1];
-	var path  = __DIR__ + "../external/jquery/" + name;
-	try {
-	    load(path);
-	} catch (e) {
-	    checkWindow(e);
-	}
+
+    try {
+    var split = url.split('/');
+    name = split[split.length - 1];
+    var path  = __DIR__ + "../external/jquery/" + name;
+    try {
+        load(path);
     } catch (e) {
-	print("Unexpected exception " + e);
+        checkWindow(e);
     }
-    
+    } catch (e) {
+    print("Unexpected exception " + e);
+    }
+
     print("done " + name);
 }
 
diff --git a/nashorn/test/script/basic/jsadapter.js b/nashorn/test/script/basic/jsadapter.js
index 9fe80ad..a5c7ec2 100644
--- a/nashorn/test/script/basic/jsadapter.js
+++ b/nashorn/test/script/basic/jsadapter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/jsadapterlink.js b/nashorn/test/script/basic/jsadapterlink.js
index 15117b3..ed44d61 100644
--- a/nashorn/test/script/basic/jsadapterlink.js
+++ b/nashorn/test/script/basic/jsadapterlink.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/json.js b/nashorn/test/script/basic/json.js
index 72391ff..ce18146 100644
--- a/nashorn/test/script/basic/json.js
+++ b/nashorn/test/script/basic/json.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -51,12 +51,12 @@
 print(JSON.stringify(obj));
 print(JSON.stringify(obj2));
 
-try { 
+try {
     JSON.parse('{ "foo" /*comment */ : 44, "bar" : "hello" }', reviver);
     print("Fail!");
 } catch (e) {
     if (!(e instanceof SyntaxError)) {
-	print("Comments are illegal in JSON. Should throw SyntaxError, not " + e);
+    print("Comments are illegal in JSON. Should throw SyntaxError, not " + e);
     }
 }
 print("Success!");
diff --git a/nashorn/test/script/basic/list.js b/nashorn/test/script/basic/list.js
index 59136c0..acbffca 100644
--- a/nashorn/test/script/basic/list.js
+++ b/nashorn/test/script/basic/list.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/literal.js b/nashorn/test/script/basic/literal.js
index 2003c34..8c21091 100644
--- a/nashorn/test/script/basic/literal.js
+++ b/nashorn/test/script/basic/literal.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Object literal test.
  *
  * @test
- * @run 
+ * @run
  */
 
 
diff --git a/nashorn/test/script/basic/load.js b/nashorn/test/script/basic/load.js
index 4c8f9be..7426b44 100644
--- a/nashorn/test/script/basic/load.js
+++ b/nashorn/test/script/basic/load.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/loadedfile.js b/nashorn/test/script/basic/loadedfile.js
index dfc09a3..459e122 100644
--- a/nashorn/test/script/basic/loadedfile.js
+++ b/nashorn/test/script/basic/loadedfile.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/localundef.js b/nashorn/test/script/basic/localundef.js
index 0548492..82922ef 100644
--- a/nashorn/test/script/basic/localundef.js
+++ b/nashorn/test/script/basic/localundef.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -32,7 +32,7 @@
 function func(arg){
     // initializing "x" with something removes VerifyError!
     var x;
-    if (arg == 1) { 
+    if (arg == 1) {
         return x;
     } else {
         x = 0;
diff --git a/nashorn/test/script/basic/map.js b/nashorn/test/script/basic/map.js
index c024f6e..79bf3d3 100644
--- a/nashorn/test/script/basic/map.js
+++ b/nashorn/test/script/basic/map.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -41,7 +41,7 @@
 
 print("m = " + m)
 print("m.empty = " + m.empty) // prints "false"
-print("m['empty'] = " + m['empty']) 
+print("m['empty'] = " + m['empty'])
 print("m[empty_key] = " + m[empty_key]) // prints "foo"
 
 print("m.bwah = " + m.bwah) // prints "null"
diff --git a/nashorn/test/script/basic/math.js b/nashorn/test/script/basic/math.js
index d6b34c4..2d8c2d2 100644
--- a/nashorn/test/script/basic/math.js
+++ b/nashorn/test/script/basic/math.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/minuszero.js b/nashorn/test/script/basic/minuszero.js
index 21c1cdf..7caa9aa 100644
--- a/nashorn/test/script/basic/minuszero.js
+++ b/nashorn/test/script/basic/minuszero.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/module.js b/nashorn/test/script/basic/module.js
index 665e362..af6f632 100644
--- a/nashorn/test/script/basic/module.js
+++ b/nashorn/test/script/basic/module.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,4 +31,4 @@
   exports.func = function() {
      print("module.func called");
   }
-} 
+}
diff --git a/nashorn/test/script/basic/moduleload.js b/nashorn/test/script/basic/moduleload.js
index 633d2a1..bcabe17 100644
--- a/nashorn/test/script/basic/moduleload.js
+++ b/nashorn/test/script/basic/moduleload.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/nashorn2.js b/nashorn/test/script/basic/nashorn2.js
index d509a01..a8eb144 100644
--- a/nashorn/test/script/basic/nashorn2.js
+++ b/nashorn/test/script/basic/nashorn2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,9 +25,9 @@
  * Regression:  NAS2 - lhs of index has no symbol.
  *
  * @test
- * @run 
+ * @run
  */
- 
+
 
 var obj = { prop: [3, 4] };
 print(obj.prop[0]);
diff --git a/nashorn/test/script/basic/natives.js b/nashorn/test/script/basic/natives.js
index 60f9610..ee7e411 100644
--- a/nashorn/test/script/basic/natives.js
+++ b/nashorn/test/script/basic/natives.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 var s = "abcded";
 var n = 1289.90;
 var b = true;
diff --git a/nashorn/test/script/basic/new.js b/nashorn/test/script/basic/new.js
index 25904b1..ec26b69 100644
--- a/nashorn/test/script/basic/new.js
+++ b/nashorn/test/script/basic/new.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * new Function test.
  *
  * @test
- * @run 
+ * @run
  */
 
 function MyObject() {
diff --git a/nashorn/test/script/basic/newexpr.js b/nashorn/test/script/basic/newexpr.js
index d8d1b48..90c3117 100644
--- a/nashorn/test/script/basic/newexpr.js
+++ b/nashorn/test/script/basic/newexpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -44,8 +44,8 @@
 }
 
 print(new func().foo);
- 
-print ((new function() { this.x = "hello" }).x); 
+
+print ((new function() { this.x = "hello" }).x);
 
 var abc = {
    bar: function() {
@@ -56,10 +56,10 @@
 print(new abc.bar().x);
 
 function func2() {
-    return { 
+    return {
         foo: function() {
             print("foo");
-        } 
+        }
     };
 };
 
diff --git a/nashorn/test/script/basic/newnew.js b/nashorn/test/script/basic/newnew.js
index 98a8e4d..9eaa516 100644
--- a/nashorn/test/script/basic/newnew.js
+++ b/nashorn/test/script/basic/newnew.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 function myObject() {
     this.x = 10;
     this.y = 20;
diff --git a/nashorn/test/script/basic/no_line_numbers.js b/nashorn/test/script/basic/no_line_numbers.js
index bd18e4d..f53eb51 100644
--- a/nashorn/test/script/basic/no_line_numbers.js
+++ b/nashorn/test/script/basic/no_line_numbers.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -53,8 +53,8 @@
 
 while (true) {
     break;
-    if (true) { 
-	var s; 
+    if (true) {
+    var s;
     }
 }
 
@@ -64,20 +64,20 @@
 for ( ; ; ) {
     break;
     while (true) {
-	do {
-	    var u;
-	} while (true);
-    }    
+    do {
+        var u;
+    } while (true);
+    }
 }
 
 function terminal() {
     print("r = "+r);
     print("t = "+t);
     for (;;) {
-	var r;
-	return;
-	var t;
-	print("THIS SHOULD NEVER BE PRINTED!");
+    var r;
+    return;
+    var t;
+    print("THIS SHOULD NEVER BE PRINTED!");
     }
     print("NEITHER SHOULD THIS");
 }
@@ -87,13 +87,13 @@
 function terminal2() {
     print("q = "+q);
     for (;;) {
-	return;
-	print("THIS SHOULD NEVER BE PRINTED!");
+    return;
+    print("THIS SHOULD NEVER BE PRINTED!");
     }
     print("NEITHER SHOULD THIS");
 }
 
-try { 
+try {
     terminal2();
 } catch (e) {
     print(e);
@@ -111,13 +111,13 @@
 }  catch (e) {
     print(e);
 }
-	
+
 
 function disp_a() {
     var a = 20;
     print("Value of 'a' inside the function " + a);
 }
-	
+
 var a = 10;
 
 disp_a();
diff --git a/nashorn/test/script/basic/nonconstructors.js b/nashorn/test/script/basic/nonconstructors.js
index 8fb0d36..9c529db 100644
--- a/nashorn/test/script/basic/nonconstructors.js
+++ b/nashorn/test/script/basic/nonconstructors.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/nosuchmethod.js b/nashorn/test/script/basic/nosuchmethod.js
index 6ac03f2..6a539dc 100644
--- a/nashorn/test/script/basic/nosuchmethod.js
+++ b/nashorn/test/script/basic/nosuchmethod.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Test noSuchMethod feature.
  *
  * @test
- * @run 
+ * @run
  */
 
 __noSuchProperty__ = function(a) { this[a] = "xxx"; return this[a]; }
diff --git a/nashorn/test/script/basic/nosuchproperty.js b/nashorn/test/script/basic/nosuchproperty.js
index 8797610..a414f17 100644
--- a/nashorn/test/script/basic/nosuchproperty.js
+++ b/nashorn/test/script/basic/nosuchproperty.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/number.js b/nashorn/test/script/basic/number.js
index 9215615..83f915c 100644
--- a/nashorn/test/script/basic/number.js
+++ b/nashorn/test/script/basic/number.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/numberstring.js b/nashorn/test/script/basic/numberstring.js
index 7daddb0..62b3d58 100644
--- a/nashorn/test/script/basic/numberstring.js
+++ b/nashorn/test/script/basic/numberstring.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/objectprops.js b/nashorn/test/script/basic/objectprops.js
index 525e80c..6f157ad 100644
--- a/nashorn/test/script/basic/objectprops.js
+++ b/nashorn/test/script/basic/objectprops.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -45,7 +45,7 @@
      xyz: { value: 44 },
      abc: { get: function() { print("get abc"); return "abc"; } }
   }
-); 
+);
 
 print("obj.xyz = " + obj.xyz);
 print("obj.abc = " + obj.abc);
@@ -54,7 +54,7 @@
 var obj2 = Object.create(MyConstructor.prototype);
 print("obj2 in MyConstructor instance? " + (obj2 instanceof MyConstructor));
 
-var obj3 = Object.create(Object.prototype, 
+var obj3 = Object.create(Object.prototype,
   {
      xyz: { value: 44 }
   }
diff --git a/nashorn/test/script/basic/objects.js b/nashorn/test/script/basic/objects.js
index 9d91379..fd79508 100644
--- a/nashorn/test/script/basic/objects.js
+++ b/nashorn/test/script/basic/objects.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/octane-payload.js b/nashorn/test/script/basic/octane-payload.js
new file mode 100644
index 0000000..36c780d
--- /dev/null
+++ b/nashorn/test/script/basic/octane-payload.js
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ */
+
+/**
+ * @subtest
+ */
+
+function initZlib() {
+    zlib = new BenchmarkSuite('zlib', [152815148], [
+                            new Benchmark('zlib', false, true, 10,
+                                  runZlib, undefined, tearDownZlib, null, 3)]);
+}
+
+var tests = [
+    {name:"box2d",         files:["box2d.js"],                         suite:"Box2DBenchmark"},
+    {name:"code-load",     files:["code-load.js"],                     suite:"CodeLoad"},
+    {name:"crypto",        files:["crypto.js"],                        suite:"Crypto"},
+    {name:"deltablue",     files:["deltablue.js"],                     suite:"DeltaBlue"},
+    {name:"earley-boyer",  files:["earley-boyer.js"],                  suite:"EarleyBoyer"},
+    {name:"gbemu",         files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
+    {name:"mandreel",      files:["mandreel.js"],                      suite:"MandreelBenchmark"},
+    {name:"navier-stokes", files:["navier-stokes.js"],                 suite:"NavierStokes"},
+    {name:"pdfjs",         files:["pdfjs.js"],                         suite:"PdfJS"},
+    {name:"raytrace",      files:["raytrace.js"],                      suite:"RayTrace"},
+    {name:"regexp",        files:["regexp.js"],                        suite:"RegExpSuite"},
+    {name:"richards",      files:["richards.js"],                      suite:"Richards"},
+    {name:"splay",         files:["splay.js"],                         suite:"Splay"},
+    {name:"typescript",    files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"},
+    //zlib currently disabled - requires read
+    {name:"zlib",          files:["zlib.js", "zlib-data.js"], suite:"zlib", before:initZlib}
+];
+
+var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
+
+// TODO: why is this path hard coded when it's defined in project properties?
+var path = dir + "../external/octane/";
+var base = path + "base.js";
+
diff --git a/nashorn/test/script/basic/optimistic_arithmetic_check_type.js b/nashorn/test/script/basic/optimistic_arithmetic_check_type.js
new file mode 100644
index 0000000..62ff301
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_arithmetic_check_type.js
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @option --optimistic-types=true
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = 3, b, c;
+var x = { a: 2, b:1, c: 7, d: -1}
+var y = { a: Number.MAX_VALUE, b: Number.POSITIVE_INFINITY, c: "Hello", d: undefined}
+
+// Testing arithmetic operators
+//-- Local variable
+print(inspect(x.a*x.b, "local int multiplication by local int"))
+print(inspect(x.a/x.b, "local int division by local int without remainder"))
+print(inspect(x.c/x.a, "local int division by local int with remainder"))
+print(inspect(x.c%x.a, "local int modulo by local int"))
+print(inspect(x.a+x.b, "local int addition local int"))
+print(inspect(x.a-x.b, "local int substraction local int"))
+print(inspect(y.a*y.a, "max value multiplication by max value"))
+print(inspect(y.b*y.b, "infinity multiplication by infinity"))
+print(inspect(x.d/y.b, "-1 division by infinity"))
+print(inspect(y.b/x.e, "infinity division by zero"))
+print(inspect(y.b/y.c, "infinity division by String"))
+print(inspect(y.d/y.d, "local undefined division by local undefined"))
+print(inspect(y.d*y.d, "local undefined multiplication by local undefined"))
+print(inspect(y.d+x.a, "local undefined addition local int"))
+print(inspect(y.d--, "local undefined decrement postfix"))
+print(inspect(--y.d, "local undefined decrement prefix"))
+print(inspect(x.a++, "local int increment postfix"))
+print(inspect(++x.a, "local int increment prefix"))
+print(inspect(x.a--, "local int decrement postfix"))
+print(inspect(--x.a, "local int decrement prefix"))
+print(inspect(+x.a, "local int unary plus"))
+print(inspect(-x.a, "local int unary minus"))
+//-- Global variable
+print(inspect(b*c, "undefined multiplication by undefined"))
+print(inspect(b/c, "undefined division by undefined"))
+print(inspect(a+a, "global int addition global int"))
+print(inspect(a-a, "global int substraction global int"))
+print(inspect(a*a, "global int multiplication by global int"))
+print(inspect(a++, "global int increment postfix"))
+print(inspect(++a, "global int increment prefix"))
+print(inspect(a--, "global int decrement postfix"))
+print(inspect(--a, "global int decrement prefix"))
+print(inspect(+a, "global int unary plus"))
+print(inspect(-a, "global int unary minus"))
+print(inspect(b--, "global undefined decrement postfix"))
+print(inspect(--b, "global undefined decrement prefix"))
+print(inspect(x, "object"))
+print(inspect(x/x, "object division by object"))
+print(inspect(x/y, "object division by object"))
diff --git a/nashorn/test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED b/nashorn/test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED
new file mode 100644
index 0000000..bce78f9
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_arithmetic_check_type.js.EXPECTED
@@ -0,0 +1,38 @@
+local int multiplication by local int: int
+local int division by local int without remainder: int
+local int division by local int with remainder: double
+local int modulo by local int: int
+local int addition local int: int
+local int substraction local int: int
+max value multiplication by max value: double
+infinity multiplication by infinity: double
+-1 division by infinity: double
+infinity division by zero: double
+infinity division by String: double
+local undefined division by local undefined: double
+local undefined multiplication by local undefined: double
+local undefined addition local int: double
+local undefined decrement postfix: double
+local undefined decrement prefix: double
+local int increment postfix: int
+local int increment prefix: int
+local int decrement postfix: int
+local int decrement prefix: int
+local int unary plus: int
+local int unary minus: int
+undefined multiplication by undefined: double
+undefined division by undefined: double
+global int addition global int: int
+global int substraction global int: int
+global int multiplication by global int: int
+global int increment postfix: int
+global int increment prefix: int
+global int decrement postfix: int
+global int decrement prefix: int
+global int unary plus: int
+global int unary minus: int
+global undefined decrement postfix: double
+global undefined decrement prefix: double
+object: object
+object division by object: double
+object division by object: double
\ No newline at end of file
diff --git a/nashorn/test/script/basic/optimistic_assignment_check_type.js b/nashorn/test/script/basic/optimistic_assignment_check_type.js
new file mode 100644
index 0000000..7ead00d
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_assignment_check_type.js
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @option --optimistic-types=true
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = b = 3;
+var c;
+var x = { a: 2, b:1, c: 7, d: -1, e: 1}
+var y = { a: undefined, b: undefined}
+
+// Testing assignment operators
+//-- Global variable
+print(inspect(a=c, "global int assignment to global variable"))
+print(inspect(a=b, "undefined assignment to global int"))
+print(inspect(a=y.a, "global int assignment to undefined"))
+print(inspect(a+=b, "undefined addition assignment to global int"))
+print(inspect(b=b+b, "global int addition global int"))
+print(inspect(b+= y.a, "global int addition assignment undefined"))
+//--Local variable
+print(inspect(x.a+= y.a, "local int addition assignment local undefined"))
+print(inspect(x.b=y.a, "local int assignment to undefined"))
+print(inspect(y.a+=y.a, "local undefined addition assignment local undefined"))
+print(inspect(x.c-=x.d, "local int substraction assignment local int"))
+print(inspect(x.c*=x.d, "local int multiplication assignment local int"))
+print(inspect(x.c/=x.d, "local int division assignment local int"))
+print(inspect(y.b=x.c, "local undefined assignment to local int"))
+print(inspect(y.c=x.c, "local boolean assignment to local int"))
diff --git a/nashorn/test/script/basic/optimistic_assignment_check_type.js.EXPECTED b/nashorn/test/script/basic/optimistic_assignment_check_type.js.EXPECTED
new file mode 100644
index 0000000..4e4deea
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_assignment_check_type.js.EXPECTED
@@ -0,0 +1,14 @@
+global int assignment to global variable: undefined
+undefined assignment to global int: int
+global int assignment to undefined: undefined
+undefined addition assignment to global int: double
+global int addition global int: int
+global int addition assignment undefined: double
+local int addition assignment local undefined: double
+local int assignment to undefined: undefined
+local undefined addition assignment local undefined: double
+local int substraction assignment local int: int
+local int multiplication assignment local int: int
+local int division assignment local int: int
+local undefined assignment to local int: int
+local boolean assignment to local int: int
\ No newline at end of file
diff --git a/nashorn/test/script/basic/optimistic_check_type.js b/nashorn/test/script/basic/optimistic_check_type.js
new file mode 100644
index 0000000..d2b50a4
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_check_type.js
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @option --optimistic-types=true
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a=3, b=2.3, c=true, d;
+var x = { a: 2, b:0, c:undefined}
+var trees = new Array("redwood", "bay", "cedar", "oak");
+
+// Testing conditional operator
+print(inspect("" ? b : x.a, "ternary operator"))
+print(inspect(x.b ? b : x.a, "ternary operator"))
+print(inspect(c ? b : a, "ternary operator"))
+print(inspect(!c ? b : a, "ternary operator"))
+print(inspect(d ? b : x.c, "ternary operator"))
+print(inspect(x.c ? a : c, "ternary operator"))
+print(inspect(c ? d : a, "ternary operator"))
+print(inspect(c ? +a : b, "ternary operator"))
+
+// Testing format methods
+print(inspect(b.toFixed(2), "global double toFixed()"))
+print(inspect(b.toPrecision(2)/1, "global double toPrecision() divided by 1"))
+print(inspect(b.toExponential(2), "global double toExponential()"))
+
+// Testing arrays
+print(inspect(trees[1], "member object"))
+trees[1] = undefined;
+print(inspect(trees[1], "member undefined"))
+print(inspect(1 in trees ? b : a, "conditional on array member"))
+delete trees[2]
+print(inspect(2 in trees ? b : a, "conditional on array member"))
+print(inspect(3 in trees ? trees[2]="bay" : a, "conditional on array member"))
+print(inspect("oak" in trees ? b : a, "conditional on array member"))
+
+// Testing nested functions and return value
+function f1() {
+    var x = 2, y = 1;
+    function g() {
+        print(inspect(x, "outer local variable"));
+        print(inspect(a, "global variable"));
+        print(inspect(x*y, "outer local int multiplication by outer local int"));
+        print(inspect(a*d, "global int multiplication by global undefined"));
+    }
+    g()
+}
+f1()
+
+function f2(a,b,c) {
+    g = (a+b) * c;
+    print(inspect(c, "local undefined"));
+    print(inspect(a+b, "local undefined addition local undefined"));
+    print(inspect(g, "local undefined multiplication by undefined"));
+}
+f2()
+
+function f3(a,b) {
+    g = a && b;
+    print(inspect(g, "local undefined AND local undefined"));
+    print(inspect(c||g, "global true OR local undefined"));
+}
+f3()
+
+function f4() {
+    var x = true, y = 0;
+    function g() {
+        print(inspect(x+y, "outer local true addition local int"));
+        print(inspect(a+x, "global int addition outer local true"));
+        print(inspect(x*y, "outer local true multiplication by outer local int"));
+        print(inspect(y*d, "outer local int multiplication by global undefined"));
+    }
+    g()
+}
+f4()
diff --git a/nashorn/test/script/basic/optimistic_check_type.js.EXPECTED b/nashorn/test/script/basic/optimistic_check_type.js.EXPECTED
new file mode 100644
index 0000000..b1ae800
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_check_type.js.EXPECTED
@@ -0,0 +1,30 @@
+ternary operator: int
+ternary operator: int
+ternary operator: double
+ternary operator: int
+ternary operator: undefined
+ternary operator: boolean
+ternary operator: undefined
+ternary operator: int
+global double toFixed(): object
+global double toPrecision() divided by 1: double
+global double toExponential(): object
+member object: object
+member undefined: undefined
+conditional on array member: double
+conditional on array member: int
+conditional on array member: object
+conditional on array member: int
+outer local variable: int
+global variable: int
+outer local int multiplication by outer local int: int
+global int multiplication by global undefined: double
+local undefined: undefined
+local undefined addition local undefined: double
+local undefined multiplication by undefined: double
+local undefined AND local undefined: undefined
+global true OR local undefined: boolean
+outer local true addition local int: double
+global int addition outer local true: double
+outer local true multiplication by outer local int: double
+outer local int multiplication by global undefined: double
diff --git a/nashorn/test/script/basic/optimistic_logical_check_type.js b/nashorn/test/script/basic/optimistic_logical_check_type.js
new file mode 100644
index 0000000..bb9de0c
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_logical_check_type.js
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8036987, 8037572
+ * @summary Implement tests that checks static types in the compiled code
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = 3, b = true, c = 0;
+var x = { a: 2, b: undefined, c: true}
+
+// Testing logical operators
+//-- Global variable
+print(inspect("cat" && "dog", "object AND object"))
+print(inspect(b && a, "true AND non-falsey global int"))
+print(inspect(a && b, "non-falsey global int AND true"))
+print(inspect(x && b, "non-falsey object AND true"))
+print(inspect(b && x, "true AND non-falsey object"))
+print(inspect("cat" || "dog", "object OR object"))
+print(inspect(b || a, "true OR non-falsey global int"))
+print(inspect(a || b, "non-falsey global int OR true"))
+print(inspect(x || b, "non-falsey object OR true"))
+print(inspect(b || x, "true OR non-falsey object"))
+print(inspect(!x.c || b, "false OR true"))
+print(inspect(c && b, "falsey global int AND true"))
+print(inspect(c || x.b, "falsey global int OR undefined"))
+print(inspect(!c || x.b, "logical not falsey global int OR undefined"))
+print(inspect(!b || x.b, "false OR undefined"))
+print(inspect(!b || c, "false OR falsey global int"))
+print(inspect(!c || c, "logical not falsey global int OR falsey global int"))
+ //--Local variable
+print(inspect(x.b && a, "local undefined AND non-falsey global int"))
+print(inspect(b && x.b, "true AND local undefined"))
+print(inspect(x.b && x.a, "local undefined AND non-falsey local int"))
+print(inspect(x.b || b, "local undefined OR true"))
+print(inspect(b || x.b, "true OR local undefined"))
+print(inspect(x.a && x.c, "non-falsey local int AND true"))
+print(inspect(x.c && x.a, "true AND non-falsey local int"))
+print(inspect(x.c && !!x.a, "true AND double logical not non-falsey local int "))
+print(inspect(!x.c && x.a, "false AND non-falsey local int"))
+print(inspect(x.a || x.c, "non-falsey local int OR true"))
+print(inspect(!x.c || x.c, "false OR true"))
diff --git a/nashorn/test/script/basic/optimistic_logical_check_type.js.EXPECTED b/nashorn/test/script/basic/optimistic_logical_check_type.js.EXPECTED
new file mode 100644
index 0000000..994b083
--- /dev/null
+++ b/nashorn/test/script/basic/optimistic_logical_check_type.js.EXPECTED
@@ -0,0 +1,28 @@
+object AND object: object
+true AND non-falsey global int: int
+non-falsey global int AND true: boolean
+non-falsey object AND true: boolean
+true AND non-falsey object: object
+object OR object: object
+true OR non-falsey global int: boolean
+non-falsey global int OR true: int
+non-falsey object OR true: object
+true OR non-falsey object: boolean
+false OR true: boolean
+falsey global int AND true: int
+falsey global int OR undefined: undefined
+logical not falsey global int OR undefined: boolean
+false OR undefined: undefined
+false OR falsey global int: int
+logical not falsey global int OR falsey global int: boolean
+local undefined AND non-falsey global int: undefined
+true AND local undefined: undefined
+local undefined AND non-falsey local int: undefined
+local undefined OR true: boolean
+true OR local undefined: boolean
+non-falsey local int AND true: boolean
+true AND non-falsey local int: int
+true AND double logical not non-falsey local int : boolean
+false AND non-falsey local int: boolean
+non-falsey local int OR true: int
+false OR true: boolean
diff --git a/nashorn/test/script/basic/options.js b/nashorn/test/script/basic/options.js
index 102bb5e..b97aed0 100644
--- a/nashorn/test/script/basic/options.js
+++ b/nashorn/test/script/basic/options.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/paramspec.js b/nashorn/test/script/basic/paramspec.js
index c0ea2a5..625c972 100644
--- a/nashorn/test/script/basic/paramspec.js
+++ b/nashorn/test/script/basic/paramspec.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/assignmentExpr.js b/nashorn/test/script/basic/parser/assignmentExpr.js
index 231e19f..e5b5641 100644
--- a/nashorn/test/script/basic/parser/assignmentExpr.js
+++ b/nashorn/test/script/basic/parser/assignmentExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/binaryExpr.js b/nashorn/test/script/basic/parser/binaryExpr.js
index a2b761d..b5e6276 100644
--- a/nashorn/test/script/basic/parser/binaryExpr.js
+++ b/nashorn/test/script/basic/parser/binaryExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/breakStat.js b/nashorn/test/script/basic/parser/breakStat.js
index 1b16cc2..3b2b029 100644
--- a/nashorn/test/script/basic/parser/breakStat.js
+++ b/nashorn/test/script/basic/parser/breakStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/breakStat.js.EXPECTED b/nashorn/test/script/basic/parser/breakStat.js.EXPECTED
index 1d9fd07..f9a7db9 100644
--- a/nashorn/test/script/basic/parser/breakStat.js.EXPECTED
+++ b/nashorn/test/script/basic/parser/breakStat.js.EXPECTED
@@ -24,10 +24,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "loop"
-            },
+            "label": "loop",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -42,10 +39,7 @@
                             "body": [
                                 {
                                     "type": "BreakStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "loop"
-                                    }
+                                    "label": "loop"
                                 }
                             ]
                         }
@@ -60,10 +54,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "loop"
-            },
+            "label": "loop",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -77,10 +68,7 @@
                             "body": [
                                 {
                                     "type": "BreakStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "loop"
-                                    }
+                                    "label": "loop"
                                 }
                             ]
                         }
diff --git a/nashorn/test/script/basic/parser/condExpr.js b/nashorn/test/script/basic/parser/condExpr.js
index 3644ff3..f9c59fc 100644
--- a/nashorn/test/script/basic/parser/condExpr.js
+++ b/nashorn/test/script/basic/parser/condExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/continueStat.js b/nashorn/test/script/basic/parser/continueStat.js
index 22ddadd..8a715be 100644
--- a/nashorn/test/script/basic/parser/continueStat.js
+++ b/nashorn/test/script/basic/parser/continueStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/continueStat.js.EXPECTED b/nashorn/test/script/basic/parser/continueStat.js.EXPECTED
index cfd3114..efa51d9 100644
--- a/nashorn/test/script/basic/parser/continueStat.js.EXPECTED
+++ b/nashorn/test/script/basic/parser/continueStat.js.EXPECTED
@@ -24,10 +24,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "begin"
-            },
+            "label": "begin",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -42,10 +39,7 @@
                             "body": [
                                 {
                                     "type": "ContinueStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "begin"
-                                    }
+                                    "label": "begin"
                                 }
                             ]
                         }
@@ -60,10 +54,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "start"
-            },
+            "label": "start",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -77,10 +68,7 @@
                             "body": [
                                 {
                                     "type": "ContinueStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "start"
-                                    }
+                                    "label": "start"
                                 }
                             ]
                         }
diff --git a/nashorn/test/script/basic/parser/debuggerStat.js b/nashorn/test/script/basic/parser/debuggerStat.js
index 60eab78..4edcf34 100644
--- a/nashorn/test/script/basic/parser/debuggerStat.js
+++ b/nashorn/test/script/basic/parser/debuggerStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/functions.js b/nashorn/test/script/basic/parser/functions.js
index 7b624b5..93e3727 100644
--- a/nashorn/test/script/basic/parser/functions.js
+++ b/nashorn/test/script/basic/parser/functions.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/ifStat.js b/nashorn/test/script/basic/parser/ifStat.js
index 5d15666..7664167 100644
--- a/nashorn/test/script/basic/parser/ifStat.js
+++ b/nashorn/test/script/basic/parser/ifStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/labelledStat.js b/nashorn/test/script/basic/parser/labelledStat.js
index 25829a4..2a08729 100644
--- a/nashorn/test/script/basic/parser/labelledStat.js
+++ b/nashorn/test/script/basic/parser/labelledStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED b/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED
index fc5f37e..ca125dc 100644
--- a/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED
+++ b/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED
@@ -3,10 +3,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "begin"
-            },
+            "label": "begin",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -20,10 +17,7 @@
                             "body": [
                                 {
                                     "type": "BreakStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "begin"
-                                    }
+                                    "label": "begin"
                                 }
                             ]
                         }
@@ -38,10 +32,7 @@
     "body": [
         {
             "type": "LabeledStatement",
-            "label": {
-                "type": "Identifier",
-                "name": "begin"
-            },
+            "label": "begin",
             "body": {
                 "type": "BlockStatement",
                 "body": [
@@ -56,10 +47,7 @@
                             "body": [
                                 {
                                     "type": "BreakStatement",
-                                    "label": {
-                                        "type": "Identifier",
-                                        "name": "begin"
-                                    }
+                                    "label": "begin"
                                 }
                             ]
                         }
diff --git a/nashorn/test/script/basic/parser/lhsExpr.js b/nashorn/test/script/basic/parser/lhsExpr.js
index 68f4d6c..24d5c7f 100644
--- a/nashorn/test/script/basic/parser/lhsExpr.js
+++ b/nashorn/test/script/basic/parser/lhsExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED b/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED
index e61c6c8..692791c 100644
--- a/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED
+++ b/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED
@@ -69,10 +69,7 @@
                     "type": "Identifier",
                     "name": "obj"
                 },
-                "property": {
-                    "type": "Identifier",
-                    "name": "foo"
-                },
+                "property": "foo",
                 "computed": false
             }
         }
@@ -91,16 +88,10 @@
                         "type": "Identifier",
                         "name": "obj"
                     },
-                    "property": {
-                        "type": "Identifier",
-                        "name": "foo"
-                    },
+                    "property": "foo",
                     "computed": false
                 },
-                "property": {
-                    "type": "Identifier",
-                    "name": "bar"
-                },
+                "property": "bar",
                 "computed": false
             }
         }
@@ -176,10 +167,7 @@
                         "type": "Identifier",
                         "name": "obj"
                     },
-                    "property": {
-                        "type": "Identifier",
-                        "name": "Type"
-                    },
+                    "property": "Type",
                     "computed": false
                 },
                 "arguments": []
@@ -200,10 +188,7 @@
                         "type": "Identifier",
                         "name": "obj"
                     },
-                    "property": {
-                        "type": "Identifier",
-                        "name": "Type"
-                    },
+                    "property": "Type",
                     "computed": false
                 },
                 "arguments": []
@@ -224,10 +209,7 @@
                         "type": "Identifier",
                         "name": "obj"
                     },
-                    "property": {
-                        "type": "Identifier",
-                        "name": "Type"
-                    },
+                    "property": "Type",
                     "computed": false
                 },
                 "arguments": [
@@ -273,10 +255,7 @@
                         "type": "Identifier",
                         "name": "obj"
                     },
-                    "property": {
-                        "type": "Identifier",
-                        "name": "foo"
-                    },
+                    "property": "foo",
                     "computed": false
                 },
                 "arguments": []
@@ -322,10 +301,7 @@
                         "type": "Identifier",
                         "name": "obj"
                     },
-                    "property": {
-                        "type": "Identifier",
-                        "name": "foo"
-                    },
+                    "property": "foo",
                     "computed": false
                 },
                 "arguments": [
diff --git a/nashorn/test/script/basic/parser/loopStat.js b/nashorn/test/script/basic/parser/loopStat.js
index ba70556..99c3074 100644
--- a/nashorn/test/script/basic/parser/loopStat.js
+++ b/nashorn/test/script/basic/parser/loopStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/objectLitExpr.js b/nashorn/test/script/basic/parser/objectLitExpr.js
index bdecc7f..394a64c 100644
--- a/nashorn/test/script/basic/parser/objectLitExpr.js
+++ b/nashorn/test/script/basic/parser/objectLitExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/parenExpr.js b/nashorn/test/script/basic/parser/parenExpr.js
index 2d52a02..ceaaa36 100644
--- a/nashorn/test/script/basic/parser/parenExpr.js
+++ b/nashorn/test/script/basic/parser/parenExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/primaryExpr.js b/nashorn/test/script/basic/parser/primaryExpr.js
index 950c47f..6a543bf 100644
--- a/nashorn/test/script/basic/parser/primaryExpr.js
+++ b/nashorn/test/script/basic/parser/primaryExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/returnStat.js b/nashorn/test/script/basic/parser/returnStat.js
index 741a234..f143c40 100644
--- a/nashorn/test/script/basic/parser/returnStat.js
+++ b/nashorn/test/script/basic/parser/returnStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/switchStat.js b/nashorn/test/script/basic/parser/switchStat.js
index 6f0dd75..f62a525 100644
--- a/nashorn/test/script/basic/parser/switchStat.js
+++ b/nashorn/test/script/basic/parser/switchStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/throwStat.js b/nashorn/test/script/basic/parser/throwStat.js
index 345e3b8..18a3533 100644
--- a/nashorn/test/script/basic/parser/throwStat.js
+++ b/nashorn/test/script/basic/parser/throwStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/tryCatchStat.js b/nashorn/test/script/basic/parser/tryCatchStat.js
index de15313..15919bd 100644
--- a/nashorn/test/script/basic/parser/tryCatchStat.js
+++ b/nashorn/test/script/basic/parser/tryCatchStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/unaryExpr.js b/nashorn/test/script/basic/parser/unaryExpr.js
index e21b55f..d739bd5 100644
--- a/nashorn/test/script/basic/parser/unaryExpr.js
+++ b/nashorn/test/script/basic/parser/unaryExpr.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/useStrict.js b/nashorn/test/script/basic/parser/useStrict.js
index 4d1c7a9..143eac9 100644
--- a/nashorn/test/script/basic/parser/useStrict.js
+++ b/nashorn/test/script/basic/parser/useStrict.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/util.js b/nashorn/test/script/basic/parser/util.js
index 6170018..ce417d0 100644
--- a/nashorn/test/script/basic/parser/util.js
+++ b/nashorn/test/script/basic/parser/util.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/varDecl.js b/nashorn/test/script/basic/parser/varDecl.js
index e505761..6f7b8ed 100644
--- a/nashorn/test/script/basic/parser/varDecl.js
+++ b/nashorn/test/script/basic/parser/varDecl.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/parser/withStat.js b/nashorn/test/script/basic/parser/withStat.js
index 3f94c7f..c1d7d30 100644
--- a/nashorn/test/script/basic/parser/withStat.js
+++ b/nashorn/test/script/basic/parser/withStat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/propchange.js b/nashorn/test/script/basic/propchange.js
index b317032..66d465e 100644
--- a/nashorn/test/script/basic/propchange.js
+++ b/nashorn/test/script/basic/propchange.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -26,7 +26,7 @@
  *
  * @test
  * @run
- */ 
+ */
 
 var obj = { x: 343 };
 
diff --git a/nashorn/test/script/basic/propertycheck.js b/nashorn/test/script/basic/propertycheck.js
index 8e35015..61352c1 100644
--- a/nashorn/test/script/basic/propertycheck.js
+++ b/nashorn/test/script/basic/propertycheck.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/prototype.js b/nashorn/test/script/basic/prototype.js
index e85d3d4..ede550e 100644
--- a/nashorn/test/script/basic/prototype.js
+++ b/nashorn/test/script/basic/prototype.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,12 +30,12 @@
 
 function check(url_) {
     try {
-	load(url_);
+    load(url_);
     } catch (e) {
-	if (e instanceof ReferenceError && e.toString().indexOf('navigator') != -1) {
-	    return;
-	}
-	throw e;
+    if (e instanceof ReferenceError && e.toString().indexOf('navigator') != -1) {
+        return;
+    }
+    throw e;
     }
 }
 
@@ -43,7 +43,7 @@
 try {
     try {
         check(file);
-    } catch (e) { 
+    } catch (e) {
         print(e);
     }
 } catch (e) {
diff --git a/nashorn/test/script/basic/pushpull.js b/nashorn/test/script/basic/pushpull.js
index 192ef9c..a57d362 100644
--- a/nashorn/test/script/basic/pushpull.js
+++ b/nashorn/test/script/basic/pushpull.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/ranges_disabled.js b/nashorn/test/script/basic/ranges_disabled.js
deleted file mode 100644
index 5bc8846..0000000
--- a/nashorn/test/script/basic/ranges_disabled.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @test 
- * @run 
- */
-
-load(__DIR__ + "ranges_payload.js");
diff --git a/nashorn/test/script/basic/ranges_disabled.js.EXPECTED b/nashorn/test/script/basic/ranges_disabled.js.EXPECTED
deleted file mode 100644
index 1a99c91..0000000
--- a/nashorn/test/script/basic/ranges_disabled.js.EXPECTED
+++ /dev/null
@@ -1,4 +0,0 @@
-289
-11094405
-4294967293
--4722
diff --git a/nashorn/test/script/basic/ranges_enabled.js b/nashorn/test/script/basic/ranges_enabled.js
deleted file mode 100644
index 45d9efb..0000000
--- a/nashorn/test/script/basic/ranges_enabled.js
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @test
- * @option --range-analysis
- * @run 
- */
-
-load(__DIR__ + "ranges_payload.js");
diff --git a/nashorn/test/script/basic/ranges_enabled.js.EXPECTED b/nashorn/test/script/basic/ranges_enabled.js.EXPECTED
deleted file mode 100644
index 1a99c91..0000000
--- a/nashorn/test/script/basic/ranges_enabled.js.EXPECTED
+++ /dev/null
@@ -1,4 +0,0 @@
-289
-11094405
-4294967293
--4722
diff --git a/nashorn/test/script/basic/ranges_payload.js b/nashorn/test/script/basic/ranges_payload.js
deleted file mode 100644
index f10a4a2..0000000
--- a/nashorn/test/script/basic/ranges_payload.js
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * 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.
- */
-
-/**
- * range analysis test. check that computation return values are correct
- * both with and without range analysis
- *
- * @subtest
- */
-
-function f(c) {
-    var v = c & 0xffff;
-    var w = v & 0xfff;
-    var x = v * w;
-    return x;
-}
-
-function g() {
-    var sum = 0;
-    for (var x = 0; x < 4711; x++) {
-	sum += x;
-    }
-    return sum;
-}
-
-function g2() {
-    var sum = 0;
-    //make sure we overflow
-    var displacement = 0x7ffffffe;
-    for (var x = displacement; x < (displacement + 2); x++) {
-	sum += x;
-    }
-    return sum;
-}
-
-//mostly provide code coverage for all the range operations    
-function h() {
-    var sum = 0;
-    sum += 4711;
-    sum &= 0xffff;
-    sum /= 2;
-    sum *= 2;
-    sum -= 4;
-    sum |= 2;
-    sum ^= 17;
-    sum = sum % 10000;
-    sum = -sum;
-    return sum
-}
-
-print(f(17));
-print(g());
-print(g2());
-print(h());
diff --git a/nashorn/test/script/basic/regex.js b/nashorn/test/script/basic/regex.js
index 49dd743..198c254 100644
--- a/nashorn/test/script/basic/regex.js
+++ b/nashorn/test/script/basic/regex.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,9 +25,9 @@
  * RegExp test.
  *
  * @test
- * @run 
+ * @run
  */
- 
+
 var regexp;
 
 regexp = new RegExp("dog");
diff --git a/nashorn/test/script/basic/regexp_flags.js b/nashorn/test/script/basic/regexp_flags.js
index 9ff7543..05cbc2a 100644
--- a/nashorn/test/script/basic/regexp_flags.js
+++ b/nashorn/test/script/basic/regexp_flags.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,7 +24,7 @@
 /**
  * NASHORN-154: Early error reporting.
  *
- * Errors in regular expression literals that are not implementation-defined 
+ * Errors in regular expression literals that are not implementation-defined
  * syntax extensions.
  *
  * @test
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/basic/relink_index_getter.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/basic/relink_index_getter.js
index db358d2..9cd0696 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/basic/relink_index_getter.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * relink_index_getter: after call site was linked for array, make sure it
+ * gets correctly relinked for boolean.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var x = [[], false]
+for(var i in x) { print(x[i][0]) }
diff --git a/nashorn/test/script/basic/relink_index_getter.js.EXPECTED b/nashorn/test/script/basic/relink_index_getter.js.EXPECTED
new file mode 100644
index 0000000..d4f80bf
--- /dev/null
+++ b/nashorn/test/script/basic/relink_index_getter.js.EXPECTED
@@ -0,0 +1,2 @@
+undefined
+undefined
diff --git a/nashorn/test/script/basic/run-octane.js b/nashorn/test/script/basic/run-octane.js
index 840f07b..0c666f2 100644
--- a/nashorn/test/script/basic/run-octane.js
+++ b/nashorn/test/script/basic/run-octane.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,31 +24,10 @@
 /**
  * @subtest
  */
+var payload = __DIR__ + "octane-payload.js";
+load(payload);
 
-var tests = [
-    {name:"box2d",         files:["box2d.js"],                         suite:"Box2DBenchmark"},
-    {name:"code-load",     files:["code-load.js"],                     suite:"CodeLoad"},
-    {name:"crypto",        files:["crypto.js"],                        suite:"Crypto"},
-    {name:"deltablue",     files:["deltablue.js"],                     suite:"DeltaBlue"},
-    {name:"earley-boyer",  files:["earley-boyer.js"],                  suite:"EarleyBoyer"},
-    {name:"gbemu",         files:["gbemu-part1.js", "gbemu-part2.js"], suite:"GameboyBenchmark"},
-    {name:"mandreel",      files:["mandreel.js"],                      suite:"MandreelBenchmark"},
-    {name:"navier-stokes", files:["navier-stokes.js"],                 suite:"NavierStokes"},
-    {name:"pdfjs",         files:["pdfjs.js"],                         suite:"PdfJS"},
-    {name:"raytrace",      files:["raytrace.js"],                      suite:"RayTrace"},
-    {name:"regexp",        files:["regexp.js"],                        suite:"RegExpSuite"},
-    {name:"richards",      files:["richards.js"],                      suite:"Richards"},
-    {name:"splay",         files:["splay.js"],                         suite:"Splay"},
-    {name:"typescript",    files:["typescript.js", "typescript-input.js", "typescript-compiler.js"], suite:"typescript"}
-    //zlib currently disabled - requires read
-    //    {name:"zlib",          files:["zlib.js", "zlib-data.js"], suite:"zlib"},
-];
-var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
-
-// TODO: why is this path hard coded when it's defined in project properties?
-var path = dir + "../external/octane/";
-
-var runtime = "";
+var runtime = undefined;
 var verbose = false;
 
 var numberOfIterations = 5;
@@ -64,145 +43,154 @@
 function load_bench(arg) {
 
     for (var idx = 0; idx < arg.files.length; idx++) {
-	var f = arg.files[idx];
-	var file = f.split('/');
-	var file_name = path + file[file.length - 1];
-    
-	var compile_and_return = should_compile_only(file_name);
-	if (compile_and_return) {
-	    if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
-		return true;
-	    }
-	}
-	
-	print_verbose(arg, "loading '" + arg.name + "' [" + f + "]...");
-	load(file_name); 
+    var f = arg.files[idx];
+    var file = f.split('/');
+    var file_name = path + file[file.length - 1];
+
+    var compile_and_return = should_compile_only(file_name);
+    if (compile_and_return) {
+        if (typeof compile_only === 'undefined') { //for a run, skip compile onlies, don't even compile them
+        return true;
+        }
+    }
+
+    print_verbose(arg, "loading '" + arg.name + "' [" + f + "]...");
+    load(file_name);
+    }
+
+    if (typeof arg.before !== 'undefined') {
+    arg.before();
     }
 
     if (compile_and_return) {
-	print_always(arg, "Compiled OK");
+    print_always(arg, "Compiled OK");
     }
     return !compile_and_return;
 
 }
 
+
 function run_one_benchmark(arg, iters) {
 
     if (!load_bench(arg)) {
-	return;
-    }    
-    
+    return;
+    }
+
     var success = true;
     var current_name;
-    
+
     if (iters == undefined) {
-	iters = numberOfIterations;
+    iters = numberOfIterations;
     } else {
-	numberOfIterations = iters;
+    numberOfIterations = iters;
     }
-    
+
     var benchmarks = eval(arg.suite + ".benchmarks");
     var min_score  = 1e9;
     var max_score  = 0;
     var mean_score = 0;
 
     try {
-	for (var x = 0; x < benchmarks.length ; x++) { 
-	    //do warmup run
-	    //reset random number generator needed as of octane 9 before each run
-	    BenchmarkSuite.ResetRNG();
-	    benchmarks[x].Setup();
-	}
-	BenchmarkSuite.ResetRNG();
-	print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds (" + runtime + ")");
-	
-	var scores = [];
-	
-	var min_time_ms = min_time * 1000;
-	var len = benchmarks.length;    
-	
-	for (var it = 0; it < iters + 1; it++) {
-	    //every iteration must take a minimum of 10 secs
-	    var ops = 0;
-	    var elapsed = 0;
-	    var start = new Date;
-	    do {
-		for (var i = 0; i < len; i++) {
-		    benchmarks[i].run();
-		    //important - no timing here like elapsed = new Date() - start, as in the 
-		    //original harness. This will make timing very non-deterministic.
-		    //NOTHING else must live in this loop
-		}	    
-		ops += len;
-		elapsed = new Date - start;
-	    } while (elapsed < min_time * 1000);
-	    
-	    var score = ops / elapsed * 1000 * 60;
-	    scores.push(score);
-	    var name = it == 0 ? "warmup" : "iteration " + it;   
-	    print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
-	}
+    for (var x = 0; x < benchmarks.length ; x++) {
+        //do warmup run
+        //reset random number generator needed as of octane 9 before each run
+        BenchmarkSuite.ResetRNG();
+        benchmarks[x].Setup();
+    }
+    BenchmarkSuite.ResetRNG();
+    print_verbose(arg, "running '" + arg.name + "' for " + iters + " iterations of no less than " + min_time + " seconds");
 
-	for (var x = 0; x < benchmarks.length ; x++) { 
-	    benchmarks[x].TearDown();
-	}
+    var scores = [];
 
-	for (var x = 1; x < iters + 1 ; x++) {
-	    mean_score += scores[x];
-	    min_score = Math.min(min_score, scores[x]);
-	    max_score = Math.max(max_score, scores[x]);
-	}
-	mean_score /= iters;    
+    var min_time_ms = min_time * 1000;
+    var len = benchmarks.length;
 
+    for (var it = 0; it < iters + 1; it++) {
+        //every iteration must take a minimum of 10 secs
+        var ops = 0;
+        var elapsed = 0;
+        var start = new Date;
+        do {
+        for (var i = 0; i < len; i++) {
+            benchmarks[i].run();
+            //important - no timing here like elapsed = new Date() - start, as in the
+            //original harness. This will make timing very non-deterministic.
+            //NOTHING else must live in this loop
+        }
+        ops += len;
+        elapsed = new Date - start;
+        } while (elapsed < min_time * 1000);
+
+        var score = ops / elapsed * 1000 * 60;
+        scores.push(score);
+        var name = it == 0 ? "warmup" : "iteration " + it;
+        print_verbose(arg, name + " finished " + score.toFixed(0) + " ops/minute");
+    }
+
+    for (var x = 0; x < benchmarks.length ; x++) {
+        benchmarks[x].TearDown();
+    }
+
+    for (var x = 1; x < iters + 1 ; x++) {
+        mean_score += scores[x];
+        min_score = Math.min(min_score, scores[x]);
+        max_score = Math.max(max_score, scores[x]);
+    }
+    mean_score /= iters;
     } catch (e) {
-	print_always("*** Aborted and setting score to zero. Reason: " + e);
-	mean_score = min_score = max_score = 0;
-	scores = [0];
+    print_always(arg, "*** Aborted and setting score to zero. Reason: " + e);
+    if (e instanceof java.lang.Throwable) {
+        e.printStackTrace();
+    }
+    mean_score = min_score = max_score = 0;
+    scores = [0];
     }
 
     var res = mean_score.toFixed(0);
     if (verbose) {
-	res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
+    res += " ops/minute (" + min_score.toFixed(0) + "-" + max_score.toFixed(0) + "), warmup=" + scores[0].toFixed(0);
     }
     print_always(arg, res);
 }
 
+function runtime_string() {
+    return runtime == undefined ? "" : ("[" + runtime + "] ");
+}
+
 function print_always(arg, x) {
-    print("[" + arg.name + "] " + x);
+    print(runtime_string() + "[" + arg.name + "] " + x);
 }
 
 function print_verbose(arg, x) {
     if (verbose) {
-	print_always(arg, x)
+    print_always(arg, x)
     }
 }
 
 function run_suite(tests, iters) {
     for (var idx = 0; idx < tests.length; idx++) {
-	run_one_benchmark(tests[idx], iters);
+    run_one_benchmark(tests[idx], iters);
     }
 }
 
-runtime = "command line";
-
 var args = [];
 
 if (typeof $ARGS !== 'undefined') {
     args = $ARGS;
 } else if (typeof arguments !== 'undefined' && arguments.length != 0) {
     args = arguments;
-}  
+}
 
 var new_args = [];
 for (i in args) {
     if (args[i].toString().indexOf(' ') != -1) {
-	args[i] = args[i].replace(/\/$/, '');
-	var s = args[i].split(' ');
-	for (j in s) {
-	    new_args.push(s[j]);
-	}
+    args[i] = args[i].replace(/\/$/, '');
+    var s = args[i].split(' ');
+    for (j in s) {
+        new_args.push(s[j]);
+    }
     } else {
-	new_args.push(args[i]);
+    new_args.push(args[i]);
     }
 }
 
@@ -214,50 +202,76 @@
 var iters = undefined;
 var min_time = 5;
 
-for (var i = 0; i < args.length; i++) { 
+for (var i = 0; i < args.length; i++) {
     arg = args[i];
     if (arg == "--iterations") {
-	iters = +args[++i];
+    iters = +args[++i];
+    if (isNaN(iters)) {
+        throw "'--iterations' must be followed by integer";
+    }
     } else if (arg == "--runtime") {
-	runtime = args[++i];
+    runtime = args[++i];
     } else if (arg == "--verbose") {
-	verbose = true;
+    verbose = true;
     } else if (arg == "--min-time") {
-	min_time = +args[++i];
+    min_time = +args[++i];
+    if (isNaN(iters)) {
+        throw "'--min-time' must be followed by integer";
+    }
     } else if (arg == "") {
-	continue; //skip
+    continue; //skip
     } else {
-	var found = false;
-	for (j in tests) {
-	    if (tests[j].name === arg) {
-		tests_found.push(tests[j]);
-		found = true;
-		break;
-	    }
-	}
-	if (!found) {
-	    var str = "unknown test name: '" + arg + "' -- valid names are: ";
-	    for (j in tests) {
-		if (j != 0) {
-		    str += ", ";
-		}
-		str += "'" + tests[j].name + "'";
-	    }
-	    throw str;
-	}
+    var found = false;
+    for (j in tests) {
+        if (tests[j].name === arg) {
+        tests_found.push(tests[j]);
+        found = true;
+        break;
+        }
+    }
+    if (!found) {
+        var str = "unknown test name: '" + arg + "' -- valid names are: ";
+        for (j in tests) {
+        if (j != 0) {
+            str += ", ";
+        }
+        str += "'" + tests[j].name + "'";
+        }
+        throw str;
+    }
     }
 }
 
-if (tests_found.length == 0) {    
+if (tests_found.length == 0) {
     for (i in tests) {
-	tests_found.push(tests[i]);
+    tests_found.push(tests[i]);
     }
-} 
+}
 
-tests_found.sort();
+// returns false for rhino, v8 and all other javascript runtimes, true for Nashorn
+function is_this_nashorn() {
+    return typeof Error.dumpStack == 'function'
+}
+
+if (is_this_nashorn()) {
+    try {
+    read = readFully;
+    } catch (e) {
+    print("ABORTING: Cannot find 'readFully'. You must have scripting enabled to use this test harness. (-scripting)");
+    throw e;
+    }
+}
+
+// run tests in alphabetical order by name
+tests_found.sort(function(a, b) {
+    if (a.name < b.name) {
+    return -1;
+    } else if (a.name > b.name) {
+    return 1;
+    } else {
+    return 0;
+    }
+});
 
 load(path + 'base.js');
 run_suite(tests_found, iters);
-
-
-
diff --git a/nashorn/test/script/basic/runsunspider.js b/nashorn/test/script/basic/runsunspider.js
index 84ce915..738aea0 100644
--- a/nashorn/test/script/basic/runsunspider.js
+++ b/nashorn/test/script/basic/runsunspider.js
@@ -24,7 +24,9 @@
 /**
  * runsunspider : runs the sunspider tests and checks for compliance
  *
- * @subtest
+ * @test
+ * @option -timezone=PST
+ * @runif external.sunspider
  */
 
 /**
@@ -37,32 +39,32 @@
     }
 }
 
+function pprint(x) {
+    if (verbose_run) {
+    print(x);
+    }
+}
+
 var runs = 0;
-var iterations__ = 1;
 var total_time = 0;
 
 function runbench(name) {
     var filename = name.split("/").pop();
-    if (verbose_run) {
-        print("Running " + filename);
-    }
+    pprint("Running (warmup/sanity) " + filename);
 
     var start = new Date;
-    for (var i = 0; i < iterations__; i++) {
-        load(name);
-    }
+    load(name);
+
     var stop = new Date - start;
     total_time += stop;
 
-    if (verbose_run) {
-        print(filename + " done in " + stop + " ms");
-    }
+    pprint(filename + " done in " + stop + " ms");
     runs++;
 }
 
-var m_w = 4711;
-var m_z = 17;
-var MAXINT = 0x7fffffff;
+var m_w;
+var m_z;
+var MAXINT;
 
 //produce deterministic random numbers for test suite
 function pseudorandom() {
@@ -71,25 +73,133 @@
     return (Math.abs((m_z << 16) + m_w) & MAXINT) / MAXINT;
 }
 
-function runsuite(tests) {
-    var changed = false;
-
-    var oldRandom = Math.random;
+function initrandom() {
+    m_w = 4711;
+    m_z = 17;
+    MAXINT = 0x7fffffff;
     Math.random = pseudorandom;
+}
+
+var rtimes = 0;
+var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
+var single;
+var verbose_run = false;
+var runall = false;
+
+var args = [];
+if (typeof $ARGS !== 'undefined') {
+    args = $ARGS;
+} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
+    args = arguments;
+}
+
+for (var i = 0; i < args.length; i++) {
+    if (args[i] === '--verbose') {
+        verbose_run = true;
+    } else if (args[i] === '--times') {
+    i++;
+    rtimes = +args[i];
+    } else if (args[i] === '--single') {
+    i++;
+    single = args[i];
+    } else if (args[i] === '--runall') {
+    i++;
+    runall = true;
+    }
+}
+
+function runsuite(tests) {
+    var changed   = false;
+    var res       = [];
+    var oldRandom = Math.random;
 
     try {
-        for (var n = 0; n < tests.length; n++) {
-            path = dir + '../external/sunspider/tests/sunspider-1.0/' + tests[n].name
-            runbench(path);
-            if (typeof tests[n].actual !== 'undefined') {
-                assertEq(tests[n].actual(), tests[n].expected());
+    for (var n = 0; n < tests.length; n++) {
+            try {
+                path = dir + '../external/sunspider/tests/sunspider-1.0.2/' + tests[n].name
+
+                initrandom();
+
+                var dd = new Date;
+
+                runbench(path);
+                if (typeof tests[n].actual !== 'undefined') {
+                    assertEq(tests[n].actual(), tests[n].expected());
+                }
+
+                var times = 0;
+                if (typeof tests[n].rerun !== 'undefined' && tests[n].times > 0) {
+                    pprint("rerunning " + tests[n].name + " " + tests[n].times + " times...");
+                    var to = tests[n].times;
+
+                    var elemsPerPercent = to / 100;
+                    var po = 0|(to / 10);
+
+            pprint("Doing warmup.");
+                    for (times = 0; times < to; times++) {
+                        initrandom();
+                        tests[n].rerun();
+                    }
+
+            pprint("Doing hot runs.");
+                    for (times = 0; times < to; times++) {
+                        initrandom();
+                        tests[n].rerun();
+                        if ((times % (po|0)) == 0) {
+                            pprint("\t" + times/to * 100 + "%");
+                        }
+                    }
+                }
+
+                var t = Math.round(((new Date - dd) / (times == 0 ? 1 : times)) * 100 / 100);
+                pprint("time per iteration: " + t + " ms");
+                if (typeof tests[n].actual !== 'undefined') {
+                    assertEq(tests[n].actual(), tests[n].expected());
+                }
+                res.push(t);
+
+                pprint("");
+
+                changed = true;
+            } catch(e) {
+                if (runall) {
+                    print("FAIL!");
+                } else {
+                    throw e;
+                }
             }
-            changed = true;
         }
+    } catch (e) {
+    print("FAIL!");
+    throw e;
         // no scripting or something, silently fail
     } finally {
-    }
     Math.random = oldRandom;
+    }
+
+    for (var n = 0; n < tests.length; n++) {
+
+    var time = "" + res[n];
+    while (time.length < 6) {
+        time = " " + time;
+    }
+    time += " ms";
+    if (res[n] == -1) {
+        time = "<couldn't be rerun>";
+    }
+    var str = tests[n].name;
+    for (var spaces = str.length; spaces < 32; spaces++) {
+        str += " ";
+    }
+    str += " ";
+    str += time;
+
+    if (tests[n].times > 0) {
+        str += " [";
+        str += tests[n].times + " reruns]";
+    }
+    pprint(str);
+    }
 
     return changed;
 }
@@ -106,20 +216,47 @@
 }
 
 var tests = [
+
+    { name: 'regexp-dna.js',
+      actual: function() {
+      return dnaOutputString + dnaInput;
+      },
+      expected: function() {
+      return expectedDNAOutputString + expectedDNAInput;
+      },
+    },
+
     { name: 'string-base64.js',
       actual: function() {
           return hash(str);
       },
       expected: function() {
           return 1544571068;
-      }
-    },
-    { name: 'string-validate-input.js',
-      actual: function() {
-          return hash(endResult);
       },
-      expected: function() {
-          return 2016572373;
+      times: rtimes,
+      rerun: function() {
+      toBinaryTable = [
+          -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+          -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,-1,
+          -1,-1,-1,-1, -1,-1,-1,-1, -1,-1,-1,62, -1,-1,-1,63,
+              52,53,54,55, 56,57,58,59, 60,61,-1,-1, -1, 0,-1,-1,
+          -1, 0, 1, 2,  3, 4, 5, 6,  7, 8, 9,10, 11,12,13,14,
+               15,16,17,18, 19,20,21,22, 23,24,25,-1, -1,-1,-1,-1,
+          -1,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+              41,42,43,44, 45,46,47,48, 49,50,51,-1, -1,-1,-1,-1
+      ];
+      var str = "";
+      for (var i = 0; i < 8192; i++)
+              str += String.fromCharCode((25 * Math.random()) + 97);
+
+      for (var i = 8192; i <= 16384; i *= 2) {
+          var base64;
+          base64 = toBase64(str);
+          var encoded = base64ToString(base64);
+
+          str += str;
+      }
+      toBinaryTable = null;
       }
     },
     { name: 'date-format-xparb.js',
@@ -128,7 +265,29 @@
       },
       expected: function() {
           return "2017-09-05Tuesday, September 05, 2017 8:43:48 AM";
+      },
+      times: rtimes,
+      rerun: function() {
+      date = new Date("1/1/2007 1:11:11");
+      for (i = 0; i < 4000; ++i) {
+          var shortFormat = date.dateFormat("Y-m-d");
+          var longFormat = date.dateFormat("l, F d, Y g:i:s A");
+          date.setTime(date.getTime() + 84266956);
       }
+      }
+
+    },
+    { name: 'string-validate-input.js',
+      actual: function() {
+          return hash(endResult);
+      },
+      expected: function() {
+          return 726038055;
+      },
+      times: rtimes,
+      rerun: function() {
+      doTest();
+      },
     },
     { name: '3d-morph.js',
       actual: function() {
@@ -137,6 +296,20 @@
       },
       expected: function() {
           return true;
+      },
+      times: rtimes,
+      rerun: function() {
+      a = Array()
+      for (var i=0; i < nx*nz*3; ++i)
+          a[i] = 0
+      for (var i = 0; i < loops; ++i) {
+          morph(a, i/loops)
+      }
+      testOutput = 0;
+      for (var i = 0; i < nx; i++)
+          testOutput += a[3*(i*nx+i)+1];
+      a = null;
+
       }
     },
     { name: 'crypto-aes.js',
@@ -145,6 +318,12 @@
       },
       expected: function() {
           return decryptedText;
+      },
+      times: rtimes,
+      rerun: function() {
+      cipherText = AESEncryptCtr(plainText, password, 256);
+      decryptedText = AESDecryptCtr(cipherText, password, 256);
+
       }
     },
     { name: 'crypto-md5.js',
@@ -153,32 +332,56 @@
       },
       expected: function() {
           return "a831e91e0f70eddcb70dc61c6f82f6cd";
+      },
+      times: rtimes,
+      rerun: function() {
+      md5Output = hex_md5(plainText);
       }
     },
+
     { name: 'crypto-sha1.js',
       actual: function() {
           return sha1Output;
       },
       expected: function() {
           return "2524d264def74cce2498bf112bedf00e6c0b796d";
+      },
+      times: rtimes,
+      rerun: function() {
+      sha1Output = hex_sha1(plainText);
       }
     },
+
     { name: 'bitops-bitwise-and.js',
       actual: function() {
           return result;
       },
       expected: function() {
           return 0;
+      },
+      times: rtimes,
+      rerun: function() {
+      bitwiseAndValue = 4294967296;
+      for (var i = 0; i < 600000; i++) {
+          bitwiseAndValue = bitwiseAndValue & i;
+      }
+      result = bitwiseAndValue;
       }
     },
+
     { name: 'bitops-bits-in-byte.js',
       actual: function() {
           return result;
       },
       expected: function() {
           return 358400;
+      },
+      times: rtimes,
+      rerun: function() {
+      result = TimeFunc(bitsinbyte);
       }
     },
+
     { name: 'bitops-nsieve-bits.js',
       actual: function() {
           var ret = 0;
@@ -190,40 +393,101 @@
       },
       expected: function() {
           return -1286749539853;
+      },
+      times: rtimes,
+      rerun: function() {
+      result = sieve();
       }
     },
+
     { name: 'bitops-3bit-bits-in-byte.js',
       actual: function() {
           return sum;
       },
       expected: function() {
           return 512000;
+      },
+      times: rtimes,
+      rerun: function() {
+      sum = TimeFunc(fast3bitlookup);
       }
     },
+
     { name: 'access-nbody.js',
       actual: function() {
           return ret;
       },
       expected: function() {
             return -1.3524862408537381;
+      },
+      times: rtimes,
+      rerun: function() {
+      var ret = 0;
+      for (var n = 3; n <= 24; n *= 2) {
+          (function(){
+          var bodies = new NBodySystem( Array(
+              Sun(),Jupiter(),Saturn(),Uranus(),Neptune()
+          ));
+          var max = n * 100;
+
+          ret += bodies.energy();
+          for (var i=0; i<max; i++){
+              bodies.advance(0.01);
+          }
+          ret += bodies.energy();
+          })();
+      }
       }
     },
+
     { name: 'access-binary-trees.js',
       actual: function() {
           return ret;
       },
       expected: function() {
           return -4;
+      },
+      times: rtimes,
+      rerun: function() {
+      ret = 0;
+
+      for (var n = 4; n <= 7; n += 1) {
+          var minDepth = 4;
+          var maxDepth = Math.max(minDepth + 2, n);
+          var stretchDepth = maxDepth + 1;
+
+          var check = bottomUpTree(0,stretchDepth).itemCheck();
+
+          var longLivedTree = bottomUpTree(0,maxDepth);
+          for (var depth=minDepth; depth<=maxDepth; depth+=2){
+          var iterations = 1 << (maxDepth - depth + minDepth);
+
+          check = 0;
+          for (var i=1; i<=iterations; i++){
+              check += bottomUpTree(i,depth).itemCheck();
+              check += bottomUpTree(-i,depth).itemCheck();
+          }
+          }
+
+          ret += longLivedTree.itemCheck();
+      }
       }
     },
+
     { name: 'access-fannkuch.js',
       actual: function() {
           return ret;
       },
       expected: function() {
           return 22;
+      },
+      times: rtimes,
+      rerun: function() {
+      n = 8;
+      ret = fannkuch(n);
       }
     },
+
     { name: 'math-spectral-norm.js',
       actual: function() {
           var ret = '';
@@ -234,32 +498,43 @@
       },
       expected: function() {
           return "1.2657786149754053,1.2727355112619148,1.273989979775574,1.274190125290389,";
+      },
+      times: rtimes,
+      rerun: function() {
+      total = 0;
+      for (var i = 6; i <= 48; i *= 2) {
+          total += spectralnorm(i);
+      }
       }
     },
+
     { name: '3d-raytrace.js',
       actual: function() {
           return hash(testOutput);
       },
       expected: function() {
           return 230692593;
-      }
-    },
-    { name: 'regexp-dna.js',
-      actual: function() {
-          return dnaOutputString;
       },
-      expected: function() {
-          return "agggtaaa|tttaccct 0\n[cgt]gggtaaa|tttaccc[acg] 9\na[act]ggtaaa|tttacc[agt]t 27\nag[act]gtaaa|tttac[agt]ct 24\nagg[act]taaa|ttta[agt]cct 30\naggg[acg]aaa|ttt[cgt]ccct 9\nagggt[cgt]aa|tt[acg]accct 12\nagggta[cgt]a|t[acg]taccct 9\nagggtaa[cgt]|[acg]ttaccct 15\n";
+      times: rtimes,
+      rerun: function() {
+      testOutput = arrayToCanvasCommands(raytraceScene());
       }
     },
+
     { name: 'math-cordic.js',
       actual: function() {
           return total;
       },
       expected: function() {
           return 10362.570468755888;
+      },
+      times: rtimes,
+      rerun: function() {
+      total = 0;
+      cordic(25000);
       }
     },
+
     { name: 'controlflow-recursive.js',
       actual: function() {
           var ret = 0;
@@ -272,16 +547,36 @@
       },
       expected: function() {
           return 57775;
+      },
+      times: rtimes,
+      rerun: function() {
+      result = 0;
+      for (var i = 3; i <= 5; i++) {
+          result += ack(3,i);
+          result += fib(17.0+i);
+          result += tak(3*i+3,2*i+2,i+1);
+      }
       }
     },
+
     { name: 'date-format-tofte.js',
       actual: function() {
           return shortFormat + longFormat;
       },
       expected: function() {
           return "2008-05-01Thursday, May 01, 2008 6:31:22 PM";
+      },
+      times: rtimes,
+      rerun: function() {
+      date = new Date("1/1/2007 1:11:11");
+      for (i = 0; i < 500; ++i) {
+          var shortFormat = date.formatDate("Y-m-d");
+          var longFormat = date.formatDate("l, F d, Y g:i:s A");
+          date.setTime(date.getTime() + 84266956);
+      }
       }
     },
+
     { name: 'string-tagcloud.js',
       actual: function() {
           // The result string embeds floating-point numbers, which can vary a bit on different platforms,
@@ -291,8 +586,71 @@
       },
       expected: function() {
           return 295906;
+      },
+      times: rtimes,
+      rerun: function() {
+      tagInfo = tagInfoJSON.parseJSON(function(a, b) { if (a == "popularity") { return Math.log(b) / log2; } else {return b; } });
+      tagcloud = makeTagCloud(tagInfo);
       }
     },
+
+    { name: 'math-partial-sums.js',
+      actual: function() {
+      return total;
+      },
+      expected: function() {
+      return 60.08994194659945;
+      },
+      times: rtimes,
+      rerun: function() {
+      total = 0;
+      for (var i = 1024; i <= 16384; i *= 2) {
+          total += partial(i);
+      }
+      }
+    },
+
+    { name: 'access-nsieve.js',
+      actual: function() {
+      return result;
+      },
+      expected: function() {
+      return 14302;
+      },
+      times: rtimes,
+      rerun: function() {
+      result = sieve();
+      }
+    },
+
+    { name: '3d-cube.js',
+      times: rtimes,
+      rerun: function() {
+      Q = new Array();
+      MTrans = new Array();  // transformation matrix
+      MQube = new Array();  // position information of qube
+      I = new Array();      // entity matrix
+      Origin = new Object();
+      Testing = new Object();
+      for ( var i = 20; i <= 160; i *= 2 ) {
+          Init(i);
+      }
+      }
+    },
+
+    //TODO no easy way to sanity check result
+    { name: 'string-fasta.js',
+      times: rtimes,
+      rerun: function() {
+      ret = 0;
+      count = 7;
+      fastaRepeat(2*count*100000, ALU);
+      fastaRandom(3*count*1000, IUB);
+      fastaRandom(5*count*1000, HomoSap);
+      }
+    },
+
+    //TODO no easy way to sanity check result
     { name: 'string-unpack-code.js',
       actual: function() {
           return decompressedMochiKit.length == 106415 &&
@@ -301,43 +659,32 @@
               decompressedMochiKit[82556] == '>';
       },
       expected: function() {
-          return true;
-      }
+      return true;
+      },
     },
-    //TODO no easy way to sanity check result
-    { name: 'string-fasta.js' },
-    //TODO no easy way to sanity check result
-    { name: 'math-partial-sums.js' },
-    //TODO no easy way to sanity check result
-    { name: 'access-nsieve.js' },
-    //TODO no easy way to sanity check result
-    { name: '3d-cube.js' },
+
 ];
 
-// handle the case this script may be run by a JS engine that doesn't
-// support __DIR__ global variable.
-var dir = (typeof(__DIR__) == 'undefined') ? "test/script/basic/" : __DIR__;
-
-var verbose_run = false;
-
-var args = [];
-if (typeof $ARGS !== 'undefined') {
-    args = $ARGS;
-} else if (typeof arguments !== 'undefined' && arguments.length != 0) {
-    args = arguments;
-}
-
-for (i in args) {
-    if (args[i] === '--verbose') {
-        verbose_run = true;
+tests.sort(function(a,b) { return a.name.localeCompare(b.name); });
+if (typeof single !== 'undefined') {
+    for (i in tests) {
+    if (tests[i].name === single) {
+        singleTest = tests[i];
+        tests = [singleTest];
         break;
     }
+    }
+    if (tests.length != 1) {
+    throw "unknown single test '" + single + "'";
+    }
 }
 
+
+// handle the case this script may be run by a JS engine that doesn't
+// support __DIR__ global variable.
+
 runsuite(tests);
 
-if (verbose_run) {
-    print('\n' + runs + "/" + tests.length + " tests were successfully run in " + total_time + " ms ");
-}
+pprint('\n' + runs + "/" + tests.length + " tests were successfully run in " + total_time + " ms ");
 
 print("Sunspider finished!");
diff --git a/nashorn/test/script/basic/runsunspider-lazy.js.EXPECTED b/nashorn/test/script/basic/runsunspider.js.EXPECTED
similarity index 100%
rename from nashorn/test/script/basic/runsunspider-lazy.js.EXPECTED
rename to nashorn/test/script/basic/runsunspider.js.EXPECTED
diff --git a/nashorn/test/script/basic/samfunc.js b/nashorn/test/script/basic/samfunc.js
index 7751bee0..8cd6aed 100644
--- a/nashorn/test/script/basic/samfunc.js
+++ b/nashorn/test/script/basic/samfunc.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -34,7 +34,7 @@
 
 var t1 = new java.lang.Thread(function() {
     print("thread t1.run");
-}); 
+});
 
 // make sure that we can pass interface implementation as well.
 var t2 = new java.lang.Thread(new java.lang.Runnable() {
diff --git a/nashorn/test/script/basic/scripting.js b/nashorn/test/script/basic/scripting.js
index 8809636..056afc7 100644
--- a/nashorn/test/script/basic/scripting.js
+++ b/nashorn/test/script/basic/scripting.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/scripting.js.EXPECTED b/nashorn/test/script/basic/scripting.js.EXPECTED
index 4f06475..3b1b3b6 100644
--- a/nashorn/test/script/basic/scripting.js.EXPECTED
+++ b/nashorn/test/script/basic/scripting.js.EXPECTED
@@ -22,21 +22,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/sealfreeze.js b/nashorn/test/script/basic/sealfreeze.js
index 8b932f8..742ac8c 100644
--- a/nashorn/test/script/basic/sealfreeze.js
+++ b/nashorn/test/script/basic/sealfreeze.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/setlength.js b/nashorn/test/script/basic/setlength.js
index 45f54e5..6a79192 100644
--- a/nashorn/test/script/basic/setlength.js
+++ b/nashorn/test/script/basic/setlength.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -27,7 +27,7 @@
  * @test
  * @run
  */
- 
+
 var a = ["a", "b", "c", "d", "e"];
 print(a.length);
 print(a);
diff --git a/nashorn/test/script/basic/splitter.js b/nashorn/test/script/basic/splitter.js
index 62f5ddf..5637b27 100644
--- a/nashorn/test/script/basic/splitter.js
+++ b/nashorn/test/script/basic/splitter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/stdin.js b/nashorn/test/script/basic/stdin.js
index a3a9332..1e507e4 100644
--- a/nashorn/test/script/basic/stdin.js
+++ b/nashorn/test/script/basic/stdin.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/strings.js b/nashorn/test/script/basic/strings.js
index 87aff31..62b9dba 100644
--- a/nashorn/test/script/basic/strings.js
+++ b/nashorn/test/script/basic/strings.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/throws.js b/nashorn/test/script/basic/throws.js
index 30647e4..4e673a4 100644
--- a/nashorn/test/script/basic/throws.js
+++ b/nashorn/test/script/basic/throws.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/tosource.js b/nashorn/test/script/basic/tosource.js
index ad6cfcc..43e7ab7 100644
--- a/nashorn/test/script/basic/tosource.js
+++ b/nashorn/test/script/basic/tosource.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/tostring.js b/nashorn/test/script/basic/tostring.js
index 80e6b0f..56f5294 100644
--- a/nashorn/test/script/basic/tostring.js
+++ b/nashorn/test/script/basic/tostring.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/try.js b/nashorn/test/script/basic/try.js
index 07ec43c..d3d6818 100644
--- a/nashorn/test/script/basic/try.js
+++ b/nashorn/test/script/basic/try.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,12 +25,12 @@
  * Try throw test.
  *
  * @test
- * @run 
+ * @run
  */
 
 function A() {
     print("before try");
-    
+
     try {
         print("before throw");
         throw "a string";
@@ -41,7 +41,7 @@
     } finally {
         print("finally");
     }
-    
+
     return "incorrect";
 }
 
diff --git a/nashorn/test/script/basic/try2.js b/nashorn/test/script/basic/try2.js
index 8a59c89..9e50718 100644
--- a/nashorn/test/script/basic/try2.js
+++ b/nashorn/test/script/basic/try2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,21 +25,21 @@
  * Try throw test - nest finally
  *
  * @test
- * @run 
+ * @run
  */
 
 function f() {
     print("a");
     try {
-	print("b");
+    print("b");
     } finally {
-	print("c");
-	try {
-	    print("d");
-	} finally {
-	    print("e");
-	}
-	print("f");
+    print("c");
+    try {
+        print("d");
+    } finally {
+        print("e");
+    }
+    print("f");
     }
     print("g");
 }
diff --git a/nashorn/test/script/basic/trybreakcont.js b/nashorn/test/script/basic/trybreakcont.js
index 94bfdf1..683f26b 100644
--- a/nashorn/test/script/basic/trybreakcont.js
+++ b/nashorn/test/script/basic/trybreakcont.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/trycatch.js b/nashorn/test/script/basic/trycatch.js
index f5707e4..632c320 100644
--- a/nashorn/test/script/basic/trycatch.js
+++ b/nashorn/test/script/basic/trycatch.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * try catch test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var actual = '';
@@ -35,13 +35,13 @@
 
 function test() {
     expect = true;
-    
+
     try {
         actual = true;
     }
     catch(ex) {
         actual = ex + '';
     }
-    
+
     print(actual);
 }
diff --git a/nashorn/test/script/basic/trycatchfor.js b/nashorn/test/script/basic/trycatchfor.js
index a8c2d09..953f05d 100644
--- a/nashorn/test/script/basic/trycatchfor.js
+++ b/nashorn/test/script/basic/trycatchfor.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
 
 try {
     for(var i =0; i < 10; i++) {
-    } 
+    }
 } catch (e) {
 }
 
diff --git a/nashorn/test/script/basic/tryfinallyreturn.js b/nashorn/test/script/basic/tryfinallyreturn.js
index bc79146..ed7fe62 100644
--- a/nashorn/test/script/basic/tryfinallyreturn.js
+++ b/nashorn/test/script/basic/tryfinallyreturn.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/tryforbreak.js b/nashorn/test/script/basic/tryforbreak.js
index 04d8de3..4a62581 100644
--- a/nashorn/test/script/basic/tryforbreak.js
+++ b/nashorn/test/script/basic/tryforbreak.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -31,8 +31,8 @@
 try {
     for(i = 0; i < 3; i++) {
         break;
-    };	
-} catch (e) {	
+    };
+} catch (e) {
 }
 
 print("done");
diff --git a/nashorn/test/script/basic/typechange.js b/nashorn/test/script/basic/typechange.js
index ff416f8..c930e8a 100644
--- a/nashorn/test/script/basic/typechange.js
+++ b/nashorn/test/script/basic/typechange.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * This test crashes with VerifyError (bad type on stack).
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/typecoerce.js b/nashorn/test/script/basic/typecoerce.js
index ba95e6a..3e3bc6d 100644
--- a/nashorn/test/script/basic/typecoerce.js
+++ b/nashorn/test/script/basic/typecoerce.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,9 +24,9 @@
 /**
  * There was a bug in the old Lower that didn't fully propagate type information
  * by way of assignment. 'q' in the example below would have finished a double
- * even though it can get an object value through the assignment 'q = l' 
- * 
- * Furthermore, this caused type coercion to be done at q = l, and not a q = q * 2, 
+ * even though it can get an object value through the assignment 'q = l'
+ *
+ * Furthermore, this caused type coercion to be done at q = l, and not a q = q * 2,
  * which is a bug. This test ensures it happens in the correct order
  *
  * @test
@@ -42,11 +42,11 @@
     var l = 1.2; //number
     var q = 2.3; //number
     for (var i = 0; i < 2; i++) {
-	q = l; // q = toNumber(l), no coercion here
-	print("assignment done");
-	q = q * 2; // q = q * 2, coercion here
-	print("multiplication done");
-	l = createObject();
+    q = l; // q = toNumber(l), no coercion here
+    print("assignment done");
+    q = q * 2; // q = q * 2, coercion here
+    print("multiplication done");
+    l = createObject();
     }
 }
 
diff --git a/nashorn/test/script/basic/typedarrays.js b/nashorn/test/script/basic/typedarrays.js
index 0854bea..b15f5dd1 100644
--- a/nashorn/test/script/basic/typedarrays.js
+++ b/nashorn/test/script/basic/typedarrays.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,20 +25,20 @@
  * typedarray test.
  *
  * @test
- * @run 
+ * @run
  */
 
 
 var typeDefinitions = [
-Int8Array, 
-Uint8Array, 
-Uint8ClampedArray, 
-Int16Array, 
-Uint16Array, 
-Int32Array, 
-Uint32Array, 
-Float32Array, 
-Float64Array, 
+Int8Array,
+Uint8Array,
+Uint8ClampedArray,
+Int16Array,
+Uint16Array,
+Int32Array,
+Uint32Array,
+Float32Array,
+Float64Array,
 ];
 
 var mem1 = new ArrayBuffer(1024);
@@ -55,17 +55,17 @@
 typeDefinitions.forEach(function(arrayDef) {
     var p = arrayDef.prototype;
     var sub = [];
-    sub.push(new arrayDef(mem1, arrayDef.BYTES_PER_ELEMENT, 3));   
+    sub.push(new arrayDef(mem1, arrayDef.BYTES_PER_ELEMENT, 3));
     sub.push(new arrayDef(size));
     sub.push(new arrayDef(arr));
     //push the instances, they will be reused to do instance based construction
     partial.push({
-        instances:sub, 
+        instances:sub,
         type:arrayDef
     });
-    
+
     all.concat(all, sub);
-    
+
 });
 
 partial.forEach(function(inst) {
@@ -83,11 +83,11 @@
     var arr = Object.getOwnPropertyNames(instance);
     arr.forEach(function(p) {
         var val = instance[p];
-        if(!isNaN(p)){
+        if(!isNaN(p)) {
             val[p] = 99;
-        }       
+        }
     });
-        
+
     instance.set(instance, 0);
     instance.set(instance);
     instance.set(arr2);
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/basic/typedarrays2.js
similarity index 70%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/basic/typedarrays2.js
index c9182ef..dfbecb0 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/basic/typedarrays2.js
@@ -1,35 +1,56 @@
 /*
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * Typed array test 2
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var b = new ArrayBuffer(8);
+
+var v1 = new Int32Array(b);
+var v2 = new Uint8Array(b, 2);
+var v3 = new Int16Array(b, 2, 2);
+
+v3[1000] = 17;
+v3.apa = 17;
+print(v3[1000]);
+var arr = [1,2,3];
+arr.gegg = 17;
+print(arr.gegg);
+var v4 = new Int32Array(arr);
+print(v4.gegg);
+
+v2[0] = 0xff;
+v2[1] = 0xff;
+if (v2[1] != 0xff) {
+    print("Error 1: " + v2[1]);
+}
+if (v3[0] != -1) {
+    print("Error 2: " + v3[0]);
+}
+
+print("Done");
+
diff --git a/nashorn/test/script/basic/typedarrays2.js.EXPECTED b/nashorn/test/script/basic/typedarrays2.js.EXPECTED
new file mode 100644
index 0000000..de377cc
--- /dev/null
+++ b/nashorn/test/script/basic/typedarrays2.js.EXPECTED
@@ -0,0 +1,4 @@
+undefined
+17
+undefined
+Done
diff --git a/nashorn/test/script/basic/typeof.js b/nashorn/test/script/basic/typeof.js
index 15c9f81..4e0205f 100644
--- a/nashorn/test/script/basic/typeof.js
+++ b/nashorn/test/script/basic/typeof.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Typeof test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var x = { a: 1, b: "string", c: [1, 2, 3], d: function() {} };
diff --git a/nashorn/test/script/basic/typeof2.js b/nashorn/test/script/basic/typeof2.js
index 248fabf..80513e9 100644
--- a/nashorn/test/script/basic/typeof2.js
+++ b/nashorn/test/script/basic/typeof2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/undefined.js b/nashorn/test/script/basic/undefined.js
index b949eec..cd0e885 100644
--- a/nashorn/test/script/basic/undefined.js
+++ b/nashorn/test/script/basic/undefined.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/underscore.js b/nashorn/test/script/basic/underscore.js
index 064e525..f9b2a7a 100644
--- a/nashorn/test/script/basic/underscore.js
+++ b/nashorn/test/script/basic/underscore.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * NASHORN-466 : corpus parse test for underscore
- * 
+ *
  * @test
  * @runif external.underscore
  */
diff --git a/nashorn/test/script/basic/varargs.js b/nashorn/test/script/basic/varargs.js
index 0284413..061325d 100644
--- a/nashorn/test/script/basic/varargs.js
+++ b/nashorn/test/script/basic/varargs.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * Var args test.
  *
  * @test
- * @run 
+ * @run
  */
 function varFunc(a, b, c) {
     print(a, b, c);
diff --git a/nashorn/test/script/basic/void.js b/nashorn/test/script/basic/void.js
index 957f954..8abc146 100644
--- a/nashorn/test/script/basic/void.js
+++ b/nashorn/test/script/basic/void.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/with.js b/nashorn/test/script/basic/with.js
index 1ae8113..2e13b28 100644
--- a/nashorn/test/script/basic/with.js
+++ b/nashorn/test/script/basic/with.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * With test.
  *
  * @test
- * @run 
+ * @run
  */
 
 var x = {a: 10, b: 20, c: 30};
@@ -38,12 +38,12 @@
 with (x) {
     print(b);
     print(x.b);
-    
+
     b = false;
-    
+
     print(b);
     print(x.b);
-    
+
     y = 200;
 }
 
@@ -52,10 +52,10 @@
 
 for (i in x) print(i, x[i]);
 
-var obj = { 
+var obj = {
     __noSuchProperty__: function(name) {
         return name.toUpperCase();
-    }   
+    }
 };
 
 with(obj) {
diff --git a/nashorn/test/script/basic/withprimitive.js b/nashorn/test/script/basic/withprimitive.js
index a0ee021..a3c6db1 100644
--- a/nashorn/test/script/basic/withprimitive.js
+++ b/nashorn/test/script/basic/withprimitive.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,7 +24,7 @@
 /**
  * Using "with" statement with primitive typed value as scope object.
  * Results in VerifyError: Bad type on operand stack.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/basic/writable_relink.js b/nashorn/test/script/basic/writable_relink.js
index ebc8a3b..378923d 100644
--- a/nashorn/test/script/basic/writable_relink.js
+++ b/nashorn/test/script/basic/writable_relink.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/basic/xorassign.js b/nashorn/test/script/basic/xorassign.js
index 1cb73b6..0a6fd37 100644
--- a/nashorn/test/script/basic/xorassign.js
+++ b/nashorn/test/script/basic/xorassign.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * The following crashes with VerifyError. 
+ * The following crashes with VerifyError.
  *
  * @test
  * @run
diff --git a/nashorn/test/script/basic/yui.js b/nashorn/test/script/basic/yui.js
index 879fb57..9c48af5 100644
--- a/nashorn/test/script/basic/yui.js
+++ b/nashorn/test/script/basic/yui.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,23 +23,23 @@
 
 /**
  * NASHORN-469 : corpus parse test for yahoo ui library / yahoo ui library min
- * 
+ *
  * @test
  * @runif external.yui
  */
 
 var names = [ "yui-min.js", "yui.js" ];
 
-for each (name in names) { 
+for each (name in names) {
     try {
-	try {
+    try {
             var file = __DIR__ + "../external/yui/" + name;
-	    load(__DIR__ + "../external/yui/" + name);
-	} catch (e) { 
-	    print(e);
-	}
+        load(__DIR__ + "../external/yui/" + name);
     } catch (e) {
-	print("error: " + e);
+        print(e);
+    }
+    } catch (e) {
+    print("error: " + e);
     }
     print("parsed and compiled ok " + name);
 }
diff --git a/nashorn/test/script/currently-failing/JDK-8006191.js b/nashorn/test/script/currently-failing/JDK-8006191.js
index b856c71..ca0dda5 100644
--- a/nashorn/test/script/currently-failing/JDK-8006191.js
+++ b/nashorn/test/script/currently-failing/JDK-8006191.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
- * 
+ *
  * 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 Oracle nor the names of its
  *     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
@@ -28,14 +28,14 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
- 
+
 /**
  * JDK-8006191 - `cmd` -> exec("cmd") in script mode
  *
  * @test
  * @option -scripting
  * @argument ArgumentFromCommandLine
- * @run 
+ * @run
  */
 
 #!/usr/bin/jjs
diff --git a/nashorn/test/script/basic/JDK-8010697.js b/nashorn/test/script/currently-failing/JDK-8010697.js
similarity index 90%
rename from nashorn/test/script/basic/JDK-8010697.js
rename to nashorn/test/script/currently-failing/JDK-8010697.js
index c1b8e57..2ed194f 100644
--- a/nashorn/test/script/basic/JDK-8010697.js
+++ b/nashorn/test/script/currently-failing/JDK-8010697.js
@@ -35,7 +35,7 @@
 var refArray = new WeakReferenceArray(N);
 
 for (var i = 0; i < N; i ++) {
-    var object = new java.lang.Object();
+    var object = new java.awt.Color(0,0,0);//lang.Object();
     array[i] = object;
     refArray[i] = new java.lang.ref.WeakReference(object);
 }
@@ -48,11 +48,11 @@
 
 java.lang.System.gc();
 java.lang.System.gc();
+java.lang.System.gc();
 
 for (var i = 0; i < N; i ++) {
     if (refArray[i].get() != null) {
-        print("Reference found at " + i);
-        exit(0);
+        print("Reference found at " + i + " " + refArray + " " + refArray[i].get());
     }
 }
 
diff --git a/nashorn/test/script/basic/JDK-8010697.js.EXPECTED b/nashorn/test/script/currently-failing/JDK-8010697.js.EXPECTED
similarity index 100%
rename from nashorn/test/script/basic/JDK-8010697.js.EXPECTED
rename to nashorn/test/script/currently-failing/JDK-8010697.js.EXPECTED
diff --git a/nashorn/test/script/currently-failing/apply_to_call_bench.js b/nashorn/test/script/currently-failing/apply_to_call_bench.js
new file mode 100644
index 0000000..5c10977
--- /dev/null
+++ b/nashorn/test/script/currently-failing/apply_to_call_bench.js
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+/**
+ * sanity check that apply to call specialization is faster than apply.
+ *
+ * @test
+  * @run
+ */
+
+var Class = {
+    create: function() {
+    return function() { //vararg
+        this.initialize.apply(this, arguments);
+    }
+    }
+};
+
+Color = Class.create();
+Color.prototype = {
+    red: 0, green: 0, blue: 0,
+    initialize: function(r,g,b) {
+    this.red = r;
+    this.green = g;
+    this.blue = b;
+    }
+};
+
+var time1 = 0;
+var time2 = 0;
+
+function set_time1(t) {
+    time1 = t;
+}
+
+function set_time2(t) {
+    time2 = t;
+}
+
+function bench(x, set_time) {
+    var d = new Date;
+    var colors = new Array(16);
+    for (var i=0;i<1e8;i++) {
+    colors[i & 0xf] = new Color(1,2,3);
+    }
+    var t = new Date - d;
+    set_time(t);
+    return colors;
+}
+
+//warmup
+print("Running warmup");
+bench(17, set_time1);
+
+print("Running sharp run");
+bench(17, set_time1);
+
+print("Swapping out call");
+Function.prototype.call = function() {
+    throw "This should not happen, apply should be called instead";
+};
+
+print("Rerunning invalidated");
+bench(17, set_time2);
+
+print("All done!");
+
+if (time1 > time2) {
+    print("ERROR: time1 > time2 (" + time1 + " > " + time2 + ")");
+} else {
+    print("Times OK");
+}
+
diff --git a/nashorn/test/script/currently-failing/apply_to_call_bench.js.EXPECTED b/nashorn/test/script/currently-failing/apply_to_call_bench.js.EXPECTED
new file mode 100644
index 0000000..ad3cbf1
--- /dev/null
+++ b/nashorn/test/script/currently-failing/apply_to_call_bench.js.EXPECTED
@@ -0,0 +1,6 @@
+Running warmup
+Running sharp run
+Swapping out call
+Rerunning invalidated
+All done!
+Times OK
diff --git a/nashorn/test/script/currently-failing/clone_ir.js b/nashorn/test/script/currently-failing/clone_ir.js
index 3c1eccf..1400950 100644
--- a/nashorn/test/script/currently-failing/clone_ir.js
+++ b/nashorn/test/script/currently-failing/clone_ir.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -41,12 +41,12 @@
 var System            = Java.type("java.lang.System");
 
 var toArrayMethod = ASTWriter.class.getMethod("toArray");
-var parseMethod  = Parser.class.getMethod("parse");    
+var parseMethod  = Parser.class.getMethod("parse");
 
 function toString(obj) {
     var output = "{ ";
     for (property in obj) {
-	output += property + ': ' + obj[property]+'; ';
+    output += property + ': ' + obj[property]+'; ';
     }
     return output + '}'
 }
@@ -54,11 +54,11 @@
 function flatten(func) {
     var writer   = new ASTWriter(func);
     var funcList = toArrayMethod.invoke(writer);
-    
+
     var res = [];
     for each (x in funcList) {
-	    res.push({ name: x.getClass().getName(), id: System.identityHashCode(x) });
-	}
+        res.push({ name: x.getClass().getName(), id: System.identityHashCode(x) });
+    }
     return res;
 }
 
@@ -80,20 +80,20 @@
     print(f2.map(toString));
 
     if (f1.length != f2.length) {
-	print("length difference between original and clone " + f1.length + " != " + f2.length);
-	return false;
+    print("length difference between original and clone " + f1.length + " != " + f2.length);
+    return false;
     }
 
     for (var i = 0; i < f1.length; i++) {
-	if (f1[i].name !== f2[i].name) {
-	    print("name conflict at " + i + " " + f1[i].name + " != " + f2[i].name);
-	    return false;
-	} else if (f1[i].id === f2[i].id) {
-	    print("id problem at " + i + " " + toString(f1[i]) + " was not deep copied to " + toString(f2[i]) + " became " + f1[i].id + " != " + f2[i].id);
-	    return false;
-	}
+    if (f1[i].name !== f2[i].name) {
+        print("name conflict at " + i + " " + f1[i].name + " != " + f2[i].name);
+        return false;
+    } else if (f1[i].id === f2[i].id) {
+        print("id problem at " + i + " " + toString(f1[i]) + " was not deep copied to " + toString(f2[i]) + " became " + f1[i].id + " != " + f2[i].id);
+        return false;
     }
-    
+    }
+
     return true;
 }
 
diff --git a/nashorn/test/script/currently-failing/gettersetter.js b/nashorn/test/script/currently-failing/gettersetter.js
index 88f6949..5fec25d 100644
--- a/nashorn/test/script/currently-failing/gettersetter.js
+++ b/nashorn/test/script/currently-failing/gettersetter.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/currently-failing/logcoverage.js b/nashorn/test/script/currently-failing/logcoverage.js
index 2d8d410..0c78c1d 100644
--- a/nashorn/test/script/currently-failing/logcoverage.js
+++ b/nashorn/test/script/currently-failing/logcoverage.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * mh_coverage.js
- * Screen scrape various logs to ensure that we cover enough functionality, 
+ * Screen scrape various logs to ensure that we cover enough functionality,
  * e.g. method handle instrumentation
  *
  * @test
@@ -44,25 +44,25 @@
         var fac = new NashornScriptEngineFactory();
         // get current System.err
         var oldErr = System.err;
-	var oldOut = System.out;
+    var oldOut = System.out;
         var baosErr = new ByteArrayOutputStream();
         var newErr = new PrintStream(baosErr);
         var baosOut = new ByteArrayOutputStream();
-	var newOut = new PrintStream(baosOut);
+    var newOut = new PrintStream(baosOut);
         try {
             // set new standard err
             System.setErr(newErr);
             System.setOut(newOut);
             var engine = fac.getScriptEngine(Java.to(opts, "java.lang.String[]"));
-	    var reader = new java.io.FileReader(name);
+        var reader = new java.io.FileReader(name);
             engine.eval(reader);
             newErr.flush();
-	    newOut.flush();
+        newOut.flush();
             return new java.lang.String(baosErr.toByteArray());
         } finally {
             // restore System.err to old value
             System.setErr(oldErr);
-	    System.setOut(oldOut);
+        System.setOut(oldOut);
         }
     }
 }
@@ -70,27 +70,27 @@
 var str;
 
 var methodsCalled = [
-   'asCollector', 
-   'asType', 
-   'bindTo', 
-   'dropArguments', 
-   'explicitCastArguments', 
-   'filterArguments', 
-   'filterReturnValue', 
-   'findStatic', 
-   'findVirtual',  
-   'foldArguments', 
-   'getter', 
-   'guardWithTest', 
-   'insertArguments', 
-   'methodType', 
+   'asCollector',
+   'asType',
+   'bindTo',
+   'dropArguments',
+   'explicitCastArguments',
+   'filterArguments',
+   'filterReturnValue',
+   'findStatic',
+   'findVirtual',
+   'foldArguments',
+   'getter',
+   'guardWithTest',
+   'insertArguments',
+   'methodType',
    'setter'
 ];
 
 function check(str, strs) {
     for each (s in strs) {
        if (str.indexOf(s) !== -1) {
-	   continue;
+       continue;
        }
        print(s + " not found");
        return;
diff --git a/nashorn/test/script/currently-failing/optimistic_check_type_cases.js b/nashorn/test/script/currently-failing/optimistic_check_type_cases.js
new file mode 100644
index 0000000..80dc759
--- /dev/null
+++ b/nashorn/test/script/currently-failing/optimistic_check_type_cases.js
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8035652,8037858
+ * @summary Implement tests that checks static types in the compiled code
+ * @run
+ */
+
+var inspect = Java.type("jdk.nashorn.test.tools.StaticTypeInspector").inspect
+var a = b = c = 3;
+
+//JDK-8035652
+print(inspect(a/a, "global int division by global int"))
+print(inspect(a%a, "global int modulus by global int"))
+print(inspect(b+=b, "global int addition assignment global int"))
+//JDK-8037858
+print(inspect(b-=b, "global int substraction assignment global int"))
+print(inspect(c*=a, "global int multiplication assignment global int"))
+print(inspect(a/=a, "global int division assignment global int"))
+print(inspect(c%=c, "global int modulo assignment global int"))
diff --git a/nashorn/test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED b/nashorn/test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED
new file mode 100644
index 0000000..eb0573b
--- /dev/null
+++ b/nashorn/test/script/currently-failing/optimistic_check_type_cases.js.EXPECTED
@@ -0,0 +1,7 @@
+global int division by global int: int
+global int modulus by global int: int
+global int addition assignment global int: int
+global int substraction assignment global int: int
+global int multiplication assignment global int: int
+global int division assignment global int: int
+global int modulo assignment global int: int
\ No newline at end of file
diff --git a/nashorn/test/script/maptests/property_delete.js b/nashorn/test/script/currently-failing/property_delete.js
similarity index 98%
rename from nashorn/test/script/maptests/property_delete.js
rename to nashorn/test/script/currently-failing/property_delete.js
index e2824dd..ab508bf 100644
--- a/nashorn/test/script/maptests/property_delete.js
+++ b/nashorn/test/script/currently-failing/property_delete.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/error/JDK-8008814-1.js b/nashorn/test/script/error/JDK-8008814-1.js
index 324d090..7cfa7a3 100644
--- a/nashorn/test/script/error/JDK-8008814-1.js
+++ b/nashorn/test/script/error/JDK-8008814-1.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/JDK-8008814-2.js b/nashorn/test/script/error/JDK-8008814-2.js
index 079b253..fcc0cce 100644
--- a/nashorn/test/script/error/JDK-8008814-2.js
+++ b/nashorn/test/script/error/JDK-8008814-2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/JDK-8016522.js b/nashorn/test/script/error/JDK-8016522.js
index e083228..58e9b2f 100644
--- a/nashorn/test/script/error/JDK-8016522.js
+++ b/nashorn/test/script/error/JDK-8016522.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/JDK-8020437-2.js b/nashorn/test/script/error/JDK-8020437-2.js
index dcd1e17..7dbc2aa 100644
--- a/nashorn/test/script/error/JDK-8020437-2.js
+++ b/nashorn/test/script/error/JDK-8020437-2.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/JDK-8020437.js b/nashorn/test/script/error/JDK-8020437.js
index e8b84c9..6d03aa4 100644
--- a/nashorn/test/script/error/JDK-8020437.js
+++ b/nashorn/test/script/error/JDK-8020437.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/JDK-8026039.js b/nashorn/test/script/error/JDK-8026039.js
index f37d9bd..65fd3d7 100644
--- a/nashorn/test/script/error/JDK-8026039.js
+++ b/nashorn/test/script/error/JDK-8026039.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,4 +29,4 @@
 
 function public() {"use strict"}
 
-function f(public) {"use strict"} 
+function f(public) {"use strict"}
diff --git a/nashorn/test/script/error/JDK-8026039.js.EXPECTED b/nashorn/test/script/error/JDK-8026039.js.EXPECTED
index cde398f..4166339 100644
--- a/nashorn/test/script/error/JDK-8026039.js.EXPECTED
+++ b/nashorn/test/script/error/JDK-8026039.js.EXPECTED
@@ -2,7 +2,7 @@
 function public() {"use strict"}
          ^
 test/script/error/JDK-8026039.js:32:11 Expected ident but found public
-function f(public) {"use strict"} 
+function f(public) {"use strict"}
            ^
 test/script/error/JDK-8026039.js:33:0 Expected } but found eof
 
diff --git a/nashorn/test/script/error/JDK-8027933.js b/nashorn/test/script/error/JDK-8027933.js
index 9b398fa..2c1dc1f 100644
--- a/nashorn/test/script/error/JDK-8027933.js
+++ b/nashorn/test/script/error/JDK-8027933.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/error/JDK-8039047.js b/nashorn/test/script/error/JDK-8039047.js
index 8cbd51f..042dcb2 100644
--- a/nashorn/test/script/error/JDK-8039047.js
+++ b/nashorn/test/script/error/JDK-8039047.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js b/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js
index 12b1669..ac5ae9e 100644
--- a/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js
+++ b/nashorn/test/script/error/NASHORN-154/function_mult_params_in_strict.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,8 +24,8 @@
 /**
  * Early error reporting.
  *
- * The occurrence of an Identifier value appearing more than once within a 
- * FormalParameterList of an individual strict mode FunctionDeclaration or 
+ * The occurrence of an Identifier value appearing more than once within a
+ * FormalParameterList of an individual strict mode FunctionDeclaration or
  * FunctionExpression
  *
  * @test/compile-error
diff --git a/nashorn/test/script/error/NASHORN-154/improper_return_break_continue.js b/nashorn/test/script/error/NASHORN-154/improper_return_break_continue.js
index 7496d77..3fc374e 100644
--- a/nashorn/test/script/error/NASHORN-154/improper_return_break_continue.js
+++ b/nashorn/test/script/error/NASHORN-154/improper_return_break_continue.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-154/invalid_lvalue.js b/nashorn/test/script/error/NASHORN-154/invalid_lvalue.js
index ce28462..1625cce 100644
--- a/nashorn/test/script/error/NASHORN-154/invalid_lvalue.js
+++ b/nashorn/test/script/error/NASHORN-154/invalid_lvalue.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,8 +24,8 @@
 /**
  * Early error reporting.
  *
- * Attempts to call PutValue on any value for which an early determination can 
- * be made that the value is not a Reference (for example, executing the 
+ * Attempts to call PutValue on any value for which an early determination can
+ * be made that the value is not a Reference (for example, executing the
  * assignment statement 3=4).
  *
  * @test/compile-error
diff --git a/nashorn/test/script/error/NASHORN-154/literal_data_and_accessor.js b/nashorn/test/script/error/NASHORN-154/literal_data_and_accessor.js
index 4a236f1..c46e236 100644
--- a/nashorn/test/script/error/NASHORN-154/literal_data_and_accessor.js
+++ b/nashorn/test/script/error/NASHORN-154/literal_data_and_accessor.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-154/literal_mult_getters.js b/nashorn/test/script/error/NASHORN-154/literal_mult_getters.js
index 8777b61..b168417 100644
--- a/nashorn/test/script/error/NASHORN-154/literal_mult_getters.js
+++ b/nashorn/test/script/error/NASHORN-154/literal_mult_getters.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,8 +24,8 @@
 /**
  * Early error reporting.
  *
- * Attempts to define an ObjectLiteral that has multiple get property 
- * assignments with the same name or multiple set property assignments with 
+ * Attempts to define an ObjectLiteral that has multiple get property
+ * assignments with the same name or multiple set property assignments with
  * the same name.
  *
  * @test/compile-error
diff --git a/nashorn/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js b/nashorn/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js
index 30d3fad..b6876a9 100644
--- a/nashorn/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js
+++ b/nashorn/test/script/error/NASHORN-154/literal_mult_prop_in_strict.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -24,7 +24,7 @@
 /**
  * Early error reporting.
  *
- * Attempts in strict mode code to define an ObjectLiteral that has multiple 
+ * Attempts in strict mode code to define an ObjectLiteral that has multiple
  * data property assignments with the same name.
  *
  * @test/compile-error
diff --git a/nashorn/test/script/error/NASHORN-154/with_in_strict.js b/nashorn/test/script/error/NASHORN-154/with_in_strict.js
index 866c822..e9b0bba 100644
--- a/nashorn/test/script/error/NASHORN-154/with_in_strict.js
+++ b/nashorn/test/script/error/NASHORN-154/with_in_strict.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-214.js b/nashorn/test/script/error/NASHORN-214.js
index afffec2..4349619 100644
--- a/nashorn/test/script/error/NASHORN-214.js
+++ b/nashorn/test/script/error/NASHORN-214.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-35.js b/nashorn/test/script/error/NASHORN-35.js
index 314cd3a..3ba6080 100644
--- a/nashorn/test/script/error/NASHORN-35.js
+++ b/nashorn/test/script/error/NASHORN-35.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-39.js b/nashorn/test/script/error/NASHORN-39.js
index 59f4a4a..7afef41 100644
--- a/nashorn/test/script/error/NASHORN-39.js
+++ b/nashorn/test/script/error/NASHORN-39.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -29,5 +29,5 @@
 
 // line terminator here should result in compiler error.
 
-throw 
+throw
   1;
diff --git a/nashorn/test/script/error/NASHORN-568.js b/nashorn/test/script/error/NASHORN-568.js
index 1a8159e..0701a1a 100644
--- a/nashorn/test/script/error/NASHORN-568.js
+++ b/nashorn/test/script/error/NASHORN-568.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-57.js b/nashorn/test/script/error/NASHORN-57.js
index 2dc5b15..fd5ce73 100644
--- a/nashorn/test/script/error/NASHORN-57.js
+++ b/nashorn/test/script/error/NASHORN-57.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/NASHORN-668.js b/nashorn/test/script/error/NASHORN-668.js
index f332856..8abf6ca 100644
--- a/nashorn/test/script/error/NASHORN-668.js
+++ b/nashorn/test/script/error/NASHORN-668.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/quotemissing.js b/nashorn/test/script/error/quotemissing.js
index 74d9a3e..3a70122 100644
--- a/nashorn/test/script/error/quotemissing.js
+++ b/nashorn/test/script/error/quotemissing.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/error/strictmode.js b/nashorn/test/script/error/strictmode.js
index abdf216..05a8e5f 100644
--- a/nashorn/test/script/error/strictmode.js
+++ b/nashorn/test/script/error/strictmode.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/jfx/kaleidoscope.js b/nashorn/test/script/jfx/kaleidoscope.js
index 4430ff0..438ceac 100644
--- a/nashorn/test/script/jfx/kaleidoscope.js
+++ b/nashorn/test/script/jfx/kaleidoscope.js
@@ -52,99 +52,99 @@
 var isFrameRendered = false;

 

 function renderFrame() {

-	if (!isFrameRendered) {

+    if (!isFrameRendered) {

         a=0.2*angle;

-		b=0.7*angle;

-		r=0;

-		fade=32;

-		for(var i=0;i<6;i++)

-			{

-			c[i]=1.0/(i+1)/2;

-			d[i]=1.0/(i+1)/2;

-			}

-		radius=Math.round((WIDTH+HEIGHT)/8);

-		e=radius*0.2;

-		p_x=Math.round(WIDTH/2);

-		p_y=Math.round(HEIGHT/2);

-		x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);

-		y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);

+        b=0.7*angle;

+        r=0;

+        fade=32;

+        for(var i=0;i<6;i++)

+            {

+            c[i]=1.0/(i+1)/2;

+            d[i]=1.0/(i+1)/2;

+            }

+        radius=Math.round((WIDTH+HEIGHT)/8);

+        e=radius*0.2;

+        p_x=Math.round(WIDTH/2);

+        p_y=Math.round(HEIGHT/2);

+        x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);

+        y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);

         isFrameRendered = true;

     }

     anim();

 }

 

 function anim() {

-	var a1=Math.cos(a*2);

-	var a2=Math.cos(a*4);

-	var a3=Math.cos(a);

-	var a4=Math.sin(a);

-	if(b>limit1&&b<limit2) {

-		r+=radius*0.02*a1;

-		prv_x=x;

-		prv_y=y;

-		x=prv_x2+r*a3;

-		y=prv_y2+r*a4;

-	} else {

-		prv_x=x;

-		prv_y=y;

-		prv_x2=x;

-		prv_y2=y;

-		x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);

-		y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);

-	}

-	var c3=16*Math.cos(a*10);

-	var c1=Math.floor(56*Math.cos(a*angle*4)+c3);

-	var c2=Math.floor(56*Math.sin(a*angle*4)-c3);

-	context.lineCap=StrokeLineCap.ROUND;

-	context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.01-0.005*-a1)+')'));

-	context.lineWidth=e*1.4+e*0.8*a3;

-	draw_line(p_x,p_y,prv_x,prv_y,x,y);

-	context.lineWidth=e+e*0.8*a3;

-	draw_line(p_x,p_y,prv_x,prv_y,x,y);

-	context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.06-0.03*-a1)+')'));

-	context.lineWidth=e*0.6+e*0.35*a3;

-	draw_line(p_x,p_y,prv_x,prv_y,x,y);

-	context.setStroke(Paint.valueOf('rgba(0,0,0,0.06)'));

-	context.lineWidth=e*0.4+e*0.225*a3;

-	draw_line(p_x,p_y,prv_x,prv_y,x,y);

-	context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.1-0.075*-a1)+')'));

-	context.lineWidth=e*0.2+e*0.1*a3;

-	draw_line(p_x,p_y,prv_x,prv_y,x,y);

-	context.setStroke(Paint.valueOf('rgba(255,255,255,0.4)'));

-	context.lineWidth=e*(0.1-0.05*-a2);

-	draw_line(p_x,p_y,prv_x,prv_y,x,y);

-	a+=angle*Math.cos(b);

-	b+=angle*0.1;

+    var a1=Math.cos(a*2);

+    var a2=Math.cos(a*4);

+    var a3=Math.cos(a);

+    var a4=Math.sin(a);

+    if(b>limit1&&b<limit2) {

+        r+=radius*0.02*a1;

+        prv_x=x;

+        prv_y=y;

+        x=prv_x2+r*a3;

+        y=prv_y2+r*a4;

+    } else {

+        prv_x=x;

+        prv_y=y;

+        prv_x2=x;

+        prv_y2=y;

+        x=(radius*c[0])*Math.cos(a*d[1])+(radius*c[2])*Math.sin(a*d[3])+(radius*c[4])*Math.sin(a*d[5]);

+        y=(radius*c[5])*Math.sin(a*d[4])+(radius*c[3])*Math.cos(a*d[2])+(radius*c[1])*Math.cos(a*d[0]);

+    }

+    var c3=16*Math.cos(a*10);

+    var c1=Math.floor(56*Math.cos(a*angle*4)+c3);

+    var c2=Math.floor(56*Math.sin(a*angle*4)-c3);

+    context.lineCap=StrokeLineCap.ROUND;

+    context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.01-0.005*-a1)+')'));

+    context.lineWidth=e*1.4+e*0.8*a3;

+    draw_line(p_x,p_y,prv_x,prv_y,x,y);

+    context.lineWidth=e+e*0.8*a3;

+    draw_line(p_x,p_y,prv_x,prv_y,x,y);

+    context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.06-0.03*-a1)+')'));

+    context.lineWidth=e*0.6+e*0.35*a3;

+    draw_line(p_x,p_y,prv_x,prv_y,x,y);

+    context.setStroke(Paint.valueOf('rgba(0,0,0,0.06)'));

+    context.lineWidth=e*0.4+e*0.225*a3;

+    draw_line(p_x,p_y,prv_x,prv_y,x,y);

+    context.setStroke(Paint.valueOf('rgba('+(192+c1)+','+(192+c2)+','+(192-c1)+','+(0.1-0.075*-a1)+')'));

+    context.lineWidth=e*0.2+e*0.1*a3;

+    draw_line(p_x,p_y,prv_x,prv_y,x,y);

+    context.setStroke(Paint.valueOf('rgba(255,255,255,0.4)'));

+    context.lineWidth=e*(0.1-0.05*-a2);

+    draw_line(p_x,p_y,prv_x,prv_y,x,y);

+    a+=angle*Math.cos(b);

+    b+=angle*0.1;

 }

 

 function draw_line(x,y,x1,y1,x2,y2) {

-	context.beginPath();

-	context.moveTo(x+x1,y+y1);

-	context.lineTo(x+x2,y+y2);

-	context.moveTo(x-x1,y+y1);

-	context.lineTo(x-x2,y+y2);

-	context.moveTo(x-x1,y-y1);

-	context.lineTo(x-x2,y-y2);

-	context.moveTo(x+x1,y-y1);

-	context.lineTo(x+x2,y-y2);

-	context.moveTo(x+y1,y+x1);

-	context.lineTo(x+y2,y+x2);

-	context.moveTo(x-y1,y+x1);

-	context.lineTo(x-y2,y+x2);

-	context.moveTo(x-y1,y-x1);

-	context.lineTo(x-y2,y-x2);

-	context.moveTo(x+y1,y-x1);

-	context.lineTo(x+y2,y-x2);

-	context.moveTo(x,y+x2);

-	context.lineTo(x,y+x1);

-	context.moveTo(x,y-x2);

-	context.lineTo(x,y-x1);

-	context.moveTo(x+x2,y);

-	context.lineTo(x+x1,y);

-	context.moveTo(x-x2,y);

-	context.lineTo(x-x1,y);

-	context.stroke();

-	context.closePath();

+    context.beginPath();

+    context.moveTo(x+x1,y+y1);

+    context.lineTo(x+x2,y+y2);

+    context.moveTo(x-x1,y+y1);

+    context.lineTo(x-x2,y+y2);

+    context.moveTo(x-x1,y-y1);

+    context.lineTo(x-x2,y-y2);

+    context.moveTo(x+x1,y-y1);

+    context.lineTo(x+x2,y-y2);

+    context.moveTo(x+y1,y+x1);

+    context.lineTo(x+y2,y+x2);

+    context.moveTo(x-y1,y+x1);

+    context.lineTo(x-y2,y+x2);

+    context.moveTo(x-y1,y-x1);

+    context.lineTo(x-y2,y-x2);

+    context.moveTo(x+y1,y-x1);

+    context.lineTo(x+y2,y-x2);

+    context.moveTo(x,y+x2);

+    context.lineTo(x,y+x1);

+    context.moveTo(x,y-x2);

+    context.lineTo(x,y-x1);

+    context.moveTo(x+x2,y);

+    context.lineTo(x+x1,y);

+    context.moveTo(x-x2,y);

+    context.lineTo(x-x1,y);

+    context.stroke();

+    context.closePath();

 }

 

 var stack = new StackPane();

diff --git a/nashorn/test/script/jfx/spread.js b/nashorn/test/script/jfx/spread.js
index 4a8f38c..8312d1f 100644
--- a/nashorn/test/script/jfx/spread.js
+++ b/nashorn/test/script/jfx/spread.js
@@ -211,7 +211,7 @@
 var timer = new AnimationTimerExtend() {

     handle: function handle(now) {

         if (frame < 200) {

-		    draw_frame();

+            draw_frame();

         } else {

             checkImageAndExit();

             timer.stop();

diff --git a/nashorn/test/script/maptests/builtins.js b/nashorn/test/script/maptests/builtins.js
index 4de2ec9..8bfd848 100644
--- a/nashorn/test/script/maptests/builtins.js
+++ b/nashorn/test/script/maptests/builtins.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/maptests/constructor.js b/nashorn/test/script/maptests/constructor.js
index 5722a3c..f409ce1 100644
--- a/nashorn/test/script/maptests/constructor.js
+++ b/nashorn/test/script/maptests/constructor.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -33,4 +33,4 @@
 // These objects should share the map
 assertSameMap(new Point(2, 3), new Point(43, 23));
 assertSameMap(new Point(), new Point());
-assertSameMap(new Point(), new Point(3, 1));
+assertEqualWithoutTypeMap(new Point(), new Point(3, 1));
diff --git a/nashorn/test/script/maptests/maputil.js b/nashorn/test/script/maptests/maputil.js
index aa85d7f..2294e75 100644
--- a/nashorn/test/script/maptests/maputil.js
+++ b/nashorn/test/script/maptests/maputil.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -27,7 +27,7 @@
 
 function assertSameMap(obj1, obj2, msg) {
     if (! Debug.identical(Debug.map(obj1), Debug.map(obj2))) {
-        fail(obj1.constructor + " instances don't share map");
+        fail(obj1.constructor + " instances don't share map " + Debug.diffPropertyMaps(Debug.map(obj1), Debug.map(obj2)));
     }
 }
 
@@ -36,3 +36,9 @@
         fail(obj1.constructor + " and " + obj2.constructor + " instances share map");
     }
 }
+
+function assertEqualWithoutTypeMap(obj1, obj2, msg) {
+    if (!Debug.equalWithoutType(Debug.map(obj1), Debug.map(obj2))) {
+        fail(obj1.constructor + " and " + obj2.constructor + " instances don't have identical (without considering property types) maps");
+    }
+}
diff --git a/nashorn/test/script/maptests/object_create.js b/nashorn/test/script/maptests/object_create.js
index 1b1bd60..e0b5f60 100644
--- a/nashorn/test/script/maptests/object_create.js
+++ b/nashorn/test/script/maptests/object_create.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/maptests/object_literals.js b/nashorn/test/script/maptests/object_literals.js
index c73d801..b379ac6 100644
--- a/nashorn/test/script/maptests/object_literals.js
+++ b/nashorn/test/script/maptests/object_literals.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -42,5 +42,5 @@
 
 // Object literals created at different callsites
 assertSameMap({}, {});
-assertSameMap({foo: 4}, {foo: 'hello'});
-assertSameMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54});
+assertEqualWithoutTypeMap({foo: 4}, {foo: 'hello'});
+assertEqualWithoutTypeMap({foo: 34, bar: 'fdgd'}, {foo: 'world', bar: 54});
diff --git a/nashorn/test/script/maptests/point.js b/nashorn/test/script/maptests/point.js
index 38b8fa2..06b64dd 100644
--- a/nashorn/test/script/maptests/point.js
+++ b/nashorn/test/script/maptests/point.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -46,4 +46,4 @@
 
 assertSameMap(new Point(2, 3), new Point(43, 23));
 assertSameMap(new Point(), new Point());
-assertSameMap(new Point(), new Point(3, 1));
+assertEqualWithoutTypeMap(new Point(), new Point(3, 1));
diff --git a/nashorn/test/script/maptests/property_add.js b/nashorn/test/script/maptests/property_add.js
index 2026455..606f2d0 100644
--- a/nashorn/test/script/maptests/property_add.js
+++ b/nashorn/test/script/maptests/property_add.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -43,4 +43,4 @@
 addX(obj1, 3);
 addX(obj2, 'hello');
 
-assertSameMap(obj1, obj2);
+assertEqualWithoutTypeMap(obj1, obj2);
diff --git a/nashorn/test/script/maptests/proto.js b/nashorn/test/script/maptests/proto.js
index afb5950..5bc3332 100644
--- a/nashorn/test/script/maptests/proto.js
+++ b/nashorn/test/script/maptests/proto.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown.js
similarity index 71%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown.js
index db358d2..f1c4625 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown.js
@@ -1,33 +1,38 @@
 /*
- * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Base library for Showdown markdown engine Nashorn testing.
+ * @subtest
  *
- * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ *
  */
 
-load(__DIR__ + "runsunspider.js");
+load(__DIR__ + "external/showdown/showdown.js");
+var shdwn = Showdown;
+var window =  {
+    Showdown: shdwn
+}
+load(__DIR__ + "external/showdown/table.js");
+var converter = new Showdown.converter({extensions: ['table']});
 
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/anchors-by-reference.js
similarity index 65%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/anchors-by-reference.js
index db358d2..20a8761 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/anchors-by-reference.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nThis is [an example][id] reference-style link.\nThis is [another] [foo] reference-style link.\nThis is [a third][bar] reference-style link.\nThis is [a fourth][4] reference-style link.\n\n  [id]: http://example.com/  \"Optional Title Here\"\n  [foo]: http://example.com/  (Optional Title Here)\n  [bar]: http://example.com/  (Optional Title Here)\n  [4]: <http://example.com/>\n    \"Optional Title Here\"";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/anchors-by-reference.js.EXPECTED b/nashorn/test/script/markdown/anchors-by-reference.js.EXPECTED
new file mode 100644
index 0000000..6115d50
--- /dev/null
+++ b/nashorn/test/script/markdown/anchors-by-reference.js.EXPECTED
@@ -0,0 +1,4 @@
+<p>This is <a href="http://example.com/" title="Optional Title Here">an example</a> reference-style link.
+This is <a href="http://example.com/" title="Optional Title Here">another</a> reference-style link.
+This is <a href="http://example.com/" title="Optional Title Here">a third</a> reference-style link.
+This is <a href="http://example.com/" title="Optional Title Here">a fourth</a> reference-style link.</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/automatic-anchors.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/automatic-anchors.js
index db358d2..260dd59 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/automatic-anchors.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n<http://example.com/>";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/automatic-anchors.js.EXPECTED b/nashorn/test/script/markdown/automatic-anchors.js.EXPECTED
new file mode 100644
index 0000000..6de71a9
--- /dev/null
+++ b/nashorn/test/script/markdown/automatic-anchors.js.EXPECTED
@@ -0,0 +1 @@
+<p><a href="http://example.com/">http://example.com/</a></p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/blockquote-nested-markdown.js
similarity index 75%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/blockquote-nested-markdown.js
index db358d2..c030960 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/blockquote-nested-markdown.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "> ## This is a header.\n>\n> 1.   This is the first list item.\n> 2.   This is the second list item.\n>\n> Here's some example code:\n>\n>     return shell_exec(\"echo $input | $markdown_script\");";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/blockquote-nested-markdown.js.EXPECTED b/nashorn/test/script/markdown/blockquote-nested-markdown.js.EXPECTED
new file mode 100644
index 0000000..b32199c
--- /dev/null
+++ b/nashorn/test/script/markdown/blockquote-nested-markdown.js.EXPECTED
@@ -0,0 +1,13 @@
+<blockquote>
+  <h2 id="thisisaheader">This is a header.</h2>
+  
+  <ol>
+  <li>This is the first list item.</li>
+  <li>This is the second list item.</li>
+  </ol>
+  
+  <p>Here's some example code:</p>
+
+<pre><code>return shell_exec("echo $input | $markdown_script");
+</code></pre>
+</blockquote>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/blockquote.js
similarity index 81%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/blockquote.js
index db358d2..e342b01 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/blockquote.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "  \n  > This is a multi line blockquote test\n  >\n  > With more than one line.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/blockquote.js.EXPECTED b/nashorn/test/script/markdown/blockquote.js.EXPECTED
new file mode 100644
index 0000000..c4956bb
--- /dev/null
+++ b/nashorn/test/script/markdown/blockquote.js.EXPECTED
@@ -0,0 +1,5 @@
+<blockquote>
+  <p>This is a multi line blockquote test</p>
+  
+  <p>With more than one line.</p>
+</blockquote>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/code-block-html-escape.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/code-block-html-escape.js
index db358d2..9ea178d 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/code-block-html-escape.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nThis is some HTML:\n\n    <h1>Heading</h1>";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/code-block-html-escape.js.EXPECTED b/nashorn/test/script/markdown/code-block-html-escape.js.EXPECTED
new file mode 100644
index 0000000..028f874
--- /dev/null
+++ b/nashorn/test/script/markdown/code-block-html-escape.js.EXPECTED
@@ -0,0 +1,4 @@
+<p>This is some HTML:</p>
+
+<pre><code>&lt;h1&gt;Heading&lt;/h1&gt;
+</code></pre>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/code-block.js
similarity index 83%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/code-block.js
index db358d2..e3f7429 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/code-block.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nThis is a normal paragraph:\n\n    This is a code block.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/code-block.js.EXPECTED b/nashorn/test/script/markdown/code-block.js.EXPECTED
new file mode 100644
index 0000000..3e56099
--- /dev/null
+++ b/nashorn/test/script/markdown/code-block.js.EXPECTED
@@ -0,0 +1,4 @@
+<p>This is a normal paragraph:</p>
+
+<pre><code>This is a code block.
+</code></pre>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/doubline-list.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/doubline-list.js
index db358d2..bb56ea5 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/doubline-list.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n *  Bird\n\n *  Magic";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/doubline-list.js.EXPECTED b/nashorn/test/script/markdown/doubline-list.js.EXPECTED
new file mode 100644
index 0000000..1065a44
--- /dev/null
+++ b/nashorn/test/script/markdown/doubline-list.js.EXPECTED
@@ -0,0 +1,4 @@
+<ul>
+<li><p>Bird</p></li>
+<li><p>Magic</p></li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/emphasis.js
similarity index 83%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/emphasis.js
index db358d2..1775207 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/emphasis.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n*important*\n\n_important_\n\nthis mid*important*sentence";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/emphasis.js.EXPECTED b/nashorn/test/script/markdown/emphasis.js.EXPECTED
new file mode 100644
index 0000000..a1fda4a
--- /dev/null
+++ b/nashorn/test/script/markdown/emphasis.js.EXPECTED
@@ -0,0 +1,5 @@
+<p><em>important</em></p>
+
+<p><em>important</em></p>
+
+<p>this mid<em>important</em>sentence</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/escaped-number-period.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/escaped-number-period.js
index db358d2..b21776c 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/escaped-number-period.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "It happened in 1986\.  What a great season.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/escaped-number-period.js.EXPECTED b/nashorn/test/script/markdown/escaped-number-period.js.EXPECTED
new file mode 100644
index 0000000..0ea83ba
--- /dev/null
+++ b/nashorn/test/script/markdown/escaped-number-period.js.EXPECTED
@@ -0,0 +1 @@
+<p>It happened in 1986.  What a great season.</p>
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/markdown/escaping.js
similarity index 80%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/markdown/escaping.js
index c9182ef..c9897f7 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/markdown/escaping.js
@@ -1,35 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var input = "\nThese should all be escaped:\n\n\\\n\n\`\n\n\*\n\n\_\n\n\{\n\n\}\n\n\[\n\n\]\n\n\(\n\n\)\n\n\#\n\n\+\n\n\-\n\n\.\n\n\!";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/escaping.js.EXPECTED b/nashorn/test/script/markdown/escaping.js.EXPECTED
new file mode 100644
index 0000000..1ac6a29
--- /dev/null
+++ b/nashorn/test/script/markdown/escaping.js.EXPECTED
@@ -0,0 +1,31 @@
+<p>These should all be escaped:</p>
+
+<p>\</p>
+
+<p>`</p>
+
+<p>*</p>
+
+<p>_</p>
+
+<p>{</p>
+
+<p>}</p>
+
+<p>[</p>
+
+<p>]</p>
+
+<p>(</p>
+
+<p>)</p>
+
+<p>#</p>
+
+<p>+</p>
+
+<p>-</p>
+
+<p>.</p>
+
+<p>!</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/github-style-at-start.js
similarity index 82%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/github-style-at-start.js
index db358d2..053f504 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/github-style-at-start.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "```\nfunction MyFunc(a) {\n    // ...\n}\n```\n\nThat is some code!";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/github-style-at-start.js.EXPECTED b/nashorn/test/script/markdown/github-style-at-start.js.EXPECTED
new file mode 100644
index 0000000..4f119a7
--- /dev/null
+++ b/nashorn/test/script/markdown/github-style-at-start.js.EXPECTED
@@ -0,0 +1,6 @@
+<pre><code>function MyFunc(a) {
+    // ...
+}
+</code></pre>
+
+<p>That is some code!</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/github-style-codeblock.js
similarity index 78%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/github-style-codeblock.js
index db358d2..272f8ab 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/github-style-codeblock.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nDefine a function in javascript:\n\n```\nfunction MyFunc(a) {\n    var s = '`';\n}\n```\n\nAnd some HTML\n\n```html\n<div>HTML!</div>\n```";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/github-style-codeblock.js.EXPECTED b/nashorn/test/script/markdown/github-style-codeblock.js.EXPECTED
new file mode 100644
index 0000000..5daca2f
--- /dev/null
+++ b/nashorn/test/script/markdown/github-style-codeblock.js.EXPECTED
@@ -0,0 +1,11 @@
+<p>Define a function in javascript:</p>
+
+<pre><code>function MyFunc(a) {
+    var s = '`';
+}
+</code></pre>
+
+<p>And some HTML</p>
+
+<pre><code class="html">&lt;div&gt;HTML!&lt;/div&gt;
+</code></pre>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/github-style-linebreaks.js
similarity index 83%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/github-style-linebreaks.js
index db358d2..17c739f 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/github-style-linebreaks.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "```\ncode can go here\nthis is rendered on a second line\n```";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/github-style-linebreaks.js.EXPECTED b/nashorn/test/script/markdown/github-style-linebreaks.js.EXPECTED
new file mode 100644
index 0000000..276dbf0
--- /dev/null
+++ b/nashorn/test/script/markdown/github-style-linebreaks.js.EXPECTED
@@ -0,0 +1,3 @@
+<pre><code>code can go here
+this is rendered on a second line
+</code></pre>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h1-with-double-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h1-with-double-hash.js
index db358d2..7a822e5 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h1-with-double-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "# This is an H1 #";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h1-with-double-hash.js.EXPECTED b/nashorn/test/script/markdown/h1-with-double-hash.js.EXPECTED
new file mode 100644
index 0000000..ab5b555
--- /dev/null
+++ b/nashorn/test/script/markdown/h1-with-double-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h1 id="thisisanh1">This is an H1</h1>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h1-with-equals.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h1-with-equals.js
index db358d2..ec1b5a8 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h1-with-equals.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "This is an H1\n=============";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h1-with-equals.js.EXPECTED b/nashorn/test/script/markdown/h1-with-equals.js.EXPECTED
new file mode 100644
index 0000000..ab5b555
--- /dev/null
+++ b/nashorn/test/script/markdown/h1-with-equals.js.EXPECTED
@@ -0,0 +1 @@
+<h1 id="thisisanh1">This is an H1</h1>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h1-with-single-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h1-with-single-hash.js
index db358d2..b878274 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h1-with-single-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "# This is an H1";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h1-with-single-hash.js.EXPECTED b/nashorn/test/script/markdown/h1-with-single-hash.js.EXPECTED
new file mode 100644
index 0000000..ab5b555
--- /dev/null
+++ b/nashorn/test/script/markdown/h1-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h1 id="thisisanh1">This is an H1</h1>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h2-with-dashes.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h2-with-dashes.js
index db358d2..b5af2d3 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h2-with-dashes.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "This is an H2\n-------------";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h2-with-dashes.js.EXPECTED b/nashorn/test/script/markdown/h2-with-dashes.js.EXPECTED
new file mode 100644
index 0000000..375a0d0
--- /dev/null
+++ b/nashorn/test/script/markdown/h2-with-dashes.js.EXPECTED
@@ -0,0 +1 @@
+<h2 id="thisisanh2">This is an H2</h2>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h2-with-double-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h2-with-double-hash.js
index db358d2..0f7725f 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h2-with-double-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "## This is an H2 ##";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h2-with-double-hash.js.EXPECTED b/nashorn/test/script/markdown/h2-with-double-hash.js.EXPECTED
new file mode 100644
index 0000000..375a0d0
--- /dev/null
+++ b/nashorn/test/script/markdown/h2-with-double-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h2 id="thisisanh2">This is an H2</h2>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h2-with-single-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h2-with-single-hash.js
index db358d2..29fb1c9 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h2-with-single-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "## This is an H2";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h2-with-single-hash.js.EXPECTED b/nashorn/test/script/markdown/h2-with-single-hash.js.EXPECTED
new file mode 100644
index 0000000..375a0d0
--- /dev/null
+++ b/nashorn/test/script/markdown/h2-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h2 id="thisisanh2">This is an H2</h2>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h3-with-double-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h3-with-double-hash.js
index db358d2..4e0eab8 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h3-with-double-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "### This is an H3 ###";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h3-with-double-hash.js.EXPECTED b/nashorn/test/script/markdown/h3-with-double-hash.js.EXPECTED
new file mode 100644
index 0000000..13f8c9e
--- /dev/null
+++ b/nashorn/test/script/markdown/h3-with-double-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h3 id="thisisanh3">This is an H3</h3>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h3-with-single-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h3-with-single-hash.js
index db358d2..ab815eb 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h3-with-single-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "### This is an H3";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h3-with-single-hash.js.EXPECTED b/nashorn/test/script/markdown/h3-with-single-hash.js.EXPECTED
new file mode 100644
index 0000000..13f8c9e
--- /dev/null
+++ b/nashorn/test/script/markdown/h3-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h3 id="thisisanh3">This is an H3</h3>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h4-with-single-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h4-with-single-hash.js
index db358d2..38d7367 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h4-with-single-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "#### This is an H4";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h4-with-single-hash.js.EXPECTED b/nashorn/test/script/markdown/h4-with-single-hash.js.EXPECTED
new file mode 100644
index 0000000..165b4ef
--- /dev/null
+++ b/nashorn/test/script/markdown/h4-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h4 id="thisisanh4">This is an H4</h4>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h5-with-single-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h5-with-single-hash.js
index db358d2..4a3d839 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h5-with-single-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "##### This is an H5";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h5-with-single-hash.js.EXPECTED b/nashorn/test/script/markdown/h5-with-single-hash.js.EXPECTED
new file mode 100644
index 0000000..28eac14
--- /dev/null
+++ b/nashorn/test/script/markdown/h5-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h5 id="thisisanh5">This is an H5</h5>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/h6-with-single-hash.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/h6-with-single-hash.js
index db358d2..4a90f5c 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/h6-with-single-hash.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "###### This is an H6";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/h6-with-single-hash.js.EXPECTED b/nashorn/test/script/markdown/h6-with-single-hash.js.EXPECTED
new file mode 100644
index 0000000..47574cc
--- /dev/null
+++ b/nashorn/test/script/markdown/h6-with-single-hash.js.EXPECTED
@@ -0,0 +1 @@
+<h6 id="thisisanh6">This is an H6</h6>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/horizontal-rules.js
similarity index 82%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/horizontal-rules.js
index db358d2..cec7157 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/horizontal-rules.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n* * *\n\n***\n\n*****\n\n- - -\n\n---------------------------------------\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/horizontal-rules.js.EXPECTED b/nashorn/test/script/markdown/horizontal-rules.js.EXPECTED
new file mode 100644
index 0000000..aaef23e
--- /dev/null
+++ b/nashorn/test/script/markdown/horizontal-rules.js.EXPECTED
@@ -0,0 +1,9 @@
+<hr />
+
+<hr />
+
+<hr />
+
+<hr />
+
+<hr />
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/html5-strutural-tags.js
similarity index 71%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/html5-strutural-tags.js
index db358d2..ad27c87 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/html5-strutural-tags.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nThese HTML5 tags should pass through just fine.\n\n<section>hello</section>\n<header>head</header>\n<footer>footsies</footer>\n<nav>navigation</nav>\n<article>read me</article>\n<aside>ignore me</aside>\n<article>read\nme</article>\n<aside>\nignore me\n</aside>\n\nthe end";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/html5-strutural-tags.js.EXPECTED b/nashorn/test/script/markdown/html5-strutural-tags.js.EXPECTED
new file mode 100644
index 0000000..528731f
--- /dev/null
+++ b/nashorn/test/script/markdown/html5-strutural-tags.js.EXPECTED
@@ -0,0 +1,22 @@
+<p>These HTML5 tags should pass through just fine.</p>
+
+<section>hello</section>
+
+<header>head</header>
+
+<footer>footsies</footer>
+
+<nav>navigation</nav>
+
+<article>read me</article>
+
+<aside>ignore me</aside>
+
+<article>read
+me</article>
+
+<aside>
+ignore me
+</aside>
+
+<p>the end</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/images.js
similarity index 77%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/images.js
index db358d2..4d52d61 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/images.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n![Alt text](/path/to/img.jpg)\n\n![Alt text](/path/to/img.jpg \"Optional title\")\n\n![Alt text][id]\n\n  [id]: url/to/image  \"Optional title attribute\"";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/images.js.EXPECTED b/nashorn/test/script/markdown/images.js.EXPECTED
new file mode 100644
index 0000000..7df5855
--- /dev/null
+++ b/nashorn/test/script/markdown/images.js.EXPECTED
@@ -0,0 +1,5 @@
+<p><img src="/path/to/img.jpg" alt="Alt text" title="" /></p>
+
+<p><img src="/path/to/img.jpg" alt="Alt text" title="Optional title" /></p>
+
+<p><img src="url/to/image" alt="Alt text" title="Optional title attribute" /></p>
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/markdown/implicit-anchors.js
similarity index 79%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/markdown/implicit-anchors.js
index c9182ef..11d4bdb 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/markdown/implicit-anchors.js
@@ -1,35 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var input = "\nSearch the web at [Google][] or [Daring Fireball][].\n\n  [Google]: http://google.com/\n  [Daring Fireball]: http://daringfireball.net/";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/implicit-anchors.js.EXPECTED b/nashorn/test/script/markdown/implicit-anchors.js.EXPECTED
new file mode 100644
index 0000000..01e62d9
--- /dev/null
+++ b/nashorn/test/script/markdown/implicit-anchors.js.EXPECTED
@@ -0,0 +1 @@
+<p>Search the web at <a href="http://google.com/">Google</a> or <a href="http://daringfireball.net/">Daring Fireball</a>.</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/inline-anchors.js
similarity index 79%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/inline-anchors.js
index db358d2..8b18e0d 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/inline-anchors.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nThis is [an example](http://example.com/ \"Title\") inline link.\n\n[This link](http://example.net/) has no title attribute.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/inline-anchors.js.EXPECTED b/nashorn/test/script/markdown/inline-anchors.js.EXPECTED
new file mode 100644
index 0000000..52f90ed
--- /dev/null
+++ b/nashorn/test/script/markdown/inline-anchors.js.EXPECTED
@@ -0,0 +1,3 @@
+<p>This is <a href="http://example.com/" title="Title">an example</a> inline link.</p>
+
+<p><a href="http://example.net/">This link</a> has no title attribute.</p>
diff --git a/nashorn/test/script/basic/arraysIntKey.js b/nashorn/test/script/markdown/inline-code.js
similarity index 70%
copy from nashorn/test/script/basic/arraysIntKey.js
copy to nashorn/test/script/markdown/inline-code.js
index c9182ef..78fe9d7 100644
--- a/nashorn/test/script/basic/arraysIntKey.js
+++ b/nashorn/test/script/markdown/inline-code.js
@@ -1,35 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * Checks that we override array entries with defineProperty.
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
  * @run
  */
- 
-var o = [0];
-Object.defineProperty(o, "0", { get: function() { return "zero"; }, set: function(v) { print(v); }, configurable: true });
 
-print(o[0]);
-o[0] = "one";
+var input = "\nCreate a new `function`.\n\nUse the backtick in MySQL syntax ``SELECT `column` FROM whatever``.\n\nA single backtick in a code span: `` ` ``\n\nA backtick-delimited string in a code span: `` `foo` ``\n\nPlease don't use any `<blink>` tags.\n\n`&#8212;` is the decimal-encoded equivalent of `&mdash;`.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/inline-code.js.EXPECTED b/nashorn/test/script/markdown/inline-code.js.EXPECTED
new file mode 100644
index 0000000..ebb7fdc
--- /dev/null
+++ b/nashorn/test/script/markdown/inline-code.js.EXPECTED
@@ -0,0 +1,11 @@
+<p>Create a new <code>function</code>.</p>
+
+<p>Use the backtick in MySQL syntax <code>SELECT `column` FROM whatever</code>.</p>
+
+<p>A single backtick in a code span: <code>`</code></p>
+
+<p>A backtick-delimited string in a code span: <code>`foo`</code></p>
+
+<p>Please don't use any <code>&lt;blink&gt;</code> tags.</p>
+
+<p><code>&amp;#8212;</code> is the decimal-encoded equivalent of <code>&amp;mdash;</code>.</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/inline-style-tag.js
similarity index 82%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/inline-style-tag.js
index db358d2..5123e0e 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/inline-style-tag.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n<style>\n    p { line-height: 20px; }\n</style>\n\nAn exciting sentence.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/inline-style-tag.js.EXPECTED b/nashorn/test/script/markdown/inline-style-tag.js.EXPECTED
new file mode 100644
index 0000000..1006aa8
--- /dev/null
+++ b/nashorn/test/script/markdown/inline-style-tag.js.EXPECTED
@@ -0,0 +1,5 @@
+<style>
+    p { line-height: 20px; }
+</style>
+
+<p>An exciting sentence.</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/lazy-blockquote.js
similarity index 82%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/lazy-blockquote.js
index db358d2..c857957 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/lazy-blockquote.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n  > This is a multi line blockquote test\n\n  > With more than one line.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/lazy-blockquote.js.EXPECTED b/nashorn/test/script/markdown/lazy-blockquote.js.EXPECTED
new file mode 100644
index 0000000..c4956bb
--- /dev/null
+++ b/nashorn/test/script/markdown/lazy-blockquote.js.EXPECTED
@@ -0,0 +1,5 @@
+<blockquote>
+  <p>This is a multi line blockquote test</p>
+  
+  <p>With more than one line.</p>
+</blockquote>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/list-with-blockquote.js
similarity index 81%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/list-with-blockquote.js
index db358d2..8caf22e 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/list-with-blockquote.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "*   A list item with a blockquote:\n\n    > This is a blockquote\n    > inside a list item.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/list-with-blockquote.js.EXPECTED b/nashorn/test/script/markdown/list-with-blockquote.js.EXPECTED
new file mode 100644
index 0000000..7f18f5c
--- /dev/null
+++ b/nashorn/test/script/markdown/list-with-blockquote.js.EXPECTED
@@ -0,0 +1,8 @@
+<ul>
+<li><p>A list item with a blockquote:</p>
+
+<blockquote>
+  <p>This is a blockquote
+  inside a list item.</p>
+</blockquote></li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/list-with-code.js
similarity index 83%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/list-with-code.js
index db358d2..5d226d5 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/list-with-code.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "*   A list item with code:\n\n        alert('Hello world!');";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/list-with-code.js.EXPECTED b/nashorn/test/script/markdown/list-with-code.js.EXPECTED
new file mode 100644
index 0000000..566fdae
--- /dev/null
+++ b/nashorn/test/script/markdown/list-with-code.js.EXPECTED
@@ -0,0 +1,6 @@
+<ul>
+<li><p>A list item with code:</p>
+
+<pre><code>alert('Hello world!');
+</code></pre></li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/multi-paragraph-list.js
similarity index 80%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/multi-paragraph-list.js
index db358d2..842e6a7 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/multi-paragraph-list.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n 1.  This is a major bullet point.\n\n    That contains multiple paragraphs.\n\n 2.  And another line";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/multi-paragraph-list.js.EXPECTED b/nashorn/test/script/markdown/multi-paragraph-list.js.EXPECTED
new file mode 100644
index 0000000..3d751c5
--- /dev/null
+++ b/nashorn/test/script/markdown/multi-paragraph-list.js.EXPECTED
@@ -0,0 +1,6 @@
+<ol>
+<li><p>This is a major bullet point.</p>
+
+<p>That contains multiple paragraphs.</p></li>
+<li><p>And another line</p></li>
+</ol>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/multiline-unordered-list.js
similarity index 81%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/multiline-unordered-list.js
index db358d2..77671b7 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/multiline-unordered-list.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n - This line spans\n more than one line and is lazy\n - Similar to this line";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/multiline-unordered-list.js.EXPECTED b/nashorn/test/script/markdown/multiline-unordered-list.js.EXPECTED
new file mode 100644
index 0000000..fb2a58e
--- /dev/null
+++ b/nashorn/test/script/markdown/multiline-unordered-list.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>This line spans
+more than one line and is lazy</li>
+<li>Similar to this line</li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/nested-blockquote.js
similarity index 80%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/nested-blockquote.js
index db358d2..b6925c3 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/nested-blockquote.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n  > This is a multi line blockquote test\n  >\n  > > And nesting!\n  >\n  > With more than one line.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/nested-blockquote.js.EXPECTED b/nashorn/test/script/markdown/nested-blockquote.js.EXPECTED
new file mode 100644
index 0000000..0b00493
--- /dev/null
+++ b/nashorn/test/script/markdown/nested-blockquote.js.EXPECTED
@@ -0,0 +1,9 @@
+<blockquote>
+  <p>This is a multi line blockquote test</p>
+  
+  <blockquote>
+    <p>And nesting!</p>
+  </blockquote>
+  
+  <p>With more than one line.</p>
+</blockquote>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/ordered-list-same-number.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/ordered-list-same-number.js
index db358d2..5b4f97b 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/ordered-list-same-number.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n 1.  Red\n 1.  Green\n 1.  Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/ordered-list-same-number.js.EXPECTED b/nashorn/test/script/markdown/ordered-list-same-number.js.EXPECTED
new file mode 100644
index 0000000..b1abb53
--- /dev/null
+++ b/nashorn/test/script/markdown/ordered-list-same-number.js.EXPECTED
@@ -0,0 +1,5 @@
+<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/ordered-list-wrong-numbers.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/ordered-list-wrong-numbers.js
index db358d2..56c4cea 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/ordered-list-wrong-numbers.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n 8.  Red\n 1.  Green\n 3.  Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED b/nashorn/test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED
new file mode 100644
index 0000000..b1abb53
--- /dev/null
+++ b/nashorn/test/script/markdown/ordered-list-wrong-numbers.js.EXPECTED
@@ -0,0 +1,5 @@
+<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/ordered-list.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/ordered-list.js
index db358d2..0316f2d 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/ordered-list.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n 1.  Red\n 2.  Green\n 3.  Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/ordered-list.js.EXPECTED b/nashorn/test/script/markdown/ordered-list.js.EXPECTED
new file mode 100644
index 0000000..b1abb53
--- /dev/null
+++ b/nashorn/test/script/markdown/ordered-list.js.EXPECTED
@@ -0,0 +1,5 @@
+<ol>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ol>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/relative-anchors.js
similarity index 84%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/relative-anchors.js
index db358d2..b9938f3 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/relative-anchors.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nSee my [About](/about/) page for details.";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/relative-anchors.js.EXPECTED b/nashorn/test/script/markdown/relative-anchors.js.EXPECTED
new file mode 100644
index 0000000..6db73dc
--- /dev/null
+++ b/nashorn/test/script/markdown/relative-anchors.js.EXPECTED
@@ -0,0 +1 @@
+<p>See my <a href="/about/">About</a> page for details.</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/simple-paragraph.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/simple-paragraph.js
index db358d2..e7bcd7d 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/simple-paragraph.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nHello, world!";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/simple-paragraph.js.EXPECTED b/nashorn/test/script/markdown/simple-paragraph.js.EXPECTED
new file mode 100644
index 0000000..7ce5354
--- /dev/null
+++ b/nashorn/test/script/markdown/simple-paragraph.js.EXPECTED
@@ -0,0 +1 @@
+<p>Hello, world!</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/strong.js
similarity index 83%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/strong.js
index db358d2..5f2a089 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/strong.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n**important**\n\n__important__\n\nreally **freaking**strong";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/strong.js.EXPECTED b/nashorn/test/script/markdown/strong.js.EXPECTED
new file mode 100644
index 0000000..5bcc675
--- /dev/null
+++ b/nashorn/test/script/markdown/strong.js.EXPECTED
@@ -0,0 +1,5 @@
+<p><strong>important</strong></p>
+
+<p><strong>important</strong></p>
+
+<p>really <strong>freaking</strong>strong</p>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/table-basic.js
similarity index 78%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/table-basic.js
index db358d2..6990948 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/table-basic.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "| First Header  | Second Header |\n| ------------- | ------------- |\n| Row 1 Cell 1  | Row 1 Cell 2  |\n| Row 2 Cell 1  | Row 2 Cell 2  |\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/table-basic.js.EXPECTED b/nashorn/test/script/markdown/table-basic.js.EXPECTED
new file mode 100644
index 0000000..d909e65
--- /dev/null
+++ b/nashorn/test/script/markdown/table-basic.js.EXPECTED
@@ -0,0 +1,21 @@
+<table>
+<thead>
+<tr>
+<th id="first_header" style="text-align:left;"> First Header  </th>
+<th id="second_header" style="text-align:left;"> Second Header </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+<td style="text-align:left;"><p>Row 1 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 2  </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 2 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 2  </p></td>
+</tr>
+
+</tbody>
+</table>
diff --git a/nashorn/test/script/basic/runsunspider-lazy.js b/nashorn/test/script/markdown/table-large.js
similarity index 63%
rename from nashorn/test/script/basic/runsunspider-lazy.js
rename to nashorn/test/script/markdown/table-large.js
index 6e24c0c..28c55e5 100644
--- a/nashorn/test/script/basic/runsunspider-lazy.js
+++ b/nashorn/test/script/markdown/table-large.js
@@ -1,34 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @option --lazy-compilation
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "| First Header  | Second Header | Third Header  | Fourth Header |\n| ------------- | ------------- | ------------  | ------------- |\n| Row 1 Cell 1  | Row 1 Cell 2  | Row 1 Cell 3  | Row 1 Cell 4  |\n| Row 2 Cell 1  | Row 2 Cell 2  | Row 2 Cell 3  | Row 2 Cell 4  |\n| Row 3 Cell 1  | Row 3 Cell 2  | Row 3 Cell 3  | Row 3 Cell 4  |\n| Row 4 Cell 1  | Row 4 Cell 2  | Row 4 Cell 3  | Row 4 Cell 4  |\n| Row 5 Cell 1  | Row 5 Cell 2  | Row 5 Cell 3  | Row 5 Cell 4  |\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/table-large.js.EXPECTED b/nashorn/test/script/markdown/table-large.js.EXPECTED
new file mode 100644
index 0000000..332bdab
--- /dev/null
+++ b/nashorn/test/script/markdown/table-large.js.EXPECTED
@@ -0,0 +1,48 @@
+<table>
+<thead>
+<tr>
+<th id="first_header" style="text-align:left;"> First Header  </th>
+<th id="second_header" style="text-align:left;"> Second Header </th>
+<th id="third_header" style="text-align:left;"> Third Header  </th>
+<th id="fourth_header" style="text-align:left;"> Fourth Header </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+<td style="text-align:left;"><p>Row 1 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 2  </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 3  </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 4  </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 2 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 2  </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 3  </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 4  </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 3 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 3 Cell 2  </p></td>
+<td style="text-align:left;"><p>Row 3 Cell 3  </p></td>
+<td style="text-align:left;"><p>Row 3 Cell 4  </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 4 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 4 Cell 2  </p></td>
+<td style="text-align:left;"><p>Row 4 Cell 3  </p></td>
+<td style="text-align:left;"><p>Row 4 Cell 4  </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 5 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 5 Cell 2  </p></td>
+<td style="text-align:left;"><p>Row 5 Cell 3  </p></td>
+<td style="text-align:left;"><p>Row 5 Cell 4  </p></td>
+</tr>
+
+</tbody>
+</table>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/table-with-equals.js
similarity index 78%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/table-with-equals.js
index db358d2..7d1283f 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/table-with-equals.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "| First Header  | Second Header |\n| ============= | ============= |\n| Row 1 Cell 1  | Row 1 Cell 2  |\n| Row 2 Cell 1  | Row 2 Cell 2  |\n";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/table-with-equals.js.EXPECTED b/nashorn/test/script/markdown/table-with-equals.js.EXPECTED
new file mode 100644
index 0000000..d909e65
--- /dev/null
+++ b/nashorn/test/script/markdown/table-with-equals.js.EXPECTED
@@ -0,0 +1,21 @@
+<table>
+<thead>
+<tr>
+<th id="first_header" style="text-align:left;"> First Header  </th>
+<th id="second_header" style="text-align:left;"> Second Header </th>
+</tr>
+</thead>
+
+<tbody>
+<tr>
+<td style="text-align:left;"><p>Row 1 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 1 Cell 2  </p></td>
+</tr>
+
+<tr>
+<td style="text-align:left;"><p>Row 2 Cell 1  </p></td>
+<td style="text-align:left;"><p>Row 2 Cell 2  </p></td>
+</tr>
+
+</tbody>
+</table>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/unordered-list-asterisk.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/unordered-list-asterisk.js
index db358d2..3c421f0 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/unordered-list-asterisk.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n * Red\n * Green\n * Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/unordered-list-asterisk.js.EXPECTED b/nashorn/test/script/markdown/unordered-list-asterisk.js.EXPECTED
new file mode 100644
index 0000000..b445990
--- /dev/null
+++ b/nashorn/test/script/markdown/unordered-list-asterisk.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/unordered-list-minus.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/unordered-list-minus.js
index db358d2..0867cc0 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/unordered-list-minus.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n - Red\n - Green\n - Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/unordered-list-minus.js.EXPECTED b/nashorn/test/script/markdown/unordered-list-minus.js.EXPECTED
new file mode 100644
index 0000000..b445990
--- /dev/null
+++ b/nashorn/test/script/markdown/unordered-list-minus.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/unordered-list-plus.js
similarity index 85%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/unordered-list-plus.js
index db358d2..ac77b61 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/unordered-list-plus.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\n + Red\n + Green\n + Blue";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/unordered-list-plus.js.EXPECTED b/nashorn/test/script/markdown/unordered-list-plus.js.EXPECTED
new file mode 100644
index 0000000..b445990
--- /dev/null
+++ b/nashorn/test/script/markdown/unordered-list-plus.js.EXPECTED
@@ -0,0 +1,5 @@
+<ul>
+<li>Red</li>
+<li>Green</li>
+<li>Blue</li>
+</ul>
diff --git a/nashorn/test/script/basic/runsunspider-eager.js b/nashorn/test/script/markdown/url-with-parenthesis.js
similarity index 80%
copy from nashorn/test/script/basic/runsunspider-eager.js
copy to nashorn/test/script/markdown/url-with-parenthesis.js
index db358d2..01ab472 100644
--- a/nashorn/test/script/basic/runsunspider-eager.js
+++ b/nashorn/test/script/markdown/url-with-parenthesis.js
@@ -1,33 +1,33 @@
 /*
  * 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.
  */
 
 /**
- * runsunspider : runs the sunspider tests and checks for compliance
+ * Test for Showdown markdown parser work with Nashorn.
  *
  * @test
- * @option -timezone=PST
- * @runif external.sunspider
+ * @run
  */
 
-load(__DIR__ + "runsunspider.js");
-
+var input = "\nThere's an [episode](http://en.memory-alpha.org/wiki/Darmok_(episode)) of Star Trek: The Next Generation";
+var output = converter.makeHtml(input);
+print(output);
diff --git a/nashorn/test/script/markdown/url-with-parenthesis.js.EXPECTED b/nashorn/test/script/markdown/url-with-parenthesis.js.EXPECTED
new file mode 100644
index 0000000..9e1e7cc
--- /dev/null
+++ b/nashorn/test/script/markdown/url-with-parenthesis.js.EXPECTED
@@ -0,0 +1 @@
+<p>There's an <a href="http://en.memory-alpha.org/wiki/Darmok_(episode)">episode</a> of Star Trek: The Next Generation</p>
diff --git a/nashorn/test/script/nosecurity/JDK-8044798.js b/nashorn/test/script/nosecurity/JDK-8044798.js
index dc1a747..c3b6d4c 100644
--- a/nashorn/test/script/nosecurity/JDK-8044798.js
+++ b/nashorn/test/script/nosecurity/JDK-8044798.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
@@ -37,11 +37,7 @@
 
 var valueDescFields = DebuggerValueDesc.class.declaredFields;
 Arrays.sort(valueDescFields, function(f1, f2) f1.name.compareTo(f2.name));
-var keyField;
 for each (var f in valueDescFields) {
-    if (f.name == "key") {
-        keyField = f;
-    }
     f.accessible = true;
 }
 
@@ -92,22 +88,18 @@
 
 // valueInfos
 var infos = valueInfosMethod.invoke(null, Object, true);
-Arrays.sort(infos, function (i1, i2) keyField.get(i1).compareTo(keyField.get(i2)));
-
 for each (var info in infos) {
     for each (var f in valueDescFields) {
         print(f.name, "=", f.get(info));
-    }  
+    }
 }
 
 // valueInfos - user defined object
 var infos = valueInfosMethod.invoke(null, { foo: 34, bar: "hello" }, true);
-Arrays.sort(infos, function (i1, i2) keyField.get(i1).compareTo(keyField.get(i2)));
-
 for each (var info in infos) {
     for each (var f in valueDescFields) {
         print(f.name, "=", f.get(info));
-    }  
+    }
 }
 
 // valueAsString
diff --git a/nashorn/test/script/nosecurity/JDK-8044798.js.EXPECTED b/nashorn/test/script/nosecurity/JDK-8044798.js.EXPECTED
index 2a21328..24d8281 100644
--- a/nashorn/test/script/nosecurity/JDK-8044798.js.EXPECTED
+++ b/nashorn/test/script/nosecurity/JDK-8044798.js.EXPECTED
@@ -8,25 +8,17 @@
 valueAsObject = [object Object]
 valueAsString = {foo: 343}
 expandable = false
-key = bindProperties
-valueAsObject = function bindProperties() { [native code] }
-valueAsString = function bindProperties() { [native code] }
+key = setIndexedPropertiesToExternalArrayData
+valueAsObject = function setIndexedPropertiesToExternalArrayData() { [native code] }
+valueAsString = function setIndexedPropertiesToExternalArrayData() { [native code] }
 expandable = false
-key = create
-valueAsObject = function create() { [native code] }
-valueAsString = function create() { [native code] }
+key = getPrototypeOf
+valueAsObject = function getPrototypeOf() { [native code] }
+valueAsString = function getPrototypeOf() { [native code] }
 expandable = false
-key = defineProperties
-valueAsObject = function defineProperties() { [native code] }
-valueAsString = function defineProperties() { [native code] }
-expandable = false
-key = defineProperty
-valueAsObject = function defineProperty() { [native code] }
-valueAsString = function defineProperty() { [native code] }
-expandable = false
-key = freeze
-valueAsObject = function freeze() { [native code] }
-valueAsString = function freeze() { [native code] }
+key = setPrototypeOf
+valueAsObject = function setPrototypeOf() { [native code] }
+valueAsString = function setPrototypeOf() { [native code] }
 expandable = false
 key = getOwnPropertyDescriptor
 valueAsObject = function getOwnPropertyDescriptor() { [native code] }
@@ -36,26 +28,54 @@
 valueAsObject = function getOwnPropertyNames() { [native code] }
 valueAsString = function getOwnPropertyNames() { [native code] }
 expandable = false
-key = getPrototypeOf
-valueAsObject = function getPrototypeOf() { [native code] }
-valueAsString = function getPrototypeOf() { [native code] }
+key = create
+valueAsObject = function create() { [native code] }
+valueAsString = function create() { [native code] }
 expandable = false
-key = isExtensible
-valueAsObject = function isExtensible() { [native code] }
-valueAsString = function isExtensible() { [native code] }
+key = defineProperty
+valueAsObject = function defineProperty() { [native code] }
+valueAsString = function defineProperty() { [native code] }
 expandable = false
-key = isFrozen
-valueAsObject = function isFrozen() { [native code] }
-valueAsString = function isFrozen() { [native code] }
+key = defineProperties
+valueAsObject = function defineProperties() { [native code] }
+valueAsString = function defineProperties() { [native code] }
+expandable = false
+key = seal
+valueAsObject = function seal() { [native code] }
+valueAsString = function seal() { [native code] }
+expandable = false
+key = freeze
+valueAsObject = function freeze() { [native code] }
+valueAsString = function freeze() { [native code] }
+expandable = false
+key = preventExtensions
+valueAsObject = function preventExtensions() { [native code] }
+valueAsString = function preventExtensions() { [native code] }
 expandable = false
 key = isSealed
 valueAsObject = function isSealed() { [native code] }
 valueAsString = function isSealed() { [native code] }
 expandable = false
+key = isFrozen
+valueAsObject = function isFrozen() { [native code] }
+valueAsString = function isFrozen() { [native code] }
+expandable = false
+key = isExtensible
+valueAsObject = function isExtensible() { [native code] }
+valueAsString = function isExtensible() { [native code] }
+expandable = false
 key = keys
 valueAsObject = function keys() { [native code] }
 valueAsString = function keys() { [native code] }
 expandable = false
+key = bindProperties
+valueAsObject = function bindProperties() { [native code] }
+valueAsString = function bindProperties() { [native code] }
+expandable = false
+key = prototype
+valueAsObject = [object Object]
+valueAsString = {toString: function toString() { [native code] }, toLocaleString: function toLocaleString() { [native code] }, valueOf: function valueOf() { [native code] }, hasOwnProperty: function hasOwnProperty() { [native code] }, isPrototypeOf: function isPrototypeOf() { [native code] }, propertyIsEnumerable: function propertyIsEnumerable() { [native code] }, constructor: function Object() { [native code] }, __proto__: null}
+expandable = false
 key = length
 valueAsObject = 1
 valueAsString = 1
@@ -64,33 +84,13 @@
 valueAsObject = Object
 valueAsString = "Object"
 expandable = false
-key = preventExtensions
-valueAsObject = function preventExtensions() { [native code] }
-valueAsString = function preventExtensions() { [native code] }
-expandable = false
-key = prototype
-valueAsObject = [object Object]
-valueAsString = {toString: function toString() { [native code] }, toLocaleString: function toLocaleString() { [native code] }, valueOf: function valueOf() { [native code] }, hasOwnProperty: function hasOwnProperty() { [native code] }, isPrototypeOf: function isPrototypeOf() { [native code] }, propertyIsEnumerable: function propertyIsEnumerable() { [native code] }, constructor: function Object() { [native code] }, __proto__: null}
-expandable = false
-key = seal
-valueAsObject = function seal() { [native code] }
-valueAsString = function seal() { [native code] }
-expandable = false
-key = setIndexedPropertiesToExternalArrayData
-valueAsObject = function setIndexedPropertiesToExternalArrayData() { [native code] }
-valueAsString = function setIndexedPropertiesToExternalArrayData() { [native code] }
-expandable = false
-key = setPrototypeOf
-valueAsObject = function setPrototypeOf() { [native code] }
-valueAsString = function setPrototypeOf() { [native code] }
+key = foo
+valueAsObject = 34
+valueAsString = 34
 expandable = false
 key = bar
 valueAsObject = hello
 valueAsString = "hello"
-expandable = false
-key = foo
-valueAsObject = 34
-valueAsString = 34
 undefined
 null
 "hello"
diff --git a/nashorn/test/script/nosecurity/JDK-8044851.js b/nashorn/test/script/nosecurity/JDK-8044851.js
new file mode 100644
index 0000000..679c349
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8044851.js
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+/**
+ * JDK-8044851: nashorn properties leak memory
+ *
+ * @test
+ * @run
+ * @option -Dnashorn.debug=true
+ * @fork
+ */
+
+function printProperty(value, property) {
+    print(value, property.getKey(), property.isSpill() ? "spill" : "field", property.getSlot());
+}
+
+var obj = {}, i, name;
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    obj[name] = 'a' + i;
+    printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    delete obj[name];
+}
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    obj[name] = 'b' + i;
+    printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    Object.defineProperty(obj, name, {get: function() {return i;}, set: function(v) {}, configurable: true});
+    printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    delete obj[name];
+}
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    obj[name] = 'c' + i;
+    printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 7; i > -1; --i) {
+    name = 'property' + i;
+    delete obj[name];
+}
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    obj[name] = 'd' + i;
+    printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
+print();
+
+for (i = 0; i < 8; ++i) {
+    name = 'property' + i;
+    Object.defineProperty(obj, name, {get: function() {return i;}, set: function(v) {}});
+    printProperty(obj[name], Debug.map(obj).findProperty(name));
+}
diff --git a/nashorn/test/script/nosecurity/JDK-8044851.js.EXPECTED b/nashorn/test/script/nosecurity/JDK-8044851.js.EXPECTED
new file mode 100644
index 0000000..4b8ca44
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8044851.js.EXPECTED
@@ -0,0 +1,53 @@
+a0 property0 field 0
+a1 property1 field 1
+a2 property2 field 2
+a3 property3 field 3
+a4 property4 spill 0
+a5 property5 spill 1
+a6 property6 spill 2
+a7 property7 spill 3
+
+b0 property0 field 0
+b1 property1 field 1
+b2 property2 field 2
+b3 property3 field 3
+b4 property4 spill 0
+b5 property5 spill 1
+b6 property6 spill 2
+b7 property7 spill 3
+
+0 property0 spill 4
+1 property1 spill 5
+2 property2 spill 6
+3 property3 spill 7
+4 property4 spill 8
+5 property5 spill 0
+6 property6 spill 1
+7 property7 spill 2
+
+c0 property0 field 0
+c1 property1 field 1
+c2 property2 field 2
+c3 property3 field 3
+c4 property4 spill 0
+c5 property5 spill 1
+c6 property6 spill 2
+c7 property7 spill 3
+
+d0 property0 field 0
+d1 property1 field 1
+d2 property2 field 2
+d3 property3 field 3
+d4 property4 spill 0
+d5 property5 spill 1
+d6 property6 spill 2
+d7 property7 spill 3
+
+0 property0 spill 4
+1 property1 spill 5
+2 property2 spill 6
+3 property3 spill 7
+4 property4 spill 8
+5 property5 spill 0
+6 property6 spill 1
+7 property7 spill 2
diff --git a/nashorn/test/script/nosecurity/JDK-8050964.js b/nashorn/test/script/nosecurity/JDK-8050964.js
new file mode 100644
index 0000000..486948a
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8050964.js
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8050964: OptimisticTypesPersistence.java should use java.util.Date instead of java.sql.Date
+ *
+ * Make sure that nashorn.jar has only 'compact1' dependency.
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// assume that this script is run with "nashorn.jar" System
+// property set to relative path of nashorn.jar from the current
+// directory of test execution.
+
+if (typeof fail != 'function') {
+    fail = print;
+}
+
+var System = java.lang.System;
+var File = java.io.File;
+var nashornJar = new File(System.getProperty("nashorn.jar"));
+if (! nashornJar.isAbsolute()) {
+    nashornJar = new File(".", nashornJar);
+}
+
+var javahome = System.getProperty("java.home");
+var jdepsPath = javahome + "/../bin/jdeps".replaceAll(/\//g, File.separater);
+
+// run jdep on nashorn.jar - only summary but print profile info
+`${jdepsPath} -s -P ${nashornJar.absolutePath}`
+
+// check for "(compact1)" in output from jdep tool
+if (! /(compact1)/.test($OUT)) {
+    fail("non-compact1 dependency: " + $OUT);
+}
diff --git a/nashorn/test/script/nosecurity/JDK-8055034.js b/nashorn/test/script/nosecurity/JDK-8055034.js
new file mode 100644
index 0000000..76f24be
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8055034.js
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8055034: jjs exits interactive mode if exception was thrown when trying to print value of last evaluated expression
+ *
+ * @test
+ * @option -scripting
+ * @run
+ */
+
+// assume that this script is run with "nashorn.jar" System
+// property set to relative or absolute path of nashorn.jar
+
+if (typeof fail != 'function') {
+    fail = print;
+}
+
+var System = java.lang.System;
+var File = java.io.File;
+var javahome = System.getProperty("java.home");
+var nashornJar = new File(System.getProperty("nashorn.jar"));
+if (! nashornJar.isAbsolute()) {
+    nashornJar = new File(".", nashornJar);
+}
+var nashornJarDir = nashornJar.parentFile.absolutePath;
+
+// we want to use nashorn.jar passed and not the one that comes with JRE
+var jjsCmd = javahome + "/../bin/jjs";
+jjsCmd += " -J-Djava.ext.dirs=" + nashornJarDir;
+jjsCmd = jjsCmd.toString().replaceAll(/\//g, File.separater);
+
+$EXEC(jjsCmd, "var x = Object.create(null);\nx;\nprint('PASSED');\nexit(0)");
+
+// $ERR has all interactions including prompts! Just check for error substring.
+var err = $ERR.trim();
+if (! err.contains("TypeError: Cannot get default string value")) {
+    fail("Error stream does not contain expected error message");
+}
+
+// should print "PASSED"
+print($OUT.trim());
+// exit code should be 0
+print("exit code = " + $EXIT);
diff --git a/nashorn/test/script/nosecurity/JDK-8055034.js.EXPECTED b/nashorn/test/script/nosecurity/JDK-8055034.js.EXPECTED
new file mode 100644
index 0000000..416340d
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8055034.js.EXPECTED
@@ -0,0 +1,2 @@
+PASSED
+exit code = 0
diff --git a/nashorn/test/script/nosecurity/JDK-8055107.js b/nashorn/test/script/nosecurity/JDK-8055107.js
new file mode 100644
index 0000000..bcc3cba
--- /dev/null
+++ b/nashorn/test/script/nosecurity/JDK-8055107.js
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * JDK-8055107: Extension directives to turn on callsite profiling, tracing, AST print and other debug features locally
+ *
+ * @test
+ * @option -Dnashorn.debug=true
+ * @option -scripting
+ * @run
+ * @fork
+ */
+
+function runScriptEngine(code) {
+    var imports = new JavaImporter(
+        java.io, java.lang, java.util, javax.script);
+
+    with(imports) {
+        var m = new ScriptEngineManager();
+        // get current System.err
+        var oldErr = System.err;
+        var baos = new ByteArrayOutputStream();
+        var newErr = new PrintStream(baos);
+        try {
+            // set new standard err
+            System.setErr(newErr);
+            var engine = m.getEngineByName("nashorn");
+            engine.eval(code);
+            newErr.flush();
+            return new java.lang.String(baos.toByteArray());
+        } finally {
+            // restore System.err to old value
+            System.setErr(oldErr);
+        }
+    }
+}
+
+// nashorn callsite trace enterexit
+var str = runScriptEngine(<<CODE
+function func() {
+   "nashorn callsite trace enterexit";
+   k();
+}
+
+function k() {
+    var x = "hello";
+}
+
+func();
+CODE);
+
+if (!str.contains(" ENTER ")) {
+    fail("expected 'ENTER' in trace mode output");
+}
+
+if (!str.contains(" EXIT ")) {
+    fail("expected 'EXIT' in trace mode output");
+}
+
+// nashorn callsite trace objects
+var str = runScriptEngine(<<CODE
+"nashorn callsite trace objects";
+function func(x) {
+}
+
+func("hello");
+CODE);
+
+if (!str.contains(" ENTER ")) {
+    fail("expected 'ENTER' in trace mode output");
+}
+
+if (!str.contains(" EXIT ")) {
+    fail("expected 'EXIT' in trace mode output");
+}
+
+if (!str.contains("hello")) {
+    fail("expected argument to be traced in trace objects mode");
+}
+
+// nashorn callsite trace misses
+str = runScriptEngine(<<CODE
+function f() {
+   "nashorn callsite trace misses";
+   k();
+}
+
+function k() {}
+f();
+CODE);
+
+if (!str.contains(" MISS ")) {
+    fail("expected callsite MISS trace messages");
+}
+
+// nashorn print lower ast
+str = runScriptEngine(<<CODE
+function foo() {
+    "nashorn print lower ast";
+    var x = 'hello';
+}
+foo();
+CODE);
+
+if (!str.contains("Lower AST for: 'foo'") ||
+    !str.contains("nashorn print lower ast")) {
+    fail("expected Lower AST to be printed for 'foo'");
+}
+
+// nashorn print ast
+str = runScriptEngine(<<CODE
+function foo() {
+  "nashorn print ast";
+}
+CODE);
+if (!str.contains("[function ") ||
+    !str.contains("nashorn print ast")) {
+    fail("expected AST to be printed");
+}
+
+// nashorn print symbols
+str = runScriptEngine(<<CODE
+function bar(a) {
+    "nashorn print symbols";
+    if (a) print(a);
+}
+
+bar();
+CODE)
+
+if (!str.contains("[BLOCK in 'Function bar']")) {
+    fail("expected symbols to be printed for 'bar'");
+}
+
+// nashorn print parse
+str = runScriptEngine(<<CODE
+"nashorn print parse";
+
+function func() {}
+CODE);
+
+if (!str.contains("function func") ||
+    !str.contains("nashorn print parse")) {
+    fail("expected nashorn print parse output");
+}
+
+// nashorn print lower parse
+str = runScriptEngine(<<CODE
+"nashorn print lower parse";
+
+function func() {}
+
+func()
+CODE);
+
+if (!str.contains("function {U%}func") ||
+    !str.contains("nashorn print lower parse")) {
+    fail("expected nashorn print lower parse output");
+}
diff --git a/nashorn/test/script/nosecurity/debuggersupportapi.js b/nashorn/test/script/nosecurity/debuggersupportapi.js
index f2fa101..db4a69a 100644
--- a/nashorn/test/script/nosecurity/debuggersupportapi.js
+++ b/nashorn/test/script/nosecurity/debuggersupportapi.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/nosecurity/nosecurity.js b/nashorn/test/script/nosecurity/nosecurity.js
index 688af8c..b35171b 100644
--- a/nashorn/test/script/nosecurity/nosecurity.js
+++ b/nashorn/test/script/nosecurity/nosecurity.js
@@ -1,28 +1,28 @@
 /*
  * Copyright (c) 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.
  */
 
 /**
- * 8043443: Test framework changes to run script tests without security manager 
+ * 8043443: Test framework changes to run script tests without security manager
  * @test
  * @run
  */
diff --git a/nashorn/test/script/sandbox/JDK-8031106.js b/nashorn/test/script/sandbox/JDK-8031106.js
index d5d83f6..26d15a2 100644
--- a/nashorn/test/script/sandbox/JDK-8031106.js
+++ b/nashorn/test/script/sandbox/JDK-8031106.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/NASHORN-525.js b/nashorn/test/script/sandbox/NASHORN-525.js
index c6a0d4f..a099b44 100644
--- a/nashorn/test/script/sandbox/NASHORN-525.js
+++ b/nashorn/test/script/sandbox/NASHORN-525.js
@@ -1,28 +1,28 @@
 /*
  * 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.
  */
 
 /**
- * NASHORN-525 : nashorn misses security access checks 
+ * NASHORN-525 : nashorn misses security access checks
  *
  * @test
  * @run
diff --git a/nashorn/test/script/sandbox/arrayclass.js b/nashorn/test/script/sandbox/arrayclass.js
index c29c86b..69996dc 100644
--- a/nashorn/test/script/sandbox/arrayclass.js
+++ b/nashorn/test/script/sandbox/arrayclass.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/classbind.js b/nashorn/test/script/sandbox/classbind.js
index 2dabb3e..05e1292 100644
--- a/nashorn/test/script/sandbox/classbind.js
+++ b/nashorn/test/script/sandbox/classbind.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/classloader.js b/nashorn/test/script/sandbox/classloader.js
index 9de1a5c..36cf464 100644
--- a/nashorn/test/script/sandbox/classloader.js
+++ b/nashorn/test/script/sandbox/classloader.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/doprivileged.js b/nashorn/test/script/sandbox/doprivileged.js
index d901347..5b08361 100644
--- a/nashorn/test/script/sandbox/doprivileged.js
+++ b/nashorn/test/script/sandbox/doprivileged.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -48,11 +48,11 @@
             check(e);
         }
 
-	try {
-	    var prop = java.lang.System.getProperty("user.dir");
+    try {
+        var prop = java.lang.System.getProperty("user.dir");
             fail("can get user.dir " + prop);
-	} catch(e) {
+    } catch(e) {
             print(e);
-	}
+    }
     }
 });
diff --git a/nashorn/test/script/sandbox/engine.js b/nashorn/test/script/sandbox/engine.js
index e1d87c7..77aa36e 100644
--- a/nashorn/test/script/sandbox/engine.js
+++ b/nashorn/test/script/sandbox/engine.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/env.js b/nashorn/test/script/sandbox/env.js
index df80e6f..5ef40a2 100644
--- a/nashorn/test/script/sandbox/env.js
+++ b/nashorn/test/script/sandbox/env.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/exec.js b/nashorn/test/script/sandbox/exec.js
index 86d70b3..0f32938 100644
--- a/nashorn/test/script/sandbox/exec.js
+++ b/nashorn/test/script/sandbox/exec.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/exit.js b/nashorn/test/script/sandbox/exit.js
index d77744f..b807c97 100644
--- a/nashorn/test/script/sandbox/exit.js
+++ b/nashorn/test/script/sandbox/exit.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/file.js b/nashorn/test/script/sandbox/file.js
index dce3afd..3aaa897 100644
--- a/nashorn/test/script/sandbox/file.js
+++ b/nashorn/test/script/sandbox/file.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/interfaceimpl.js b/nashorn/test/script/sandbox/interfaceimpl.js
index b2ee86b..0745318 100644
--- a/nashorn/test/script/sandbox/interfaceimpl.js
+++ b/nashorn/test/script/sandbox/interfaceimpl.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/javaextend.js b/nashorn/test/script/sandbox/javaextend.js
index 60eab74..a2d1833 100644
--- a/nashorn/test/script/sandbox/javaextend.js
+++ b/nashorn/test/script/sandbox/javaextend.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -30,7 +30,7 @@
   return Java.type("jdk.nashorn.test.models." + n)
 }
 
-// Can't extend a final class  
+// Can't extend a final class
 try {
     Java.extend(model("FinalClass"))
 } catch(e) {
diff --git a/nashorn/test/script/sandbox/jsadapter.js b/nashorn/test/script/sandbox/jsadapter.js
index 32bedc8..494b900 100644
--- a/nashorn/test/script/sandbox/jsadapter.js
+++ b/nashorn/test/script/sandbox/jsadapter.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/loadLibrary.js b/nashorn/test/script/sandbox/loadLibrary.js
index 1e5151f..e693d22 100644
--- a/nashorn/test/script/sandbox/loadLibrary.js
+++ b/nashorn/test/script/sandbox/loadLibrary.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/loadcompat.js b/nashorn/test/script/sandbox/loadcompat.js
index f0338df..0dfa944 100644
--- a/nashorn/test/script/sandbox/loadcompat.js
+++ b/nashorn/test/script/sandbox/loadcompat.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/nashorninternals.js b/nashorn/test/script/sandbox/nashorninternals.js
index c68b6c8..d68f3f3 100644
--- a/nashorn/test/script/sandbox/nashorninternals.js
+++ b/nashorn/test/script/sandbox/nashorninternals.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 
 /**
- * Test to check that nashorn "internal" classes in codegen, parser, ir 
+ * Test to check that nashorn "internal" classes in codegen, parser, ir
  * packages cannot * be accessed from sandbox scripts.
  *
  * @test
diff --git a/nashorn/test/script/sandbox/net.js b/nashorn/test/script/sandbox/net.js
index 37aaf57..c7fd8d0 100644
--- a/nashorn/test/script/sandbox/net.js
+++ b/nashorn/test/script/sandbox/net.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/property.js b/nashorn/test/script/sandbox/property.js
index 685cf32..8aeb499 100644
--- a/nashorn/test/script/sandbox/property.js
+++ b/nashorn/test/script/sandbox/property.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/reflection.js b/nashorn/test/script/sandbox/reflection.js
index 4fdc58f..225f444 100644
--- a/nashorn/test/script/sandbox/reflection.js
+++ b/nashorn/test/script/sandbox/reflection.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -38,5 +38,5 @@
 try {
     var cl = java.lang.Class.class;
 } catch(e) {
-    check(e); 
+    check(e);
 }
diff --git a/nashorn/test/script/sandbox/runnable.js b/nashorn/test/script/sandbox/runnable.js
index 75f533b..02c8b4a 100644
--- a/nashorn/test/script/sandbox/runnable.js
+++ b/nashorn/test/script/sandbox/runnable.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/sandbox/unsafe.js b/nashorn/test/script/sandbox/unsafe.js
index 6b3f43a..57f9d48 100644
--- a/nashorn/test/script/sandbox/unsafe.js
+++ b/nashorn/test/script/sandbox/unsafe.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -43,7 +43,7 @@
 }
 
 try {
-    var unsafe = Java.type("sun.misc.Unsafe"); 
+    var unsafe = Java.type("sun.misc.Unsafe");
     fail("No SecurityException for Java.type sun.misc.Unsafe");
 } catch (e) {
     check(e);
diff --git a/nashorn/test/script/test262.js b/nashorn/test/script/test262.js
index a03e612..8ca528c 100644
--- a/nashorn/test/script/test262.js
+++ b/nashorn/test/script/test262.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/test262_single.js b/nashorn/test/script/test262_single.js
index 2cc905e..86d0b42 100644
--- a/nashorn/test/script/test262_single.js
+++ b/nashorn/test/script/test262_single.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/JDK-8006424.js b/nashorn/test/script/trusted/JDK-8006424.js
index 88516e1..fa0dabd 100644
--- a/nashorn/test/script/trusted/JDK-8006424.js
+++ b/nashorn/test/script/trusted/JDK-8006424.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/JDK-8006529.js b/nashorn/test/script/trusted/JDK-8006529.js
index 3567c33..75c4d7c 100644
--- a/nashorn/test/script/trusted/JDK-8006529.js
+++ b/nashorn/test/script/trusted/JDK-8006529.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -33,16 +33,18 @@
  * This test script depends on nashorn Compiler internals. It uses reflection
  * to get access to private field and many public methods of Compiler and
  * FunctionNode classes. Note that this is trusted code and access to such
- * internal package classes and methods is okay. But, if you modify any 
+ * internal package classes and methods is okay. But, if you modify any
  * Compiler or FunctionNode class, you may have to revisit this script.
  * We cannot use direct Java class (via dynalink bean linker) to Compiler
  * and FunctionNode because of package-access check and so reflective calls.
  */
 
-var forName = java.lang.Class["forName(String)"];
+var forName             = java.lang.Class["forName(String)"];
 var Parser              = forName("jdk.nashorn.internal.parser.Parser").static
 var Compiler            = forName("jdk.nashorn.internal.codegen.Compiler").static
+var CompilationPhases   = forName("jdk.nashorn.internal.codegen.Compiler$CompilationPhases").static;
 var Context             = forName("jdk.nashorn.internal.runtime.Context").static
+var CodeInstaller       = forName("jdk.nashorn.internal.runtime.CodeInstaller").static
 var ScriptEnvironment   = forName("jdk.nashorn.internal.runtime.ScriptEnvironment").static
 var Source              = forName("jdk.nashorn.internal.runtime.Source").static
 var FunctionNode        = forName("jdk.nashorn.internal.ir.FunctionNode").static
@@ -54,20 +56,23 @@
 var ThrowErrorManager   = forName("jdk.nashorn.internal.runtime.Context$ThrowErrorManager").static
 var ErrorManager        = forName("jdk.nashorn.internal.runtime.ErrorManager").static
 var Debug               = forName("jdk.nashorn.internal.runtime.Debug").static
+var String              = forName("java.lang.String").static
+var boolean             = Java.type("boolean");
 
 var parseMethod = Parser.class.getMethod("parse");
-var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class);
+var compileMethod = Compiler.class.getMethod("compile", FunctionNode.class, CompilationPhases.class);
 var getBodyMethod = FunctionNode.class.getMethod("getBody");
 var getStatementsMethod = Block.class.getMethod("getStatements");
 var getInitMethod = VarNode.class.getMethod("getInit");
 var getExpressionMethod = ExpressionStatement.class.getMethod("getExpression")
-var rhsMethod = UnaryNode.class.getMethod("rhs")
+var rhsMethod = UnaryNode.class.getMethod("getExpression")
 var lhsMethod = BinaryNode.class.getMethod("lhs")
 var binaryRhsMethod = BinaryNode.class.getMethod("rhs")
 var debugIdMethod = Debug.class.getMethod("id", java.lang.Object.class)
+var compilePhases = CompilationPhases.class.getField("COMPILE_UPTO_BYTECODE").get(null);
 
 // These are method names of methods in FunctionNode class
-var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'needsSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
+var allAssertionList = ['isVarArg', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'usesSelfSymbol', 'isSplit', 'hasEval', 'allVarsInScope', 'isStrict']
 
 // corresponding Method objects of FunctionNode class
 var functionNodeMethods = {};
@@ -103,8 +108,8 @@
         return findFunction(rhsMethod.invoke(node))
     } else if(node instanceof BinaryNode) {
         return findFunction(lhsMethod.invoke(node)) || findFunction(binaryRhsMethod.invoke(node))
-	} else if(node instanceof ExpressionStatement) {
-		return findFunction(getExpressionMethod.invoke(node))
+    } else if(node instanceof ExpressionStatement) {
+        return findFunction(getExpressionMethod.invoke(node))
     } else if(node instanceof FunctionNode) {
         return node
     }
@@ -115,22 +120,23 @@
 
 var sourceForMethod = Source.class.getMethod("sourceFor", java.lang.String.class, java.lang.String.class)
 var ParserConstructor = Parser.class.getConstructor(ScriptEnvironment.class, Source.class, ErrorManager.class)
-var CompilerConstructor = Compiler.class.getConstructor(ScriptEnvironment.class)
+var CompilerConstructor = Compiler.class.getConstructor(Context.class, ScriptEnvironment.class, CodeInstaller.class, Source.class, boolean.class);
 
-// compile(script) -- compiles a script specified as a string with its 
-// source code, returns a jdk.nashorn.internal.ir.FunctionNode object 
+// compile(script) -- compiles a script specified as a string with its
+// source code, returns a jdk.nashorn.internal.ir.FunctionNode object
 // representing it.
-function compile(source) {
+function compile(source, phases) {
     var source = sourceForMethod.invoke(null, "<no name>", source);
 
-    var env = getEnvMethod.invoke(getContextMethod.invoke(null))
+    var ctxt = getContextMethod.invoke(null);
+    var env = getEnvMethod.invoke(ctxt);
 
     var parser   = ParserConstructor.newInstance(env, source, ThrowErrorManager.class.newInstance());
     var func     = parseMethod.invoke(parser);
 
-    var compiler = CompilerConstructor.newInstance(env);
+    var compiler = CompilerConstructor.newInstance(ctxt, env, null, source, false);
 
-    return compileMethod.invoke(compiler, func);
+    return compileMethod.invoke(compiler, func, phases);
 };
 
 var allAssertions = (function() {
@@ -166,8 +172,8 @@
 // assertions are true in the first function in the given script; "script"
 // is a string with the source text of the script.
 function testFirstFn(script) {
-    arguments[0] = getFirstFunction(compile(script))
-    test.apply(null, arguments)
+    arguments[0] = getFirstFunction(compile(script, compilePhases));
+    test.apply(null, arguments);
 }
 
 // ---------------------------------- ACTUAL TESTS START HERE --------------
@@ -197,13 +203,13 @@
 // A function defining "arguments" as a local variable will be vararg.
 testFirstFn("function f() { var arguments; arguments; }", 'isVarArg', 'needsCallee')
 
-// A self-referencing function defined as a statement doesn't need a self 
+// A self-referencing function defined as a statement doesn't need a self
 // symbol, as it'll rather obtain itself from the parent scope.
 testFirstFn("function f() { f() }", 'needsCallee', 'needsParentScope')
 
 // A self-referencing function defined as an expression needs a self symbol,
 // as it can't obtain itself from the parent scope.
-testFirstFn("(function f() { f() })", 'needsCallee', 'needsSelfSymbol')
+testFirstFn("(function f() { f() })", 'needsCallee', 'usesSelfSymbol')
 
 // A child function accessing parent's variable triggers the need for scope
 // in parent
@@ -217,7 +223,7 @@
 // scope in parent
 testFirstFn("(function f() { function g() { x } })", 'needsParentScope', 'needsCallee')
 
-// A child function redefining a local variable from its parent should not 
+// A child function redefining a local variable from its parent should not
 // affect the parent function in any way
 testFirstFn("(function f() { var x; function g() { var x; x } })")
 
@@ -239,14 +245,15 @@
 
 // Using "eval" triggers pretty much everything. The function even needs to be
 // vararg, 'cause we don't know if eval will be using "arguments".
-testFirstFn("(function f() { eval() })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
+testFirstFn("(function f() { eval() })", 'usesSelfSymbol', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'hasEval', 'isVarArg', 'allVarsInScope')
 
 // Nested function using "eval" is almost the same as parent function using
 // eval, but at least the parent doesn't have to be vararg.
-testFirstFn("(function f() { function g() { eval() } })", 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
+testFirstFn("(function f() { function g() { eval() } })", 'usesSelfSymbol', 'needsParentScope', 'needsCallee', 'hasScopeBlock', 'allVarsInScope')
 
 // Function with 250 named parameters is ordinary
 testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250) { p250 = p249 }")
 
 // Function with 251 named parameters is variable arguments
-testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250, p251) { p250 = p251 }", 'isVarArg')
+// NOTE: hasScopeBlock should be optimized away. Implementation of JDK-8038942 should take care of it.
+testFirstFn("function f(p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p13, p14, p15, p16, p17, p18, p19, p20, p21, p22, p23, p24, p25, p26, p27, p28, p29, p30, p31, p32, p33, p34, p35, p36, p37, p38, p39, p40, p41, p42, p43, p44, p45, p46, p47, p48, p49, p50, p51, p52, p53, p54, p55, p56, p57, p58, p59, p60, p61, p62, p63, p64, p65, p66, p67, p68, p69, p70, p71, p72, p73, p74, p75, p76, p77, p78, p79, p80, p81, p82, p83, p84, p85, p86, p87, p88, p89, p90, p91, p92, p93, p94, p95, p96, p97, p98, p99, p100, p101, p102, p103, p104, p105, p106, p107, p108, p109, p110, p111, p112, p113, p114, p115, p116, p117, p118, p119, p120, p121, p122, p123, p124, p125, p126, p127, p128, p129, p130, p131, p132, p133, p134, p135, p136, p137, p138, p139, p140, p141, p142, p143, p144, p145, p146, p147, p148, p149, p150, p151, p152, p153, p154, p155, p156, p157, p158, p159, p160, p161, p162, p163, p164, p165, p166, p167, p168, p169, p170, p171, p172, p173, p174, p175, p176, p177, p178, p179, p180, p181, p182, p183, p184, p185, p186, p187, p188, p189, p190, p191, p192, p193, p194, p195, p196, p197, p198, p199, p200, p201, p202, p203, p204, p205, p206, p207, p208, p209, p210, p211, p212, p213, p214, p215, p216, p217, p218, p219, p220, p221, p222, p223, p224, p225, p226, p227, p228, p229, p230, p231, p232, p233, p234, p235, p236, p237, p238, p239, p240, p241, p242, p243, p244, p245, p246, p247, p248, p249, p250, p251) { p250 = p251 }", 'isVarArg', 'hasScopeBlock')
diff --git a/nashorn/test/script/trusted/JDK-8008305.js b/nashorn/test/script/trusted/JDK-8008305.js
index d57b520..d75561b 100644
--- a/nashorn/test/script/trusted/JDK-8008305.js
+++ b/nashorn/test/script/trusted/JDK-8008305.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/JDK-8008305_subtest.js b/nashorn/test/script/trusted/JDK-8008305_subtest.js
index 2485f39..b88ed3c 100644
--- a/nashorn/test/script/trusted/JDK-8008305_subtest.js
+++ b/nashorn/test/script/trusted/JDK-8008305_subtest.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/JDK-8020809.js b/nashorn/test/script/trusted/JDK-8020809.js
index 6e0296c..9052ff0 100644
--- a/nashorn/test/script/trusted/JDK-8020809.js
+++ b/nashorn/test/script/trusted/JDK-8020809.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * JDK-8020809: Java adapter should not allow overriding of caller sensitive methods
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/trusted/JDK-8021129.js b/nashorn/test/script/trusted/JDK-8021129.js
index 93bf12a..47ad5d4 100644
--- a/nashorn/test/script/trusted/JDK-8021129.js
+++ b/nashorn/test/script/trusted/JDK-8021129.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -25,7 +25,7 @@
  * JDK-8021129: Test prevention of access to members of restricted classes.
  * Note that even though the script runs as trusted, we still don't allow
  * access to non-public portions of restricted classes.
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/trusted/JDK-8021189.js b/nashorn/test/script/trusted/JDK-8021189.js
index 528a21b..c4c93cb 100644
--- a/nashorn/test/script/trusted/JDK-8021189.js
+++ b/nashorn/test/script/trusted/JDK-8021189.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -23,7 +23,7 @@
 
 /**
  * JDK-8021189: Prevent access to constructors of restricted classes
- * 
+ *
  * @test
  * @run
  */
diff --git a/nashorn/test/script/trusted/JDK-8025629.js b/nashorn/test/script/trusted/JDK-8025629.js
index 7dda846..609cfe8 100644
--- a/nashorn/test/script/trusted/JDK-8025629.js
+++ b/nashorn/test/script/trusted/JDK-8025629.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/JDK-8032060.js b/nashorn/test/script/trusted/JDK-8032060.js
index 8cb350c..4a3fe24 100644
--- a/nashorn/test/script/trusted/JDK-8032060.js
+++ b/nashorn/test/script/trusted/JDK-8032060.js
@@ -1,21 +1,21 @@
 /*
  * Copyright (c) 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.
diff --git a/nashorn/test/script/trusted/NASHORN-638.js b/nashorn/test/script/trusted/NASHORN-638.js
index 1ff789a..0bd5d41 100644
--- a/nashorn/test/script/trusted/NASHORN-638.js
+++ b/nashorn/test/script/trusted/NASHORN-638.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/NASHORN-653.js b/nashorn/test/script/trusted/NASHORN-653.js
index 14a2cbc..b6d9a54 100644
--- a/nashorn/test/script/trusted/NASHORN-653.js
+++ b/nashorn/test/script/trusted/NASHORN-653.js
@@ -1,21 +1,21 @@
 /*
  * 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.
@@ -35,37 +35,37 @@
                  \
 function b() {   \
     while (x) {      \
-	return true; \
+    return true; \
     }                \
 }                    \
                      \
 function c() {       \
     while (true) {   \
-	return true; \
+    return true; \
     }                \
  }                   \
                      \
 function d() {       \
     do {             \
-	return true; \
+    return true; \
     } while (x);     \
 } \
 \
 function f() {       \
     for (;;) {       \
-	return true; \
+    return true; \
     } \
 } \
 \
 function e() { \
     for (;;) { \
-	return true; \
+    return true; \
     } \
 } \
 \
 function g() { \
     for(;;) { \
-	print('goes on and on and on ... '); \
+    print('goes on and on and on ... '); \
     } \
     print('x'); \
 } \
diff --git a/nashorn/test/script/trusted/classfilter.js b/nashorn/test/script/trusted/classfilter.js
new file mode 100644
index 0000000..a50e4a2
--- /dev/null
+++ b/nashorn/test/script/trusted/classfilter.js
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * ClassFilter to filter out java classes in a script engine.
+ *
+ * @test
+ * @run
+ */
+
+var NashornScriptEngineFactory = Java.type("jdk.nashorn.api.scripting.NashornScriptEngineFactory");
+
+var fac = new NashornScriptEngineFactory();
+// allow only "java.*" classes to be accessed
+var e = fac.getScriptEngine(
+    function(name) name.startsWith("java."));
+
+function evalIt(str) {
+    print(str + " evalutes to " + e.eval(str));
+}
+
+function evalExpectError(str) {
+    try {
+        print(e.eval(str));
+        fail("expected error for: " + str);
+    } catch(exp) {
+        print(str + " throws " + exp);
+    }
+}
+
+evalIt("typeof javax.script.ScriptContext");
+evalIt("typeof javax.script.ScriptEngine");
+evalIt("typeof java.util.Vector");
+evalIt("typeof java.util.Map");
+evalIt("typeof java.util.HashMap");
+// should be able to call methods, create objects of java.* classes
+evalIt("var m = new java.util.HashMap(); m.put('foo', 42); m");
+evalIt("java.lang.System.out.println");
+evalIt("java.lang.System.exit");
+
+evalExpectError("new javax.script.SimpleBindings");
+evalExpectError("Java.type('javax.script.ScriptContext')");
+evalExpectError("java.lang.Class.forName('javax.script.ScriptContext')");
+
+try {
+    fac["getScriptEngine(ClassFilter)"](null);
+    fail("should have thrown NPE");
+} catch (e) {
+    if (! (e instanceof java.lang.NullPointerException)) {
+        fail("NPE expected, got " + e);
+    }
+}
diff --git a/nashorn/test/script/trusted/classfilter.js.EXPECTED b/nashorn/test/script/trusted/classfilter.js.EXPECTED
new file mode 100644
index 0000000..43d6303
--- /dev/null
+++ b/nashorn/test/script/trusted/classfilter.js.EXPECTED
@@ -0,0 +1,11 @@
+typeof javax.script.ScriptContext evalutes to object
+typeof javax.script.ScriptEngine evalutes to object
+typeof java.util.Vector evalutes to function
+typeof java.util.Map evalutes to function
+typeof java.util.HashMap evalutes to function
+var m = new java.util.HashMap(); m.put('foo', 42); m evalutes to {foo=42}
+java.lang.System.out.println evalutes to [jdk.internal.dynalink.beans.OverloadedDynamicMethod java.io.PrintStream.println]
+java.lang.System.exit evalutes to [jdk.internal.dynalink.beans.SimpleDynamicMethod void java.lang.System.exit(int)]
+new javax.script.SimpleBindings throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.SimpleBindings
+Java.type('javax.script.ScriptContext') throws java.lang.RuntimeException: java.lang.ClassNotFoundException: javax.script.ScriptContext
+java.lang.Class.forName('javax.script.ScriptContext') throws javax.script.ScriptException: TypeError: Java reflection not supported when class filter is present in <eval> at line number 1
diff --git a/nashorn/test/script/trusted/classfilter_extends.js b/nashorn/test/script/trusted/classfilter_extends.js
new file mode 100644
index 0000000..e721b3a
--- /dev/null
+++ b/nashorn/test/script/trusted/classfilter_extends.js
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8036987
+ * @run
+ */
+
+var factory = Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory')
+var engine  = new factory().getScriptEngine(function(str){
+    return str.indexOf('java.lang.Class') != -1
+            || str == 'java.lang.System'
+            || str.indexOf('java.util') != -1;
+})
+
+function tryEval (str) {
+        try {
+            print(eval(str))
+            print(engine.eval(str))
+        } catch (exc) {
+            print(exc.message)
+        }
+}
+
+tryEval("Java.type('java.util.ArrayList')")
+tryEval("Java.type('java.lang.String')")
+tryEval("java.util.ArrayList")
+tryEval("java.lang.String")
+tryEval("Java.extend(java.util.ArrayList, {})")
+tryEval("Java.extend(java.io.File, {})")
+tryEval("new java.lang.NullPointerException();")
+tryEval("try { java.lang.System.load(null) } catch (e) { e }")
diff --git a/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED b/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED
new file mode 100644
index 0000000..e0cf856
--- /dev/null
+++ b/nashorn/test/script/trusted/classfilter_extends.js.EXPECTED
@@ -0,0 +1,16 @@
+[JavaClass java.util.ArrayList]
+[JavaClass java.util.ArrayList]
+[JavaClass java.lang.String]
+java.lang.ClassNotFoundException: java.lang.String
+[JavaClass java.util.ArrayList]
+[JavaClass java.util.ArrayList]
+[JavaClass java.lang.String]
+[JavaPackage java.lang.String]
+[JavaClass jdk.nashorn.javaadapters.java.util.ArrayList]
+[JavaClass jdk.nashorn.javaadapters.java.util.ArrayList]
+[JavaClass jdk.nashorn.javaadapters.java.io.File]
+TypeError: Java.extend needs Java types as its arguments. in <eval> at line number 1
+java.lang.NullPointerException
+java.lang.ClassNotFoundException: java.lang.NullPointerException
+java.lang.NullPointerException: library can't be null
+java.lang.NullPointerException: library can't be null
diff --git a/nashorn/test/script/trusted/classfilter_mozilla_compat.js b/nashorn/test/script/trusted/classfilter_mozilla_compat.js
new file mode 100644
index 0000000..cb05a3d
--- /dev/null
+++ b/nashorn/test/script/trusted/classfilter_mozilla_compat.js
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * @test
+ * @bug 8036987
+ * @run
+ */
+
+var factory = Java.type('jdk.nashorn.api.scripting.NashornScriptEngineFactory')
+var engine  = new factory().getScriptEngine(function(str){
+    return str.indexOf('java.util') != -1;
+})
+
+load("nashorn:mozilla_compat.js");
+engine.eval("load('nashorn:mozilla_compat.js');")
+
+function tryEval (str) {
+        try {
+            print(eval(str))
+            print(engine.eval(str))
+        } catch (exc) {
+            print(exc.message)
+        }
+}
+
+tryEval("new JavaAdapter(javax.script.ScriptContext){}.class")
+tryEval("new JavaAdapter(java.util.ArrayList){}.class")
+tryEval("importClass(java.lang.Integer); Integer")
+tryEval("importClass(java.util.HashSet); HashSet")
+tryEval("importPackage(java.lang); Integer")
+tryEval("importPackage(java.util); HashMap")
diff --git a/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED b/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
new file mode 100644
index 0000000..9481e98
--- /dev/null
+++ b/nashorn/test/script/trusted/classfilter_mozilla_compat.js.EXPECTED
@@ -0,0 +1,12 @@
+class javax.script.ScriptContext$$NashornJavaAdapter
+TypeError: Java.extend needs at least one type argument. in nashorn:mozilla_compat.js at line number 39
+class jdk.nashorn.javaadapters.java.util.ArrayList
+class jdk.nashorn.javaadapters.java.util.ArrayList
+[JavaClass java.lang.Integer]
+TypeError: [object JavaPackage] is not a Java class in nashorn:mozilla_compat.js at line number 373 at column number 16
+[JavaClass java.util.HashSet]
+[JavaClass java.util.HashSet]
+[JavaClass java.lang.Integer]
+ReferenceError: "Integer" is not defined in nashorn:mozilla_compat.js at line number 67
+[JavaClass java.util.HashMap]
+[JavaClass java.util.HashMap]
diff --git a/nashorn/test/script/trusted/event_queue.js b/nashorn/test/script/trusted/event_queue.js
new file mode 100644
index 0000000..feecc20
--- /dev/null
+++ b/nashorn/test/script/trusted/event_queue.js
@@ -0,0 +1,123 @@
+/*
+ * 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.
+ */
+
+/**
+ * Debug.eventqueue test - instead of screen scraping, test the concept of asking Debug for
+ * an event log of favourable events.
+ *
+ * @test
+ * @fork
+ * @option -Dnashorn.debug=true
+ * @option --log=recompile:quiet
+ * @option --optimistic-types=true
+ */
+
+print(Debug);
+print();
+
+var forName       = java.lang.Class["forName(String)"];
+var RuntimeEvent  = forName("jdk.nashorn.internal.runtime.events.RuntimeEvent").static;
+var getValue      = RuntimeEvent.class.getMethod("getValue");
+var getValueClass = RuntimeEvent.class.getMethod("getValueClass");
+
+print(RuntimeEvent);
+
+var RewriteException = forName("jdk.nashorn.internal.runtime.RewriteException").static;
+var getReturnType    = RewriteException.class.getMethod("getReturnType");
+
+print(RewriteException);
+
+var a = [1.1, 2.2];
+function f() {
+    var sum = 2;
+    for (var i = 0; i < a.length; i++) {
+    sum *= a[i];
+    }
+    return sum;
+}
+
+function g() {
+    var diff = 17;
+    for (var i = 0; i < a.length; i++) {
+    diff -= a[i];
+    }
+    return diff;
+}
+
+//kill anything that may already be in the event queue from earlier debug runs
+Debug.clearRuntimeEvents();
+
+print();
+print(f());
+print(g());
+
+print();
+events = Debug.getRuntimeEvents();
+print("Done with " + events.length + " in the event queue");
+//make sure we got runtime events
+print("events = " + (events.toString().indexOf("RuntimeEvent") != -1));
+print("events.length = " + events.length);
+
+var lastInLoop = undefined;
+for (var i = 0; i < events.length; i++) {
+    var e = events[i];
+    print("event #" + i);
+    print("\tevent class=" + e.getClass());
+    print("\tvalueClass in event=" + getValueClass.invoke(e));
+    var v = getValue.invoke(e);
+    print("\tclass of value=" + v.getClass());
+    print("\treturn type=" + getReturnType.invoke(v));
+    lastInLoop = events[i];
+}
+
+print();
+print("in loop last class = " + lastInLoop.getClass());
+print("in loop last value class = " + getValueClass.invoke(lastInLoop));
+var rexInLoop = getValue.invoke(lastInLoop);
+print("in loop rex class = " + rexInLoop.getClass());
+print("in loop rex return type = " + getReturnType.invoke(rexInLoop));
+
+//try last runtime events
+var last = Debug.getLastRuntimeEvent();
+//the code after the loop creates additional rewrite exceptions
+print();
+print(last !== lastInLoop);
+print();
+
+print("last class = " + last.getClass());
+print("last value class = " + getValueClass.invoke(last));
+var rex = getValue.invoke(last);
+print("rex class = " + rex.getClass());
+print("rex return type = " + getReturnType.invoke(rex));
+
+//try the capacity setter
+print();
+print(Debug.getEventQueueCapacity());
+Debug.setEventQueueCapacity(2048);
+print(Debug.getEventQueueCapacity());
+
+//try clear events
+print();
+Debug.clearRuntimeEvents();
+print(Debug.getRuntimeEvents().length);
+
diff --git a/nashorn/test/script/trusted/event_queue.js.EXPECTED b/nashorn/test/script/trusted/event_queue.js.EXPECTED
new file mode 100644
index 0000000..d4eb729
--- /dev/null
+++ b/nashorn/test/script/trusted/event_queue.js.EXPECTED
@@ -0,0 +1,38 @@
+[object Debug]
+
+[JavaClass jdk.nashorn.internal.runtime.events.RuntimeEvent]
+[JavaClass jdk.nashorn.internal.runtime.RewriteException]
+
+4.840000000000001
+13.7
+
+Done with 2 in the event queue
+events = true
+events.length = 2
+event #0
+	event class=class jdk.nashorn.internal.runtime.events.RecompilationEvent
+	valueClass in event=class jdk.nashorn.internal.runtime.RewriteException
+	class of value=class jdk.nashorn.internal.runtime.RewriteException
+	return type=double
+event #1
+	event class=class jdk.nashorn.internal.runtime.events.RecompilationEvent
+	valueClass in event=class jdk.nashorn.internal.runtime.RewriteException
+	class of value=class jdk.nashorn.internal.runtime.RewriteException
+	return type=double
+
+in loop last class = class jdk.nashorn.internal.runtime.events.RecompilationEvent
+in loop last value class = class jdk.nashorn.internal.runtime.RewriteException
+in loop rex class = class jdk.nashorn.internal.runtime.RewriteException
+in loop rex return type = double
+
+true
+
+last class = class jdk.nashorn.internal.runtime.events.RecompilationEvent
+last value class = class jdk.nashorn.internal.runtime.RewriteException
+rex class = class jdk.nashorn.internal.runtime.RewriteException
+rex return type = object
+
+1024
+2048
+
+0
diff --git a/nashorn/test/script/trusted/getenv.js b/nashorn/test/script/trusted/getenv.js
index 9fb3a96..29df8ba 100644
--- a/nashorn/test/script/trusted/getenv.js
+++ b/nashorn/test/script/trusted/getenv.js
@@ -1,21 +1,21 @@
 /*
  * 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.
diff --git a/nashorn/test/script/trusted/optimistic_recompilation.js b/nashorn/test/script/trusted/optimistic_recompilation.js
new file mode 100644
index 0000000..9c9a9c7
--- /dev/null
+++ b/nashorn/test/script/trusted/optimistic_recompilation.js
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 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.
+ */
+
+/**
+ * Ask Debug for an event log of favourable events instead of using --log flags printing to screen
+ * @test
+ * @bug 8037086,8038398
+ * @fork
+ * @option -Dnashorn.debug=true
+ * @option --log=recompile:quiet
+ * @option --optimistic-types=true
+ */
+
+var forName       = java.lang.Class["forName(String)"];
+var RuntimeEvent  = forName("jdk.nashorn.internal.runtime.events.RuntimeEvent").static;
+var getValue      = RuntimeEvent.class.getMethod("getValue");
+var RewriteException = forName("jdk.nashorn.internal.runtime.RewriteException").static;
+var getReturnType    = RewriteException.class.getMethod("getReturnType");
+var RecompilationEvent = forName("jdk.nashorn.internal.runtime.events.RecompilationEvent").static;
+var getReturnValue     = RecompilationEvent.class.getMethod("getReturnValue");
+var setReturnTypeAndValue = [];
+var expectedValues = [];
+
+function checkExpectedRecompilation(f, expectedValues, testCase) {
+    Debug.clearRuntimeEvents();
+    print(f());
+    events = Debug.getRuntimeEvents();
+    //make sure we got runtime events
+    print("events = " + (events.toString().indexOf("RuntimeEvent") != -1));
+    if (events.length ==  expectedValues.length) {
+        for (var i in events) {
+            var e = events[i];
+            var returnValue = getReturnValue.invoke(e);
+            if (typeof returnValue != 'undefined') {
+            setReturnTypeAndValue[i] = [getReturnType.invoke(getValue.invoke(e)), returnValue];
+            } else {
+                returnValue = "undefined";
+                setReturnTypeAndValue[i] = [getReturnType.invoke(getValue.invoke(e)), returnValue];
+            }
+            if (!setReturnTypeAndValue[i].toString().equals(expectedValues[i].toString())) {
+                fail("The return values are not as expected. Expected value: " + expectedValues[i] + " and got: " + setReturnTypeAndValue[i] + " in test case: " + f);
+            }
+        }
+    } else {
+        fail("Number of Deoptimizing recompilation is not correct, expected: " + expectedValues.length + " and found: " + events.length + " in test case: " + f);
+    }
+}
+
+checkExpectedRecompilation(function divisionByZeroTest() {var x = { a: 2, b:1 }; x.a = Number.POSITIVE_INFINITY; x.b = 0; print(x.a/x.b); return 1;},
+                           expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function divisionWithRemainderTest() {var x = { a: 7, b:2 }; print(x.a/x.b); return 1;}, expectedValues =[['double', '3.5']]);
+checkExpectedRecompilation(function infinityMultiplicationTest() {var x = { a: Number.POSITIVE_INFINITY, b: Number.POSITIVE_INFINITY}; print(x.a*x.b); return 1;},
+                           expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function maxValueMultiplicationTest() {var x = { a: Number.MAX_VALUE, b: Number.MAX_VALUE}; print(x.a*x.b); return 1;},
+                           expectedValues =[['double', '1.7976931348623157e+308']]);
+checkExpectedRecompilation(function divisionByInfinityTest() {var x = { a: -1, b: Number.POSITIVE_INFINITY}; print(x.a/x.b); return 1;},
+                           expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function divisionByStringTest() {var x = { a: Number.POSITIVE_INFINITY, b: 'Hello'}; print(x.a/x.b); return 1;},
+                           expectedValues =[['double', 'Infinity']]);
+checkExpectedRecompilation(function nestedFunctionTest() {var a=3,b,c; function f() {var x = 2, y =1; function g(){var y = x; var z = a; z = x*y; print(a*b)} g()}f(); return 1;},
+                           expectedValues =[['object', 'undefined']]);
+checkExpectedRecompilation(function functionTest(a,b,c) { d = (a + b) * c; print(d); return 1;}, expectedValues =[['double', 'NaN']]);
+checkExpectedRecompilation(function andTest(a,b) { d = a && b; print(d); return 1;}, expectedValues =[['object', 'undefined']]);
diff --git a/nashorn/test/script/trusted/optimistic_recompilation.js.EXPECTED b/nashorn/test/script/trusted/optimistic_recompilation.js.EXPECTED
new file mode 100644
index 0000000..b36497f
--- /dev/null
+++ b/nashorn/test/script/trusted/optimistic_recompilation.js.EXPECTED
@@ -0,0 +1,27 @@
+Infinity
+1
+events = true
+3.5
+1
+events = true
+Infinity
+1
+events = true
+Infinity
+1
+events = true
+0
+1
+events = true
+NaN
+1
+events = true
+NaN
+1
+events = true
+NaN
+1
+events = true
+undefined
+1
+events = true
diff --git a/nashorn/test/src/UnnamedPackageTestCallback.java b/nashorn/test/src/UnnamedPackageTestCallback.java
index 67ab36f..3b6cdf5 100644
--- a/nashorn/test/src/UnnamedPackageTestCallback.java
+++ b/nashorn/test/src/UnnamedPackageTestCallback.java
@@ -23,6 +23,14 @@
  * questions.
  */
 
+/**
+ * Interface for callbacks used by the test suite.
+ */
 public interface UnnamedPackageTestCallback {
+    /**
+     * Call function
+     * @param s string argument
+     * @return string
+     */
     String call(String s);
 }
diff --git a/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java b/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java
index 2987b94..dd62409 100644
--- a/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java
+++ b/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java
@@ -25,7 +25,12 @@
 
 package jdk.nashorn.api;
 
-import java.sql.*;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
 import java.util.Properties;
 import java.util.logging.Logger;
 
@@ -36,18 +41,18 @@
     static {
         try {
             DriverManager.registerDriver(new NashornSQLDriver(), null);
-        } catch (SQLException se) {
+        } catch (final SQLException se) {
             throw new RuntimeException(se);
         }
     }
 
     @Override
-    public boolean acceptsURL(String url) {
+    public boolean acceptsURL(final String url) {
         return url.startsWith("jdbc:nashorn:");
     }
 
     @Override
-    public Connection connect(String url, Properties info) {
+    public Connection connect(final String url, final Properties info) {
         throw new UnsupportedOperationException("I am a dummy!!");
     }
 
@@ -62,7 +67,7 @@
     }
 
     @Override
-    public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) {
+    public DriverPropertyInfo[] getPropertyInfo(final String url, final Properties info) {
         return new DriverPropertyInfo[0];
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java b/nashorn/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
index 4a1d8d5..6997599 100644
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/ArrayConversionTest.java
@@ -111,25 +111,25 @@
         e.eval("Java.type('" + ArrayConversionTest.class.getName() + "')." + testMethodName + "(" + argument + ")");
     }
 
-    public static void assertNullIntArray(int[] array) {
+    public static void assertNullIntArray(final int[] array) {
         assertNull(array);
     }
 
-    public static void assertNullIntIntArray(int[][] array) {
+    public static void assertNullIntIntArray(final int[][] array) {
         assertNull(array);
     }
 
-    public static void assertEmptyIntArray(int[] array) {
+    public static void assertEmptyIntArray(final int[] array) {
         assertEquals(0, array.length);
     }
 
-    public static void assertSingle42IntArray(int[] array) {
+    public static void assertSingle42IntArray(final int[] array) {
         assertEquals(1, array.length);
         assertEquals(42, array[0]);
     }
 
 
-    public static void assertIntArrayConversions(int[] array) {
+    public static void assertIntArrayConversions(final int[] array) {
         assertEquals(13, array.length);
         assertEquals(0, array[0]); // false
         assertEquals(1, array[1]); // true
@@ -146,21 +146,21 @@
         assertEquals(0, array[12]); // [1, 2]
     }
 
-    public static void assertEmptyIntIntArray(int[][] array) {
+    public static void assertEmptyIntIntArray(final int[][] array) {
         assertEquals(0, array.length);
     }
 
-    public static void assertSingleEmptyIntIntArray(int[][] array) {
+    public static void assertSingleEmptyIntIntArray(final int[][] array) {
         assertEquals(1, array.length);
         assertTrue(Arrays.equals(new int[0], array[0]));
     }
 
-    public static void assertSingleNullIntIntArray(int[][] array) {
+    public static void assertSingleNullIntIntArray(final int[][] array) {
         assertEquals(1, array.length);
         assertNull(null, array[0]);
     }
 
-    public static void assertLargeIntIntArray(int[][] array) {
+    public static void assertLargeIntIntArray(final int[][] array) {
         assertEquals(5, array.length);
         assertTrue(Arrays.equals(new int[] { 0 }, array[0]));
         assertTrue(Arrays.equals(new int[] { 1 }, array[1]));
@@ -169,7 +169,7 @@
         assertTrue(Arrays.equals(new int[] { 7, 8 }, array[4]));
     }
 
-    public static void assertLargeObjectObjectArray(Object[][] array) throws ScriptException {
+    public static void assertLargeObjectObjectArray(final Object[][] array) throws ScriptException {
         assertEquals(4, array.length);
         assertTrue(Arrays.equals(new Object[] { Boolean.FALSE }, array[0]));
         assertTrue(Arrays.equals(new Object[] { 1 }, array[1]));
@@ -179,7 +179,7 @@
         assertEquals(17, e.eval("obj.x"));
     }
 
-    public static void assertBooleanArrayConversions(boolean[] array) {
+    public static void assertBooleanArrayConversions(final boolean[] array) {
         assertEquals(16, array.length);
         assertFalse(array[0]); // false
         assertTrue(array[1]); // true
@@ -199,26 +199,26 @@
         assertFalse(array[15]); // undefined
     }
 
-    public static void assertListArray(List<?>[] array) {
+    public static void assertListArray(final List<?>[] array) {
         assertEquals(2, array.length);
         assertEquals(Arrays.asList("foo", "bar"), array[0]);
         assertEquals(Arrays.asList("apple", "orange"), array[1]);
     }
 
-    public static void assertVarArg_42_17(Object... args) throws ScriptException {
+    public static void assertVarArg_42_17(final Object... args) throws ScriptException {
         assertEquals(2, args.length);
         assertEquals(42, ((Number)args[0]).intValue());
         assertEquals(17, ((Number)args[1]).intValue());
     }
 
-    public static void assertVarArg_array_17(Object... args) throws ScriptException {
+    public static void assertVarArg_array_17(final Object... args) throws ScriptException {
         assertEquals(2, args.length);
         e.getBindings(ScriptContext.ENGINE_SCOPE).put("arr", args[0]);
         assertTrue((Boolean)e.eval("arr instanceof Array && arr.length == 1 && arr[0] == 42"));
         assertEquals(18, ((Number)args[1]).intValue());
     }
 
-    public static void assertVarArg_function(Object... args) throws ScriptException {
+    public static void assertVarArg_function(final Object... args) throws ScriptException {
         assertEquals(1, args.length);
         e.getBindings(ScriptContext.ENGINE_SCOPE).put("fn", args[0]);
         assertEquals("Hello", e.eval("fn()"));
@@ -226,10 +226,10 @@
 
 
 
-    public static void x(String y) {
+    public static void x(final String y) {
         assertEquals("abc", y);
     }
-    public static void x(String[] y) {
+    public static void x(final String[] y) {
         assertTrue(Arrays.equals(new String[] { "foo", "bar"}, y));
     }
 }
diff --git a/nashorn/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java b/nashorn/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
index 1eadfb7..3b1fa2c7 100644
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/ConsStringTest.java
@@ -88,7 +88,7 @@
     public static class ArrayHolder {
         private Object[] array;
 
-        public void setArray(Object[] array) {
+        public void setArray(final Object[] array) {
             this.array = array;
         }
 
diff --git a/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java b/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
index 116d1cf..225891b 100644
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberAccessTest.java
@@ -44,8 +44,8 @@
  */
 public class NumberAccessTest {
 
-    private static ScriptEngine e = null;
-    private static SharedObject o = null;
+    private static ScriptEngine e;
+    private static SharedObject o;
 
     public static void main(final String[] args) {
         TestNG.main(args);
@@ -264,7 +264,7 @@
     @Test
     public void accessFieldByte() throws ScriptException {
         e.eval("var p_byte = o.publicByte;");
-        assertEquals(o.publicByte, e.get("p_byte"));
+        assertEquals((double)o.publicByte, ((Number)e.get("p_byte")).doubleValue());
         e.eval("o.publicByte = 16;");
         assertEquals(16, o.publicByte);
     }
@@ -287,7 +287,7 @@
     @Test
     public void accessStaticFieldByte() throws ScriptException {
         e.eval("var ps_byte = SharedObject.publicStaticByte;");
-        assertEquals(SharedObject.publicStaticByte, e.get("ps_byte"));
+        assertEquals((double)SharedObject.publicStaticByte, ((Number)e.get("ps_byte")).doubleValue());
         e.eval("SharedObject.publicStaticByte = 16;");
         assertEquals(16, SharedObject.publicStaticByte);
     }
@@ -310,7 +310,7 @@
     @Test
     public void accessFinalFieldByte() throws ScriptException {
         e.eval("var pf_byte = o.publicFinalByte;");
-        assertEquals(o.publicFinalByte, e.get("pf_byte"));
+        assertEquals((double)o.publicFinalByte, ((Number)e.get("pf_byte")).doubleValue());
         e.eval("o.publicFinalByte = 16;");
         assertEquals(-7, o.publicFinalByte);
     }
@@ -333,7 +333,7 @@
     @Test
     public void accessStaticFinalFieldByte() throws ScriptException {
         e.eval("var psf_byte = SharedObject.publicStaticFinalByte;");
-        assertEquals(SharedObject.publicStaticFinalByte, e.get("psf_byte"));
+        assertEquals((double)SharedObject.publicStaticFinalByte, ((Number)e.get("psf_byte")).doubleValue());
         e.eval("SharedObject.publicStaticFinalByte = 16;");
         assertEquals(-70, SharedObject.publicStaticFinalByte);
     }
@@ -358,7 +358,7 @@
     @Test
     public void accessFieldShort() throws ScriptException {
         e.eval("var p_short = o.publicShort;");
-        assertEquals(o.publicShort, e.get("p_short"));
+        assertEquals((double)o.publicShort, ((Number)e.get("p_short")).doubleValue());
         e.eval("o.publicShort = 18;");
         assertEquals(18, o.publicShort);
     }
@@ -381,7 +381,7 @@
     @Test
     public void accessStaticFieldShort() throws ScriptException {
         e.eval("var ps_short = SharedObject.publicStaticShort;");
-        assertEquals(SharedObject.publicStaticShort, e.get("ps_short"));
+        assertEquals((double)SharedObject.publicStaticShort, ((Number)e.get("ps_short")).doubleValue());
         e.eval("SharedObject.publicStaticShort = 180;");
         assertEquals(180, SharedObject.publicStaticShort);
     }
@@ -404,7 +404,7 @@
     @Test
     public void accessFinalFieldShort() throws ScriptException {
         e.eval("var pf_short = o.publicFinalShort;");
-        assertEquals(o.publicFinalShort, e.get("pf_short"));
+        assertEquals((double)o.publicFinalShort, ((Number)e.get("pf_short")).doubleValue());
         e.eval("o.publicFinalShort = 180;");
         assertEquals(31220, o.publicFinalShort);
     }
@@ -427,7 +427,7 @@
     @Test
     public void accessStaticFinalFieldShort() throws ScriptException {
         e.eval("var psf_short = SharedObject.publicStaticFinalShort;");
-        assertEquals(SharedObject.publicStaticFinalShort, e.get("psf_short"));
+        assertEquals((double)SharedObject.publicStaticFinalShort, ((Number)e.get("psf_short")).doubleValue());
         e.eval("SharedObject.publicStaticFinalShort = 180;");
         assertEquals(8888, SharedObject.publicStaticFinalShort);
     }
@@ -555,7 +555,7 @@
     @Test
     public void accessFieldFloat() throws ScriptException {
         e.eval("var p_float = o.publicFloat;");
-        assertEquals(o.publicFloat, e.get("p_float"));
+        assertEquals((double)o.publicFloat, ((Number)e.get("p_float")).doubleValue());
         o.publicFloat = 0.0f / 0.0f;
         assertEquals(true, e.eval("isNaN(o.publicFloat)"));
         o.publicFloat = 1.0f / 0.0f;
@@ -590,7 +590,7 @@
     @Test
     public void accessStaticFieldFloat() throws ScriptException {
         e.eval("var ps_float = SharedObject.publicStaticFloat;");
-        assertEquals(SharedObject.publicStaticFloat, e.get("ps_float"));
+        assertEquals((double)SharedObject.publicStaticFloat, ((Number)e.get("ps_float")).doubleValue());
         SharedObject.publicStaticFloat = 0.0f / 0.0f;
         assertEquals(true, e.eval("isNaN(SharedObject.publicStaticFloat)"));
         SharedObject.publicStaticFloat = 1.0f / 0.0f;
@@ -625,7 +625,7 @@
     @Test
     public void accessFinalFloat() throws ScriptException {
         e.eval("var pf_float = o.publicFinalFloat;");
-        assertEquals(o.publicFinalFloat, e.get("pf_float"));
+        assertEquals((double)o.publicFinalFloat, ((Number)e.get("pf_float")).doubleValue());
         e.eval("o.publicFinalFloat = 20.0;");
         assertEquals(7.72e8f, o.publicFinalFloat, 1e-10);
     }
@@ -648,7 +648,7 @@
     @Test
     public void accessStaticFinalFieldFloat() throws ScriptException {
         e.eval("var psf_float = SharedObject.publicStaticFinalFloat;");
-        assertEquals(SharedObject.publicStaticFinalFloat, e.get("psf_float"));
+        assertEquals((double)SharedObject.publicStaticFinalFloat, ((Number)e.get("psf_float")).doubleValue());
         e.eval("SharedObject.publicStaticFinalFloat = 20.0;");
         assertEquals(0.72e8f, SharedObject.publicStaticFinalFloat, 1e-10);
     }
diff --git a/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java b/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
index 03e3075..826368c 100644
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/NumberBoxingTest.java
@@ -43,8 +43,8 @@
  */
 public class NumberBoxingTest {
 
-    private static ScriptEngine e = null;
-    private static SharedObject o = null;
+    private static ScriptEngine e;
+    private static SharedObject o;
 
     public static void main(final String[] args) {
         TestNG.main(args);
@@ -77,10 +77,10 @@
 
     @Test
     public void accessStaticFieldLongBoxing() throws ScriptException {
-        e.eval("var ps_long = SharedObject.publicStaticLong;");
-        assertEquals(SharedObject.publicStaticLong, e.get("ps_long"));
-        e.eval("SharedObject.publicStaticLong = 120;");
-        assertEquals(120, SharedObject.publicStaticLong);
+        e.eval("var ps_long = SharedObject.publicStaticLongBox;");
+        assertEquals(SharedObject.publicStaticLongBox, e.get("ps_long"));
+        e.eval("SharedObject.publicStaticLongBox = 120;");
+        assertEquals(120L, SharedObject.publicStaticLongBox.longValue());
     }
 
     @Test
@@ -138,7 +138,7 @@
     @Test
     public void accessFieldByteBoxing() throws ScriptException {
         e.eval("var p_byte = o.publicByteBox;");
-        assertEquals(o.publicByteBox, e.get("p_byte"));
+        assertEqualsDouble(o.publicByteBox, "p_byte");
         e.eval("o.publicByteBox = 16;");
         assertEquals(Byte.valueOf((byte)16), o.publicByteBox);
     }
@@ -146,7 +146,7 @@
     @Test
     public void accessStaticFieldByteBoxing() throws ScriptException {
         e.eval("var ps_byte = SharedObject.publicStaticByte;");
-        assertEquals(SharedObject.publicStaticByte, e.get("ps_byte"));
+        assertEqualsDouble(SharedObject.publicStaticByte, "ps_byte");
         e.eval("SharedObject.publicStaticByte = 16;");
         assertEquals(16, SharedObject.publicStaticByte);
     }
@@ -154,7 +154,7 @@
     @Test
     public void accessFinalFieldByteBoxing() throws ScriptException {
         e.eval("var pf_byte = o.publicFinalByteBox;");
-        assertEquals(o.publicFinalByteBox, e.get("pf_byte"));
+        assertEqualsDouble(o.publicFinalByteBox, "pf_byte");
         e.eval("o.publicFinalByteBox = 16;");
         assertEquals(Byte.valueOf((byte)19), o.publicFinalByteBox);
     }
@@ -162,7 +162,7 @@
     @Test
     public void accessStaticFinalFieldByteBoxing() throws ScriptException {
         e.eval("var psf_byte = SharedObject.publicStaticFinalByte;");
-        assertEquals(SharedObject.publicStaticFinalByte, e.get("psf_byte"));
+        assertEqualsDouble(SharedObject.publicStaticFinalByte, "psf_byte");
         e.eval("SharedObject.publicStaticFinalByte = 16;");
         assertEquals(-70, SharedObject.publicStaticFinalByte);
     }
@@ -172,15 +172,19 @@
     @Test
     public void accessFieldShortBoxing() throws ScriptException {
         e.eval("var p_short = o.publicShortBox;");
-        assertEquals(o.publicShortBox, e.get("p_short"));
+        assertEqualsDouble(o.publicShortBox, "p_short");
         e.eval("o.publicShortBox = 18;");
         assertEquals(Short.valueOf((short)18), o.publicShortBox);
     }
 
+    private static void assertEqualsDouble(final Number n, final String name) {
+        assertEquals(n.doubleValue(), ((Number)e.get(name)).doubleValue());
+    }
+
     @Test
     public void accessStaticFieldShortBoxing() throws ScriptException {
         e.eval("var ps_short = SharedObject.publicStaticShort;");
-        assertEquals(SharedObject.publicStaticShort, e.get("ps_short"));
+        assertEqualsDouble(SharedObject.publicStaticShort, "ps_short");
         e.eval("SharedObject.publicStaticShort = 180;");
         assertEquals(180, SharedObject.publicStaticShort);
     }
@@ -188,7 +192,7 @@
     @Test
     public void accessFinalFieldShortBoxing() throws ScriptException {
         e.eval("var pf_short = o.publicFinalShortBox;");
-        assertEquals(o.publicFinalShortBox, e.get("pf_short"));
+        assertEqualsDouble(o.publicFinalShortBox, "pf_short");
         e.eval("o.publicFinalShortBox = 180;");
         assertEquals(Short.valueOf((short)-26777), o.publicFinalShortBox);
     }
@@ -196,7 +200,7 @@
     @Test
     public void accessStaticFinalFieldShortBoxing() throws ScriptException {
         e.eval("var psf_short = SharedObject.publicStaticFinalShort;");
-        assertEquals(SharedObject.publicStaticFinalShort, e.get("psf_short"));
+        assertEqualsDouble(SharedObject.publicStaticFinalShort, "psf_short");
         e.eval("SharedObject.publicStaticFinalShort = 180;");
         assertEquals(8888, SharedObject.publicStaticFinalShort);
     }
@@ -247,7 +251,7 @@
     @Test
     public void accessFieldFloatBoxing() throws ScriptException {
         e.eval("var p_float = o.publicFloatBox;");
-        assertEquals(o.publicFloatBox, e.get("p_float"));
+        assertEqualsDouble(o.publicFloatBox, "p_float");
         o.publicFloatBox = 0.0f / 0.0f;
         assertEquals(true, e.eval("isNaN(o.publicFloatBox)"));
         o.publicFloatBox = 1.0f / 0.0f;
@@ -267,7 +271,7 @@
     @Test
     public void accessStaticFieldFloatBoxing() throws ScriptException {
         e.eval("var ps_float = SharedObject.publicStaticFloat;");
-        assertEquals(SharedObject.publicStaticFloat, e.get("ps_float"));
+        assertEqualsDouble(SharedObject.publicStaticFloat, "ps_float");
         SharedObject.publicStaticFloat = 0.0f / 0.0f;
         assertEquals(true, e.eval("isNaN(SharedObject.publicStaticFloat)"));
         SharedObject.publicStaticFloat = 1.0f / 0.0f;
@@ -287,7 +291,7 @@
     @Test
     public void accessFinalFloatBoxing() throws ScriptException {
         e.eval("var pf_float = o.publicFinalFloatBox;");
-        assertEquals(o.publicFinalFloatBox, e.get("pf_float"));
+        assertEqualsDouble(o.publicFinalFloatBox, "pf_float");
         e.eval("o.publicFinalFloatBox = 20.0;");
         assertEquals(1.372e4f, o.publicFinalFloatBox, 1e-10);
     }
@@ -295,7 +299,7 @@
     @Test
     public void accessStaticFinalFieldFloatBoxing() throws ScriptException {
         e.eval("var psf_float = SharedObject.publicStaticFinalFloat;");
-        assertEquals(SharedObject.publicStaticFinalFloat, e.get("psf_float"));
+        assertEqualsDouble(SharedObject.publicStaticFinalFloat, "psf_float");
         e.eval("SharedObject.publicStaticFinalFloat = 20.0;");
         assertEquals(0.72e8f, SharedObject.publicStaticFinalFloat, 1e-10);
     }
diff --git a/nashorn/test/src/jdk/nashorn/api/javaaccess/SharedObject.java b/nashorn/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
index a7ef3ab..b400353 100644
--- a/nashorn/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
+++ b/nashorn/test/src/jdk/nashorn/api/javaaccess/SharedObject.java
@@ -51,7 +51,7 @@
     public short                  publicShort                   = 32000;
     public short[]                publicShortArray              = { 3240, 8900, -16789, 1, 12 };
     public Short                  publicShortBox                = Short.MIN_VALUE;
-    public float                  publicFloat                   = 0.7e6f;
+    public float                  publicFloat                   = 0.7f;
     public float[]                publicFloatArray              = { -32.01f, 89.3f, -1.3e8f, 3.1f };
     public Float                  publicFloatBox                = 1.377e4f;
     public double                 publicDouble                  = 1.34e20;
@@ -162,7 +162,7 @@
         return engine;
     }
 
-    public void setEngine(ScriptEngine engine) {
+    public void setEngine(final ScriptEngine engine) {
         this.engine = engine;
     }
 
@@ -414,51 +414,51 @@
         t.start();
     }
 
-    public String overloadedMethodDoubleVSint(int arg) {
+    public String overloadedMethodDoubleVSint(final int arg) {
         return "int";
     }
 
-    public String overloadedMethodDoubleVSint(double arg) {
+    public String overloadedMethodDoubleVSint(final double arg) {
         return "double";
     }
 
-    public int overloadedMethod(int arg) {
+    public int overloadedMethod(final int arg) {
         return arg*2;
     }
 
-    public int overloadedMethod(String arg) {
+    public int overloadedMethod(final String arg) {
         return arg.length();
     }
 
-    public int overloadedMethod(boolean arg) {
+    public int overloadedMethod(final boolean arg) {
         return (arg) ? 1 : 0;
     }
 
-    public int overloadedMethod(Person arg) {
+    public int overloadedMethod(final Person arg) {
         return arg.id*2;
     }
 
-    public int firstLevelMethodInt(int arg) throws ScriptException, NoSuchMethodException {
+    public int firstLevelMethodInt(final int arg) throws ScriptException, NoSuchMethodException {
         return (int) ((Invocable)engine).invokeFunction("secondLevelMethodInt", arg);
     }
 
-    public int thirdLevelMethodInt(int arg) {
+    public int thirdLevelMethodInt(final int arg) {
         return arg*5;
     }
 
-    public int firstLevelMethodInteger(Integer arg) throws ScriptException, NoSuchMethodException {
+    public int firstLevelMethodInteger(final Integer arg) throws ScriptException, NoSuchMethodException {
         return (int) ((Invocable)engine).invokeFunction("secondLevelMethodInteger", arg);
     }
 
-    public int thirdLevelMethodInteger(Integer arg) {
+    public int thirdLevelMethodInteger(final Integer arg) {
         return arg*10;
     }
 
-    public Person firstLevelMethodObject(Person p) throws ScriptException, NoSuchMethodException {
+    public Person firstLevelMethodObject(final Person p) throws ScriptException, NoSuchMethodException {
         return (Person) ((Invocable)engine).invokeFunction("secondLevelMethodObject", p);
     }
 
-    public Person thirdLevelMethodObject(Person p) {
+    public Person thirdLevelMethodObject(final Person p) {
         p.id *= 10;
         return p;
     }
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java
index a6722f5..d94aa46 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/InvocableTest.java
@@ -25,6 +25,9 @@
 
 package jdk.nashorn.api.scripting;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
 import java.util.Objects;
 import java.util.function.Function;
 import javax.script.Invocable;
@@ -34,8 +37,6 @@
 import javax.script.ScriptException;
 import javax.script.SimpleScriptContext;
 import org.testng.Assert;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.fail;
 import org.testng.annotations.Test;
 
 /**
@@ -43,7 +44,7 @@
  */
 public class InvocableTest {
 
-    private void log(String msg) {
+    private void log(final String msg) {
         org.testng.Reporter.log(msg, true);
     }
 
@@ -69,12 +70,12 @@
      * evaluating script with different Context set.
      */
     public void invokeMethodDifferentContextTest() {
-        ScriptEngineManager m = new ScriptEngineManager();
-        ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
 
         try {
             // define an object with method on it
-            Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
+            final Object obj = e.eval("({ hello: function() { return 'Hello World!'; } })");
 
             final ScriptContext ctxt = new SimpleScriptContext();
             ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
@@ -180,7 +181,7 @@
         final ScriptEngine engine2 = m.getEngineByName("nashorn");
 
         try {
-            Object obj = engine1.eval("({ run: function() {} })");
+            final Object obj = engine1.eval("({ run: function() {} })");
             // pass object from engine1 to engine2 as 'thiz' for invokeMethod
             ((Invocable) engine2).invokeMethod(obj, "run");
             fail("should have thrown IllegalArgumentException");
@@ -211,7 +212,7 @@
         // try interface on specific script object
         try {
             e.eval("var obj = { run: function() { print('run from obj'); } };");
-            Object obj = e.get("obj");
+            final Object obj = e.get("obj");
             final Runnable runnable = inv.getInterface(obj, Runnable.class);
             runnable.run();
         } catch (final Exception exp) {
@@ -307,17 +308,17 @@
      * switching to use different ScriptContext.
      */
     public void getInterfaceDifferentContext() {
-        ScriptEngineManager m = new ScriptEngineManager();
-        ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
         try {
-            Object obj = e.eval("({ run: function() { } })");
+            final Object obj = e.eval("({ run: function() { } })");
 
             // change script context
-            ScriptContext ctxt = new SimpleScriptContext();
+            final ScriptContext ctxt = new SimpleScriptContext();
             ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
             e.setContext(ctxt);
 
-            Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
+            final Runnable r = ((Invocable) e).getInterface(obj, Runnable.class);
             r.run();
         } catch (final Exception exp) {
             exp.printStackTrace();
@@ -376,7 +377,7 @@
         final ScriptEngine engine2 = m.getEngineByName("nashorn");
 
         try {
-            Object obj = engine1.eval("({ run: function() {} })");
+            final Object obj = engine1.eval("({ run: function() {} })");
             // pass object from engine1 to engine2 as 'thiz' for getInterface
             ((Invocable) engine2).getInterface(obj, Runnable.class);
             fail("should have thrown IllegalArgumentException");
@@ -433,12 +434,12 @@
      * Bindings.
      */
     public void invokeFunctionDifferentContextTest() {
-        ScriptEngineManager m = new ScriptEngineManager();
-        ScriptEngine e = m.getEngineByName("nashorn");
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
 
         try {
             // define an object with method on it
-            Object obj = e.eval("function hello() { return 'Hello World!'; }");
+            final Object obj = e.eval("function hello() { return 'Hello World!'; }");
             final ScriptContext ctxt = new SimpleScriptContext();
             ctxt.setBindings(e.createBindings(), ScriptContext.ENGINE_SCOPE);
             // change engine's current context
@@ -531,8 +532,8 @@
         final ScriptEngine e = m.getEngineByName("nashorn");
         final Invocable inv = (Invocable) e;
 
-        Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
-        Function<String, String> func = inv.getInterface(obj, Function.class);
+        final Object obj = e.eval("({ apply: function(arg) { return arg.toUpperCase(); }})");
+        final Function<String, String> func = inv.getInterface(obj, Function.class);
         assertEquals(func.apply("hello"), "HELLO");
     }
 }
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
index a574e6f..4e910ff 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java
@@ -25,6 +25,10 @@
 
 package jdk.nashorn.api.scripting;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.fail;
+
 import java.nio.IntBuffer;
 import java.util.Collection;
 import java.util.HashMap;
@@ -32,11 +36,6 @@
 import java.util.Set;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.fail;
 import org.testng.annotations.Test;
 
 /**
@@ -54,22 +53,22 @@
         }
 
         @Override
-        public Object getMember(String name) {
+        public Object getMember(final String name) {
             return map.get(name);
         }
 
         @Override
-        public void setMember(String name, Object value) {
+        public void setMember(final String name, final Object value) {
             map.put(name, value);
         }
 
         @Override
-        public boolean hasMember(String name) {
+        public boolean hasMember(final String name) {
             return map.containsKey(name);
         }
 
         @Override
-        public void removeMember(String name) {
+        public void removeMember(final String name) {
             map.remove(name);
         }
 
@@ -112,7 +111,7 @@
     public static class BufferObject extends AbstractJSObject {
         private final IntBuffer buf;
 
-        public BufferObject(int size) {
+        public BufferObject(final int size) {
             buf = IntBuffer.allocate(size);
         }
 
@@ -121,22 +120,22 @@
         }
 
         @Override
-        public Object getMember(String name) {
+        public Object getMember(final String name) {
             return name.equals("length")? buf.capacity() : null;
         }
 
         @Override
-        public boolean hasSlot(int i) {
+        public boolean hasSlot(final int i) {
             return i > -1 && i < buf.capacity();
         }
 
         @Override
-        public Object getSlot(int i) {
+        public Object getSlot(final int i) {
             return buf.get(i);
         }
 
         @Override
-        public void setSlot(int i, Object value) {
+        public void setSlot(final int i, final Object value) {
             buf.put(i, ((Number)value).intValue());
         }
 
@@ -172,9 +171,9 @@
 
     public static class Adder extends AbstractJSObject {
         @Override
-        public Object call(Object thiz, Object... args) {
+        public Object call(final Object thiz, final Object... args) {
             double res = 0.0;
-            for (Object arg : args) {
+            for (final Object arg : args) {
                 res += ((Number)arg).doubleValue();
             }
             return res;
@@ -204,7 +203,7 @@
 
     public static class Factory extends AbstractJSObject {
         @Override
-        public Object newObject(Object... args) {
+        public Object newObject(final Object... args) {
             return new HashMap<Object, Object>();
         }
 
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
index e2aec24..dfec160 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScopeTest.java
@@ -24,6 +24,11 @@
  */
 package jdk.nashorn.api.scripting;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
+
 import javax.script.Bindings;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
@@ -32,10 +37,6 @@
 import javax.script.SimpleBindings;
 import javax.script.SimpleScriptContext;
 import org.testng.Assert;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
 import org.testng.annotations.Test;
 
 /**
@@ -47,7 +48,7 @@
     public void createBindingsTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
-        Bindings b = e.createBindings();
+        final Bindings b = e.createBindings();
         b.put("foo", 42.0);
         Object res = null;
         try {
@@ -64,7 +65,7 @@
     public void engineScopeTest() {
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
-        Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
+        final Bindings engineScope = e.getBindings(ScriptContext.ENGINE_SCOPE);
 
         // check few ECMA standard built-in global properties
         assertNotNull(engineScope.get("Object"));
@@ -112,8 +113,8 @@
         newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
 
         try {
-            Object obj1 = e.eval("Object");
-            Object obj2 = e.eval("Object", newCtxt);
+            final Object obj1 = e.eval("Object");
+            final Object obj2 = e.eval("Object", newCtxt);
             Assert.assertNotEquals(obj1, obj2);
             Assert.assertNotNull(obj1);
             Assert.assertNotNull(obj2);
@@ -138,10 +139,12 @@
             e.eval("y = new Object()");
             e.eval("y = new Object()", origCtxt);
 
-            Object y1 = origCtxt.getAttribute("y");
-            Object y2 = newCtxt.getAttribute("y");
+            final Object y1 = origCtxt.getAttribute("y");
+            final Object y2 = newCtxt.getAttribute("y");
             Assert.assertNotEquals(y1, y2);
-            Assert.assertNotEquals(e.eval("y"), e.eval("y", origCtxt));
+            final Object yeval1 = e.eval("y");
+            final Object yeval2 = e.eval("y", origCtxt);
+            Assert.assertNotEquals(yeval1, yeval2);
             Assert.assertEquals("[object Object]", y1.toString());
             Assert.assertEquals("[object Object]", y2.toString());
         } catch (final ScriptException se) {
@@ -159,7 +162,7 @@
         final ScriptContext newContext = new SimpleScriptContext();
         newContext.setBindings(new SimpleBindings(), ScriptContext.ENGINE_SCOPE);
         // we are using a new bindings - so it should have 'func' defined
-        Object value = e.eval("typeof func", newContext);
+        final Object value = e.eval("typeof func", newContext);
         assertTrue(value.equals("undefined"));
     }
 
@@ -210,7 +213,7 @@
         assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
 
         // check new global instance created has engine.js definitions
-        Bindings b = e.createBindings();
+        final Bindings b = e.createBindings();
         value = b.get("__noSuchProperty__");
         assertTrue(value instanceof ScriptObjectMirror && ((ScriptObjectMirror)value).isFunction());
         value = b.get("print");
@@ -231,7 +234,7 @@
         assertTrue(e.eval("x", ctx).equals("hello"));
 
         // try some arbitray Bindings for ENGINE_SCOPE
-        Bindings sb = new SimpleBindings();
+        final Bindings sb = new SimpleBindings();
         ctx.setBindings(sb, ScriptContext.ENGINE_SCOPE);
 
         // GLOBAL_SCOPE mapping should be visible from non-default ScriptContext eval
@@ -305,7 +308,7 @@
         t1.join();
         t2.join();
 
-        Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt);
+        final Object obj3 = e.eval("delete foo; foo = 'newer context';", newCtxt);
         assertEquals(obj3, "newer context");
         final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
         final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
@@ -342,7 +345,7 @@
                     for (int i = 0; i < 1000; i++) {
                         assertEquals(e.eval(sharedScript, origContext), (double)i);
                     }
-                } catch (ScriptException se) {
+                } catch (final ScriptException se) {
                     fail(se.toString());
                 }
             }
@@ -354,7 +357,7 @@
                     for (int i = 2; i < 1000; i++) {
                         assertEquals(e.eval(sharedScript, newCtxt), (double)i);
                     }
-                } catch (ScriptException se) {
+                } catch (final ScriptException se) {
                     fail(se.toString());
                 }
             }
@@ -377,8 +380,8 @@
         final ScriptContext newCtxt = new SimpleScriptContext();
         newCtxt.setBindings(b, ScriptContext.ENGINE_SCOPE);
 
-        Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext);
-        Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt);
+        final Object obj1 = e.eval("String.prototype.foo = 'original context';", origContext);
+        final Object obj2 = e.eval("String.prototype.foo = 'new context';", newCtxt);
         assertEquals(obj1, "original context");
         assertEquals(obj2, "new context");
         final String sharedScript = "''.foo";
@@ -390,7 +393,7 @@
         t1.join();
         t2.join();
 
-        Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
+        final Object obj3 = e.eval("delete String.prototype.foo; Object.prototype.foo = 'newer context';", newCtxt);
         assertEquals(obj3, "newer context");
         final Thread t3 = new Thread(new ScriptRunner(e, origContext, sharedScript, "original context", 1000));
         final Thread t4 = new Thread(new ScriptRunner(e, newCtxt, sharedScript, "newer context", 1000));
@@ -572,7 +575,7 @@
                 for (int i = 0; i < iterations; i++) {
                     assertEquals(engine.eval(source, context), expected);
                 }
-            } catch (ScriptException se) {
+            } catch (final ScriptException se) {
                 throw new RuntimeException(se);
             }
         }
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
index 6d0d40f..09199a5 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineSecurityTest.java
@@ -27,8 +27,8 @@
 
 import static org.testng.Assert.fail;
 
-import java.lang.reflect.Method;
 import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.util.Objects;
 import javax.script.Invocable;
@@ -42,7 +42,7 @@
  */
 public class ScriptEngineSecurityTest {
 
-    private void log(String msg) {
+    private void log(final String msg) {
         org.testng.Reporter.log(msg, true);
     }
 
@@ -185,8 +185,8 @@
         // put an empty script object into array
         e.eval("holder[0] = {}");
         // holder[0] is an object of some subclass of ScriptObject
-        Class ScriptObjectClass = holder[0].getClass().getSuperclass();
-        Class PropertyAccessClass = ScriptObjectClass.getInterfaces()[0];
+        final Class<?> ScriptObjectClass = holder[0].getClass().getSuperclass();
+        final Class<?> PropertyAccessClass = ScriptObjectClass.getInterfaces()[0];
         // implementation methods for PropertyAccess class
         e.eval("function set() {}; function get() {}; function getInt(){} " +
                "function getDouble(){}; function getLong() {}; " +
@@ -206,11 +206,11 @@
 
     // @bug 8032948: Nashorn linkages awry
     public static class FakeProxy extends Proxy {
-        public FakeProxy(InvocationHandler ih) {
+        public FakeProxy(final InvocationHandler ih) {
             super(ih);
         }
 
-        public static Class<?> makeProxyClass(ClassLoader cl, Class<?>... ifaces) {
+        public static Class<?> makeProxyClass(final ClassLoader cl, final Class<?>... ifaces) {
             return Proxy.getProxyClass(cl, ifaces);
         }
     }
@@ -229,11 +229,11 @@
         e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
         e.put("intfs", new Class[] { Runnable.class });
 
-        String getClass = "Java.type(name + '$FakeProxy').getProxyClass(cl, intfs);";
+        final String getClass = "Java.type(name + '$FakeProxy').getProxyClass(cl, intfs);";
 
         // Should not be able to call static methods of Proxy via fake subclass
         try {
-            Class c = (Class)e.eval(getClass);
+            final Class<?> c = (Class<?>)e.eval(getClass);
             fail("should have thrown SecurityException");
         } catch (final Exception exp) {
             if (! (exp instanceof SecurityException)) {
@@ -256,11 +256,11 @@
         e.put("cl", ScriptEngineSecurityTest.class.getClassLoader());
         e.put("intfs", new Class[] { Runnable.class });
 
-        String getClass = "Java.type(name + '$FakeProxy').makeProxyClass(cl, intfs);";
+        final String getClass = "Java.type(name + '$FakeProxy').makeProxyClass(cl, intfs);";
 
         // Should not be able to call static methods of Proxy via fake subclass
         try {
-            Class c = (Class)e.eval(getClass);
+            final Class<?> c = (Class<?>)e.eval(getClass);
             fail("should have thrown SecurityException");
         } catch (final Exception exp) {
             if (! (exp instanceof SecurityException)) {
@@ -271,6 +271,11 @@
 
     @Test
     public static void proxyStaticAccessCheckTest() throws ScriptException {
+        if (System.getSecurityManager() == null) {
+            // pass vacuously
+            return;
+        }
+
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
         final Runnable r = (Runnable)Proxy.newProxyInstance(
@@ -278,7 +283,7 @@
             new Class[] { Runnable.class },
             new InvocationHandler() {
                 @Override
-                public Object invoke(Object p, Method m, Object[] a) {
+                public Object invoke(final Object p, final Method m, final Object[] a) {
                     return null;
                 }
             });
@@ -297,4 +302,43 @@
             }
         }
     }
+
+
+    @Test
+    public void nashornConfigSecurityTest() {
+        if (System.getSecurityManager() == null) {
+            // pass vacuously
+            return;
+        }
+
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        try {
+            fac.getScriptEngine(new ClassFilter() {
+               @Override
+               public boolean exposeToScripts(final String name) {
+                   return true;
+               }
+            });
+            fail("SecurityException should have been thrown");
+        } catch (final SecurityException exp) {}
+    }
+
+    @Test
+    public void nashornConfigSecurityTest2() {
+        if (System.getSecurityManager() == null) {
+            // pass vacuously
+            return;
+        }
+
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        try {
+            fac.getScriptEngine(new String[0], null, new ClassFilter() {
+               @Override
+               public boolean exposeToScripts(final String name) {
+                   return true;
+               }
+            });
+            fail("SecurityException should have been thrown");
+        } catch (final SecurityException exp) {}
+    }
 }
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
index 5219914..291e8d4 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java
@@ -30,7 +30,6 @@
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
-import java.io.PrintWriter;
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.lang.reflect.InvocationHandler;
@@ -56,7 +55,7 @@
  */
 public class ScriptEngineTest {
 
-    private void log(String msg) {
+    private void log(final String msg) {
         org.testng.Reporter.log(msg, true);
     }
 
@@ -65,11 +64,11 @@
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
 
-        String[] args = new String[] { "hello", "world" };
+        final String[] args = new String[] { "hello", "world" };
         try {
             e.put("arguments", args);
-            Object arg0 = e.eval("arguments[0]");
-            Object arg1 = e.eval("arguments[1]");
+            final Object arg0 = e.eval("arguments[0]");
+            final Object arg1 = e.eval("arguments[1]");
             assertEquals(args[0], arg0);
             assertEquals(args[1], arg1);
         } catch (final Exception exp) {
@@ -83,12 +82,12 @@
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
 
-        String[] args = new String[] { "hello", "world" };
+        final String[] args = new String[] { "hello", "world" };
         try {
             e.put("arguments", args);
-            Object arg0 = e.eval("var imports = new JavaImporter(java.io); " +
+            final Object arg0 = e.eval("var imports = new JavaImporter(java.io); " +
                     " with(imports) { arguments[0] }");
-            Object arg1 = e.eval("var imports = new JavaImporter(java.util, java.io); " +
+            final Object arg1 = e.eval("var imports = new JavaImporter(java.util, java.io); " +
                     " with(imports) { arguments[1] }");
             assertEquals(args[0], arg0);
             assertEquals(args[1], arg1);
@@ -129,18 +128,18 @@
         assertEquals(fac.getParameter(ScriptEngine.NAME), "javascript");
 
         boolean seenJS = false;
-        for (String ext : fac.getExtensions()) {
+        for (final String ext : fac.getExtensions()) {
             if (ext.equals("js")) {
                 seenJS = true;
             }
         }
 
         assertEquals(seenJS, true);
-        String str = fac.getMethodCallSyntax("obj", "foo", "x");
+        final String str = fac.getMethodCallSyntax("obj", "foo", "x");
         assertEquals(str, "obj.foo(x)");
 
         boolean seenNashorn = false, seenJavaScript = false, seenECMAScript = false;
-        for (String name : fac.getNames()) {
+        for (final String name : fac.getNames()) {
             switch (name) {
                 case "nashorn": seenNashorn = true; break;
                 case "javascript": seenJavaScript = true; break;
@@ -153,7 +152,7 @@
         assertTrue(seenECMAScript);
 
         boolean seenAppJS = false, seenAppECMA = false, seenTextJS = false, seenTextECMA = false;
-        for (String mime : fac.getMimeTypes()) {
+        for (final String mime : fac.getMimeTypes()) {
             switch (mime) {
                 case "application/javascript": seenAppJS = true; break;
                 case "application/ecmascript": seenAppECMA = true; break;
@@ -548,7 +547,7 @@
             new Class[] { Runnable.class },
             new InvocationHandler() {
                 @Override
-                public Object invoke(Object p, Method m, Object[] a) {
+                public Object invoke(final Object p, final Method m, final Object[] a) {
                     reached[0] = true;
                     return null;
                 }
@@ -594,9 +593,45 @@
         }
     }
 
+    // @bug 8046013: TypeError: Cannot apply "with" to non script object
+    @Test
+    public void withOnMirrorTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        final Object obj = e.eval("({ foo: 'hello'})");
+        final Object[] arr = new Object[1];
+        arr[0] = obj;
+        e.put("arr", arr);
+        final Object res = e.eval("var res; with(arr[0]) { res = foo; }; res");
+        assertEquals(res, "hello");
+    }
+
+    // @bug 8054223: Nashorn: AssertionError when use __DIR__ and ScriptEngine.eval()
+    @Test
+    public void check__DIR__Test() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+        e.eval("__DIR__");
+    }
+
+    // @bug 8050432:javax.script.filename variable should not be enumerable
+    // with nashorn engine's ENGINE_SCOPE bindings
+    @Test
+    public void enumerableGlobalsTest() throws ScriptException {
+        final ScriptEngineManager m = new ScriptEngineManager();
+        final ScriptEngine e = m.getEngineByName("nashorn");
+
+        e.put(ScriptEngine.FILENAME, "test");
+        final Object enumerable = e.eval(
+            "Object.getOwnPropertyDescriptor(this, " +
+            " 'javax.script.filename').enumerable");
+        assertEquals(enumerable, Boolean.FALSE);
+    }
+
     private static void checkProperty(final ScriptEngine e, final String name)
         throws ScriptException {
-        String value = System.getProperty(name);
+        final String value = System.getProperty(name);
         e.put("name", name);
         assertEquals(value, e.eval("java.lang.System.getProperty(name)"));
     }
diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
index 30eaefc..dc34744 100644
--- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
+++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java
@@ -25,19 +25,22 @@
 
 package jdk.nashorn.api.scripting;
 
-import java.nio.ByteBuffer;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import javax.script.Bindings;
-import javax.script.ScriptContext;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineManager;
-import javax.script.ScriptException;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertFalse;
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
+
+import java.nio.ByteBuffer;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import javax.script.Bindings;
+import javax.script.Invocable;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineManager;
+import javax.script.ScriptException;
 import org.testng.annotations.Test;
 
 /**
@@ -133,7 +136,7 @@
         final ScriptEngine e = m.getEngineByName("nashorn");
         try {
             e.eval("var obj = { '1': 'world', func: function() { return this.bar; }, bar: 'hello' }");
-            ScriptObjectMirror obj = (ScriptObjectMirror) e.get("obj");
+            final ScriptObjectMirror obj = (ScriptObjectMirror) e.get("obj");
 
             // try basic get on existing properties
             if (!obj.getMember("bar").equals("hello")) {
@@ -190,7 +193,7 @@
         final ScriptEngineManager m = new ScriptEngineManager();
         final ScriptEngine e = m.getEngineByName("nashorn");
         try {
-            Object obj = e.eval("new TypeError('wrong type')");
+            final Object obj = e.eval("new TypeError('wrong type')");
             assertEquals(obj.toString(), "TypeError: wrong type", "toString returns wrong value");
         } catch (final Throwable t) {
             t.printStackTrace();
@@ -198,7 +201,7 @@
         }
 
         try {
-            Object obj = e.eval("function func() { print('hello'); }");
+            final Object obj = e.eval("function func() { print('hello'); }");
             assertEquals(obj.toString(), "function func() { print('hello'); }", "toString returns wrong value");
         } catch (final Throwable t) {
             t.printStackTrace();
@@ -305,4 +308,79 @@
         // getMember("obj.foo") - thereby getting null instead of undefined
         assertEquals("undefined", engine.eval(TEST_SCRIPT, newGlobal));
     }
+
+    public interface MirrorCheckExample {
+        Object test1(Object arg);
+        Object test2(Object arg);
+        boolean compare(Object o1, Object o2);
+    }
+
+    // @bug 8053910: ScriptObjectMirror causing havoc with Invocation interface
+    @Test
+    public void checkMirrorToObject() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine engine = engineManager.getEngineByName("nashorn");
+        final Invocable invocable = (Invocable)engine;
+
+        engine.eval("function test1(arg) { return { arg: arg }; }");
+        engine.eval("function test2(arg) { return arg; }");
+        engine.eval("function compare(arg1, arg2) { return arg1 == arg2; }");
+
+        final Map<String, Object> map = new HashMap<>();
+        map.put("option", true);
+
+        final MirrorCheckExample example = invocable.getInterface(MirrorCheckExample.class);
+
+        final Object value1 = invocable.invokeFunction("test1", map);
+        final Object value2 = example.test1(map);
+        final Object value3 = invocable.invokeFunction("test2", value2);
+        final Object value4 = example.test2(value2);
+
+        // check that Object type argument receives a ScriptObjectMirror
+        // when ScriptObject is passed
+        assertEquals(ScriptObjectMirror.class, value1.getClass());
+        assertEquals(ScriptObjectMirror.class, value2.getClass());
+        assertEquals(ScriptObjectMirror.class, value3.getClass());
+        assertEquals(ScriptObjectMirror.class, value4.getClass());
+        assertTrue((boolean)invocable.invokeFunction("compare", value1, value1));
+        assertTrue((boolean)example.compare(value1, value1));
+        assertTrue((boolean)invocable.invokeFunction("compare", value3, value4));
+        assertTrue((boolean)example.compare(value3, value4));
+    }
+
+    // @bug 8053910: ScriptObjectMirror causing havoc with Invocation interface
+    @Test
+    @SuppressWarnings("unchecked")
+    public void mirrorUnwrapInterfaceMethod() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine engine = engineManager.getEngineByName("nashorn");
+        final Invocable invocable = (Invocable)engine;
+        engine.eval("function apply(obj) { " +
+            " return obj instanceof Packages.jdk.nashorn.api.scripting.ScriptObjectMirror; " +
+            "}");
+        final Function<Object,Object> func = invocable.getInterface(Function.class);
+        assertFalse((boolean)func.apply(engine.eval("({ x: 2 })")));
+    }
+
+    // @bug 8055687: Wrong "this" passed to JSObject.eval call
+    @Test
+    public void checkThisForJSObjectEval() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine e = engineManager.getEngineByName("nashorn");
+        final JSObject jsobj = (JSObject)e.eval("({foo: 23, bar: 'hello' })");
+        assertEquals(((Number)jsobj.eval("this.foo")).intValue(), 23);
+        assertEquals(jsobj.eval("this.bar"), "hello");
+        assertEquals(jsobj.eval("String(this)"), "[object Object]");
+        final Object global = e.eval("this");
+        assertFalse(global.equals(jsobj.eval("this")));
+    }
+
+    @Test
+    public void topLevelAnonFuncStatement() throws Exception {
+        final ScriptEngineManager engineManager = new ScriptEngineManager();
+        final ScriptEngine e = engineManager.getEngineByName("nashorn");
+        final JSObject func = (JSObject)e.eval("function(x) { return x + ' world' }");
+        assertTrue(func.isFunction());
+        assertEquals(func.call(e.eval("this"), "hello"), "hello world");
+    }
 }
diff --git a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
index 1ebb97a..777f704 100644
--- a/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/codegen/CompilerTest.java
@@ -25,8 +25,8 @@
 
 package jdk.nashorn.internal.codegen;
 
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
 import static jdk.nashorn.internal.runtime.Source.readFully;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
 import java.io.File;
 import java.io.PrintWriter;
@@ -56,7 +56,7 @@
         public boolean exclude(File file, String content);
     }
 
-    private void log(String msg) {
+    private void log(final String msg) {
         org.testng.Reporter.log(msg, true);
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java b/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java
index 8a68bb1..2b1719f 100644
--- a/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/parser/ParserTest.java
@@ -25,8 +25,8 @@
 
 package jdk.nashorn.internal.parser;
 
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
 import static jdk.nashorn.internal.runtime.Source.readFully;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
 
 import java.io.File;
 import jdk.nashorn.internal.runtime.Context;
@@ -53,7 +53,7 @@
         public boolean exclude(File file, String content);
     }
 
-    private void log(String msg) {
+    private static void log(final String msg) {
         org.testng.Reporter.log(msg, true);
     }
 
@@ -67,7 +67,7 @@
         options.set("scripting", true);
         options.set("const.as.var", true);
 
-        ErrorManager errors = new ErrorManager();
+        final ErrorManager errors = new ErrorManager();
         this.context = new Context(options, errors, Thread.currentThread().getContextClassLoader());
     }
 
@@ -157,8 +157,8 @@
                 }
             };
             errors.setLimit(0);
-            final Source   source   = sourceFor(file.getAbsolutePath(), buffer);
-            new Parser(context.getEnv(), source, errors).parse();
+            final Source source = sourceFor(file.getAbsolutePath(), buffer);
+            new Parser(context.getEnv(), source, errors, context.getEnv()._strict, null).parse();
             if (errors.getNumberOfErrors() > 0) {
                 log("Parse failed: " + file.getAbsolutePath());
                 failed++;
@@ -166,6 +166,7 @@
                 passed++;
             }
         } catch (final Throwable exp) {
+            exp.printStackTrace();
             log("Parse failed: " + file.getAbsolutePath() + " : " + exp);
             if (VERBOSE) {
                 exp.printStackTrace(System.out);
diff --git a/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java b/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java
index 7e402c6..d1f7942 100644
--- a/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/performance/OctaneTest.java
@@ -111,7 +111,7 @@
         try {
             final String mainScript      = "test/script/basic/run-octane.js";
             final String benchmarkScript = "test/script/external/octane/benchmarks/"+benchmark.toLowerCase() + ".js";
-            String[] args = {
+            final String[] args = {
                 "--",
                 benchmarkScript,
                 "--verbose"
@@ -136,16 +136,17 @@
         }
     }
 
-    public Double genericNashornTest(final String benchmark, final String testPath, String[] args) throws Throwable {
+    public Double genericNashornTest(final String benchmark, final String testPath, final String[] args) throws Throwable {
         try {
             final PerformanceWrapper wrapper = new PerformanceWrapper();
 
             final ByteArrayOutputStream baos = new ByteArrayOutputStream();
             final PrintStream ps = new PrintStream(baos);
 
-            java.io.File test=new java.io.File(testPath);
-            File absoluteFile=test.getAbsoluteFile();
+            final java.io.File test=new java.io.File(testPath);
+            final File absoluteFile=test.getAbsoluteFile();
             @SuppressWarnings("deprecation")
+            final
             URL testURL=absoluteFile.toURL();
 
             wrapper.runExecuteOnlyTest(testPath, 0, 0, testURL.toString(), ps, System.err, args);
@@ -153,7 +154,7 @@
             final byte[] output = baos.toByteArray();
             final List<String> result = outputToStrings(output);
 
-            Double _result = filterBenchmark(result, benchmark);
+            final Double _result = filterBenchmark(result, benchmark);
 
             return _result;
         } catch (final Throwable e) {
@@ -265,7 +266,7 @@
         if (v8 != null && rhino != 0) {
             nashornToV8 = nashorn.doubleValue() / v8.doubleValue();
         }
-        String normalizedBenchmark=benchmark.replace("-", "");
+        final String normalizedBenchmark=benchmark.replace("-", "");
         System.out.println("benchmark-" + normalizedBenchmark + "-nashorn=" + nashorn);
         AuroraWrapper.addResults(AuroraWrapper.createOrOpenDocument(), "benchmark-" + normalizedBenchmark + "-nashorn", nashorn.toString());
 
diff --git a/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java b/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
index ce96921..2ffefbf 100644
--- a/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
+++ b/nashorn/test/src/jdk/nashorn/internal/performance/PerformanceWrapper.java
@@ -72,8 +72,8 @@
     }
 
 
-    protected void runExecuteOnlyTest(final String name, final int numberOfIterations, final int runsPerIteration, final String testURL, final OutputStream out, final OutputStream err, String[] newargs) throws Throwable {
-        String[] args=new String[newargs.length+1];
+    protected void runExecuteOnlyTest(final String name, final int numberOfIterations, final int runsPerIteration, final String testURL, final OutputStream out, final OutputStream err, final String[] newargs) throws Throwable {
+        final String[] args=new String[newargs.length+1];
         System.arraycopy(newargs, 0, args, 1, newargs.length);
         args[0]=name;
 
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java
new file mode 100644
index 0000000..558833e
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ClassFilterTest.java
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+
+import jdk.nashorn.api.scripting.ClassFilter;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import jdk.nashorn.api.scripting.URLReader;
+import org.testng.annotations.Test;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import java.io.File;
+
+import static org.testng.Assert.fail;
+
+public class ClassFilterTest {
+    private static final String NASHORN_CODE_CACHE = "nashorn.persistent.code.cache";
+    private static final String CLASSFILTER_CODE_CACHE = "build/classfilter_nashorn_code_cache";
+
+    // @Test
+    // This test takes too much time for basic "ant clean test" run.
+    // Given that "allow-all-java-classes" is equivalent to no java class
+    // filter and external tests don't access any java, not sure if this
+    // test contributes much. We need faster "ant clean test" cycle for
+    // developers.
+    public void runExternalJsTest() {
+        String[] paths = new String[]{
+                "test/script/basic/compile-octane.js",
+                "test/script/basic/jquery.js",
+                "test/script/basic/prototype.js",
+                "test/script/basic/runsunspider.js",
+                "test/script/basic/underscore.js",
+                "test/script/basic/yui.js",
+                "test/script/basic/run-octane.js"
+        };
+        NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        for (String path : paths) {
+            ScriptEngine engine = factory.getScriptEngine(new String[]{"-scripting"}, getClass().getClassLoader(), getClassFilter());
+            try {
+                engine.eval(new URLReader(new File(path).toURI().toURL()));
+            } catch (Exception e) {
+                fail("Script " + path + " fails with exception :" + e.getMessage());
+            }
+        }
+    }
+
+    @Test
+    public void noJavaOptionTest() {
+        NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        ScriptEngine engine = factory.getScriptEngine(new String[]{"--no-java"}, getClass().getClassLoader(), getClassFilter());
+        try {
+            engine.eval("var str = Java.type('java.lang.String');");
+            fail("TypeError should have been thrown");
+        } catch (ScriptException exc) {
+        }
+    }
+
+    @Test
+    public void securityTest() {
+        if (System.getSecurityManager() == null) {
+            return;
+        }
+
+        NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        ScriptEngine engine = factory.getScriptEngine(getClassFilter());
+        try {
+            engine.eval("var thread = Java.type('sun.misc.Unsafe')");
+            fail("SecurityException should have been thrown");
+        } catch (final Exception exc) {
+        }
+        try {
+            engine.eval("var thread = new sun.misc.Unsafe()");
+            fail("SecurityException should have been thrown");
+        } catch (final Exception exc) {
+        }
+        try {
+            engine.eval("var thread = Java.extend(sun.misc.Unsafe, {})");
+            fail("TypeError should have been thrown");
+        } catch (final Exception exc) {
+        }
+        try {
+            engine.eval("java.lang.System.exit(0)");
+            fail("SecurityException should have been thrown");
+        } catch (final Exception exc) {
+        }
+
+    }
+
+    @Test
+    public void persistentCacheTest() {
+        final String oldCodeCache = System.getProperty(NASHORN_CODE_CACHE);
+        System.setProperty(NASHORN_CODE_CACHE, CLASSFILTER_CODE_CACHE);
+        try {
+            persistentCacheTestImpl();
+        } finally {
+            if (oldCodeCache != null) {
+                System.setProperty(NASHORN_CODE_CACHE, oldCodeCache);
+            }
+        }
+    }
+
+    private void persistentCacheTestImpl() {
+        NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
+        ScriptEngine engine = factory.getScriptEngine(
+                new String[]{"--persistent-code-cache"},
+                getClass().getClassLoader(),
+                getClassFilter()
+        );
+        String testScript = "var a = Java.type('java.lang.String');" + generateCodeForPersistentStore();
+        try {
+            engine.eval(testScript);
+        } catch (final ScriptException exc) {
+            fail(exc.getMessage());
+        }
+        ScriptEngine engineSafe = factory.getScriptEngine(
+                new String[]{"--persistent-code-cache"},
+                getClass().getClassLoader(),
+                new ClassFilter() {
+                    @Override
+                    public boolean exposeToScripts(String s) {
+                        return false;
+                    }
+                }
+        );
+        try {
+            engineSafe.eval(testScript);
+            fail("ClassNotFoundException should have been thrown");
+        } catch (final Exception exc) {
+            if (!(exc.getCause() instanceof ClassNotFoundException)) {
+                fail("ClassNotFoundException expected");
+            }
+        }
+    }
+
+    private String generateCodeForPersistentStore() {
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i=0; i < 100; i++) {
+            stringBuilder.append("function i")
+                    .append(i)
+                    .append("(y, z) { var x")
+                    .append(i)
+                    .append(" = ")
+                    .append(i)
+                    .append(";}");
+        }
+        return stringBuilder.toString();
+    }
+
+    private ClassFilter getClassFilter() {
+        return new ClassFilter() {
+            @Override
+            public boolean exposeToScripts(String s) {
+                return true;
+            }
+        };
+    }
+}
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
index a2d72eb..9175ef6 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/CodeStoreAndPathTest.java
@@ -24,18 +24,19 @@
  */
 package jdk.nashorn.internal.runtime;
 
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+
 import java.io.File;
 import java.io.IOException;
-import java.nio.file.Files;
 import java.nio.file.DirectoryStream;
-import java.nio.file.Path;
 import java.nio.file.FileSystems;
-import javax.script.ScriptException;
-import org.testng.annotations.Test;
+import java.nio.file.Files;
+import java.nio.file.Path;
 import javax.script.ScriptEngine;
+import javax.script.ScriptException;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertEquals;
+import org.testng.annotations.Test;
 
 /**
  * @test
@@ -95,8 +96,10 @@
     final String codeCache = "build/nashorn_code_cache";
     final String oldUserDir = System.getProperty("user.dir");
 
-    public void checkCompiledScripts(DirectoryStream<Path> stream, int numberOfScripts) throws IOException {
-        for (Path file : stream) {
+    private static final String[] ENGINE_OPTIONS = new String[]{"--persistent-code-cache", "--optimistic-types=false", "--lazy-compilation=false"};
+
+    public void checkCompiledScripts(final DirectoryStream<Path> stream, int numberOfScripts) throws IOException {
+        for (final Path file : stream) {
             numberOfScripts--;
         }
         stream.close();
@@ -106,16 +109,15 @@
     @Test
     public void pathHandlingTest() throws ScriptException, IOException {
         System.setProperty("nashorn.persistent.code.cache", codeCache);
-        String[] options = new String[]{"--persistent-code-cache"};
-        NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
-        ScriptEngine e = fac.getScriptEngine(options);
-        Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache);
-        Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS);
+        final Path expectedCodeCachePath = FileSystems.getDefault().getPath(oldUserDir + File.separator + codeCache);
+        final Path actualCodeCachePath = FileSystems.getDefault().getPath(System.getProperty(
                             "nashorn.persistent.code.cache")).toAbsolutePath();
         // Check that nashorn code cache is created in current working directory
         assertEquals(actualCodeCachePath, expectedCodeCachePath);
         // Check that code cache dir exists and it's not empty
-        File file = new File(actualCodeCachePath.toUri());
+        final File file = new File(actualCodeCachePath.toUri());
         assertFalse(!file.isDirectory(), "No code cache directory was created!");
         assertFalse(file.list().length == 0, "Code cache directory is empty!");
     }
@@ -123,37 +125,36 @@
     @Test
     public void changeUserDirTest() throws ScriptException, IOException {
         System.setProperty("nashorn.persistent.code.cache", codeCache);
-        String[] options = new String[]{"--persistent-code-cache"};
-        NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
-        ScriptEngine e = fac.getScriptEngine(options);
-        Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS);
+        final Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
                             "nashorn.persistent.code.cache")).toAbsolutePath();
-        String newUserDir = "build/newUserDir";
+        final String newUserDir = "build/newUserDir";
         // Now changing current working directory
         System.setProperty("user.dir", System.getProperty("user.dir") + File.separator + newUserDir);
-        // Check that a new compiled script is stored in exisitng code cache
-        e.eval(code1);
-        DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
-        // Already one compiled script has been stored in the cache during initialization
-        checkCompiledScripts(stream, 2);
-        // Setting to default current working dir
-        System.setProperty("user.dir", oldUserDir);
+        try {
+            // Check that a new compiled script is stored in existing code cache
+            e.eval(code1);
+            final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
+            checkCompiledScripts(stream, 1);
+            // Setting to default current working dir
+        } finally {
+            System.setProperty("user.dir", oldUserDir);
+        }
     }
 
     @Test
     public void codeCacheTest() throws ScriptException, IOException {
         System.setProperty("nashorn.persistent.code.cache", codeCache);
-        String[] options = new String[]{"--persistent-code-cache"};
-        NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
-        ScriptEngine e = fac.getScriptEngine(options);
-        Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        final ScriptEngine e = fac.getScriptEngine(ENGINE_OPTIONS);
+        final Path codeCachePath = FileSystems.getDefault().getPath(System.getProperty(
                             "nashorn.persistent.code.cache")).toAbsolutePath();
         e.eval(code1);
         e.eval(code2);
         e.eval(code3);// less than minimum size for storing
-        // Already one compiled script has been stored in the cache during initialization
         // adding code1 and code2.
-        DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
-        checkCompiledScripts(stream, 3);
+        final DirectoryStream<Path> stream = Files.newDirectoryStream(codeCachePath);
+        checkCompiledScripts(stream, 2);
     }
 }
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java
new file mode 100644
index 0000000..16c3606
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ConsStringTest.java
@@ -0,0 +1,131 @@
+/*
+ * 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.  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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static org.testng.Assert.assertEquals;
+
+import org.testng.annotations.Test;
+
+/**
+ * Tests for JSType methods.
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.ConsStringTest
+ */
+public class ConsStringTest {
+
+    /**
+     * Test toString conversion
+     */
+    @Test
+    public void testConsStringToString() {
+        final ConsString cs1 = new ConsString("b", "c");
+        final ConsString cs2 = new ConsString("d", "e");
+        final ConsString cs3 = new ConsString(cs1, cs2);
+        final ConsString cs4 = new ConsString(cs3, "f");
+        final ConsString cs5 = new ConsString("a", cs4);
+        assertEquals(cs5.toString(), "abcdef");
+        assertEquals(cs4.toString(), "bcdef");
+        assertEquals(cs3.toString(), "bcde");
+        assertEquals(cs2.toString(), "de");
+        assertEquals(cs1.toString(), "bc");
+        // ConsStrings should be flattened now
+        assertEquals(cs1.getComponents()[0], "bc");
+        assertEquals(cs1.getComponents()[1], "");
+        assertEquals(cs2.getComponents()[0], "de");
+        assertEquals(cs2.getComponents()[1], "");
+        assertEquals(cs3.getComponents()[0], "bcde");
+        assertEquals(cs3.getComponents()[1], "");
+        assertEquals(cs4.getComponents()[0], "bcdef");
+        assertEquals(cs4.getComponents()[1], "");
+        assertEquals(cs5.getComponents()[0], "abcdef");
+        assertEquals(cs5.getComponents()[1], "");
+    }
+
+    /**
+     * Test charAt
+     */
+    @Test
+    public void testConsStringCharAt() {
+        final ConsString cs1 = new ConsString("b", "c");
+        final ConsString cs2 = new ConsString("d", "e");
+        final ConsString cs3 = new ConsString(cs1, cs2);
+        final ConsString cs4 = new ConsString(cs3, "f");
+        final ConsString cs5 = new ConsString("a", cs4);
+        assertEquals(cs1.charAt(1), 'c');
+        assertEquals(cs2.charAt(0), 'd');
+        assertEquals(cs3.charAt(3), 'e');
+        assertEquals(cs4.charAt(1), 'c');
+        assertEquals(cs5.charAt(2), 'c');
+        // ConsStrings should be flattened now
+        assertEquals(cs1.getComponents()[0], "bc");
+        assertEquals(cs1.getComponents()[1], "");
+        assertEquals(cs2.getComponents()[0], "de");
+        assertEquals(cs2.getComponents()[1], "");
+        assertEquals(cs3.getComponents()[0], "bcde");
+        assertEquals(cs3.getComponents()[1], "");
+        assertEquals(cs4.getComponents()[0], "bcdef");
+        assertEquals(cs4.getComponents()[1], "");
+        assertEquals(cs5.getComponents()[0], "abcdef");
+        assertEquals(cs5.getComponents()[1], "");
+    }
+
+
+    /**
+     * Test flattening of top-level and internal ConsStrings
+     */
+    @Test
+    public void testConsStringFlattening() {
+        final ConsString cs1 = new ConsString("b", "c");
+        final ConsString cs2 = new ConsString("d", "e");
+        final ConsString cs3 = new ConsString(cs1, cs2);
+        final ConsString cs4 = new ConsString(cs3, "f");
+
+        final ConsString cs5 = new ConsString("a", cs4);
+        // top-level ConsString should not yet be flattened
+        assert(cs5.getComponents()[0] == "a");
+        assert(cs5.getComponents()[1] == cs4);
+        assertEquals(cs5.toString(), "abcdef");
+        // top-level ConsString should be flattened
+        assertEquals(cs5.getComponents()[0], "abcdef");
+        assertEquals(cs5.getComponents()[1], "");
+        // internal ConsString should not yet be flattened after first traversal
+        assertEquals(cs4.getComponents()[0], cs3);
+        assertEquals(cs4.getComponents()[1], "f");
+
+        final ConsString cs6 = new ConsString("a", cs4);
+        // top-level ConsString should not yet be flattened
+        assertEquals(cs6.getComponents()[0], "a");
+        assertEquals(cs6.getComponents()[1], cs4);
+        assertEquals(cs6.toString(), "abcdef");
+        // top-level ConsString should be flattened
+        assertEquals(cs6.getComponents()[0], "abcdef");
+        assertEquals(cs6.getComponents()[1], "");
+        // internal ConsString should have been flattened after second traversal
+        assertEquals(cs4.getComponents()[0], "bcdef");
+        assertEquals(cs4.getComponents()[1], "");
+    }
+}
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java
index 4c4a8c6..8e17e34 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java
@@ -28,6 +28,7 @@
 import static jdk.nashorn.internal.runtime.Source.sourceFor;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import java.util.Map;
 import jdk.nashorn.internal.objects.Global;
@@ -60,6 +61,27 @@
         }
     }
 
+    // Make sure trying to compile an invalid script returns null - see JDK-8046215.
+    @Test
+    public void compileErrorTest() {
+        final Options options = new Options("");
+        final ErrorManager errors = new ErrorManager();
+        final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader());
+        final Global oldGlobal = Context.getGlobal();
+        Context.setGlobal(cx.createGlobal());
+        try {
+            final ScriptFunction script = cx.compileScript(sourceFor("<evalCompileErrorTest>", "*/"), Context.getGlobal());
+            if (script != null) {
+                fail("Invalid script compiled without errors");
+            }
+            if (errors.getNumberOfErrors() != 1) {
+                fail("Wrong number of errors: " + errors.getNumberOfErrors());
+            }
+        } finally {
+            Context.setGlobal(oldGlobal);
+        }
+    }
+
     // basic check for JS reflection access - java.util.Map-like access on ScriptObject
     @Test
     public void reflectionTest() {
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java
new file mode 100644
index 0000000..e00672a
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ExceptionsNotSerializable.java
@@ -0,0 +1,77 @@
+/*
+ * 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.
+ */
+
+package jdk.nashorn.internal.runtime;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.fail;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.NotSerializableException;
+import java.io.ObjectOutputStream;
+import javax.script.ScriptEngine;
+import javax.script.ScriptException;
+import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
+import org.testng.annotations.Test;
+
+/**
+ * JDK-8044518: Ensure exceptions related to optimistic recompilation are not serializable
+ *
+ * @test
+ * @run testng jdk.nashorn.internal.runtime.ExceptionsNotSerializable
+ */
+public class ExceptionsNotSerializable {
+    @Test
+    public void rewriteExceptionNotSerializable() throws ScriptException {
+        // NOTE: we must create a RewriteException in a context of a Nashorn engine, as it uses Global.newIntance()
+        // internally.
+        final ScriptEngine e = new NashornScriptEngineFactory().getScriptEngine();
+        e.put("f", new Runnable() {
+            @Override
+            public void run() {
+                tryToSerialize(RewriteException.create(null, new Object[0], new String[0]));
+            }
+        });
+        e.eval("f()");
+    }
+
+    @Test
+    public void unwarrantedOptimismExceptionNotSerializable() throws IOException {
+        tryToSerialize(new UnwarrantedOptimismException(new Double(1.0), 128));
+    }
+
+    private static void tryToSerialize(final Object obj) {
+        try {
+            new ObjectOutputStream(new ByteArrayOutputStream()).writeObject(obj);
+            fail();
+        } catch (final NotSerializableException e) {
+            assertEquals(e.getMessage(), obj.getClass().getName());
+        } catch (final IOException e) {
+            fail("", e);
+        }
+
+    }
+}
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
index 7b84f5a..3edf4c1 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/NoPersistenceCachingTest.java
@@ -24,13 +24,12 @@
  */
 package jdk.nashorn.internal.runtime;
 
+import static org.testng.Assert.fail;
+
 import java.io.ByteArrayOutputStream;
 import java.io.PrintStream;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
-import static org.testng.Assert.fail;
-import org.testng.annotations.Test;
-
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
@@ -39,6 +38,7 @@
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import org.testng.annotations.AfterTest;
 import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
 
 /**
  * @test
@@ -59,8 +59,8 @@
       prevStderr = System.err;
       System.setErr(new PrintStream(stderr));
       NashornScriptEngineFactory nashornFactory = null;
-      ScriptEngineManager sm = new ScriptEngineManager();
-      for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+      final ScriptEngineManager sm = new ScriptEngineManager();
+      for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
          if (fac instanceof NashornScriptEngineFactory) {
             nashornFactory = (NashornScriptEngineFactory) fac;
             break;
@@ -69,7 +69,10 @@
       if (nashornFactory == null) {
          fail("Cannot find nashorn factory!");
       }
-      String[] options = new String[]{"--log=compiler:finest"};
+      // fine is enough for cache hits, finest produces way too much information
+      // TODO this should be ported to use the RuntimeEvents instead of screen scraping
+      // logs, as obviously this is very brittle
+      final String[] options = new String[]{"--log=compiler:fine"};
       engine = nashornFactory.getScriptEngine(options);
       context1 = engine.getContext();
       context2 = new SimpleScriptContext();
@@ -83,18 +86,18 @@
       System.setErr(prevStderr);
    }
 
-   public void runTest(int numberOfContext, String expectedOutputPattern,
-                       int expectedPatternOccurrence) {
+   public void runTest(final int numberOfContext, final String expectedOutputPattern,
+                       final int expectedPatternOccurrence) {
 
       try {
          switch (numberOfContext) {
          case 2:
-            String scriptTwoContexts = "print('HelloTwoContexts')";
+            final String scriptTwoContexts = "print('HelloTwoContexts')";
             engine.eval(scriptTwoContexts, context1);
             engine.eval(scriptTwoContexts, context2);
             break;
          case 3:
-            String scriptThreeContexts = "print('HelloThreeContexts')";
+            final String scriptThreeContexts = "print('HelloThreeContexts')";
             engine.eval(scriptThreeContexts, context1);
             engine.eval(scriptThreeContexts, context2);
             engine.eval(scriptThreeContexts, context3);
@@ -104,8 +107,8 @@
          se.printStackTrace();
          fail(se.getMessage());
       }
-      Pattern deoptimizing = Pattern.compile(expectedOutputPattern);
-      Matcher matcher = deoptimizing.matcher(stderr.toString());
+      final Pattern deoptimizing = Pattern.compile(expectedOutputPattern);
+      final Matcher matcher = deoptimizing.matcher(stderr.toString());
       int matches = 0;
       while (matcher.find()) {
          matches++;
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java
index 3463585..eb837fb 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/SourceTest.java
@@ -25,8 +25,10 @@
 
 package jdk.nashorn.internal.runtime;
 
-import jdk.nashorn.api.scripting.URLReader;
-import org.testng.annotations.Test;
+import static jdk.nashorn.internal.runtime.Source.sourceFor;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+import static org.testng.Assert.fail;
 
 import java.io.File;
 import java.io.IOException;
@@ -34,11 +36,8 @@
 import java.io.Reader;
 import java.net.URL;
 import java.util.Arrays;
-
-import static jdk.nashorn.internal.runtime.Source.sourceFor;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-import static org.testng.Assert.fail;
+import jdk.nashorn.api.scripting.URLReader;
+import org.testng.annotations.Test;
 
 /**
  * Tests different Source representations.
@@ -118,9 +117,6 @@
         assertEquals(str1, str2);
         assertEquals(source1.hashCode(), source2.hashCode());
         assertTrue(source1.equals(source2));
-        // Test for immutability
-        Arrays.fill(source1.getContent(), (char)0);
-        Arrays.fill(source2.getContent(), (char)1);
         assertTrue(Arrays.equals(source1.getContent(), str1.toCharArray()));
         assertTrue(Arrays.equals(source1.getContent(), chars1));
         assertTrue(Arrays.equals(source1.getContent(), source2.getContent()));
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
index f6da6f8..8225cc0 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/TrustedScriptEngineTest.java
@@ -29,13 +29,13 @@
 import static org.testng.Assert.assertTrue;
 import static org.testng.Assert.fail;
 
+import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
-import javax.script.ScriptContext;
 import javax.script.ScriptException;
-import javax.script.SimpleBindings;
 import javax.script.SimpleScriptContext;
+import jdk.nashorn.api.scripting.ClassFilter;
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import org.testng.annotations.Test;
 
@@ -55,7 +55,7 @@
         private final boolean[] reached = new boolean[1];
 
         @Override
-        protected Class findClass(final String name) throws ClassNotFoundException {
+        protected Class<?> findClass(final String name) throws ClassNotFoundException {
             // flag that it reached here
             reached[0] = true;
             return super.findClass(name);
@@ -72,7 +72,7 @@
     @Test
     public void factoryClassLoaderTest() {
         final ScriptEngineManager sm = new ScriptEngineManager();
-        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+        for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
             if (fac instanceof NashornScriptEngineFactory) {
                 final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
                 final MyClassLoader loader = new MyClassLoader();
@@ -96,7 +96,7 @@
     @Test
     public void factoryClassLoaderAndOptionsTest() {
         final ScriptEngineManager sm = new ScriptEngineManager();
-        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+        for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
             if (fac instanceof NashornScriptEngineFactory) {
                 final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
                 final String[] options = new String[] { "-strict" };
@@ -130,7 +130,7 @@
     @Test
     public void factoryOptionsTest() {
         final ScriptEngineManager sm = new ScriptEngineManager();
-        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+        for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
             if (fac instanceof NashornScriptEngineFactory) {
                 final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
                 // specify --no-syntax-extensions flag
@@ -156,7 +156,7 @@
      */
     public void noLoaderPerCompilerTest() {
         final ScriptEngineManager sm = new ScriptEngineManager();
-        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+        for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
             if (fac instanceof NashornScriptEngineFactory) {
                 final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
                 final String[] options = new String[] { "--loader-per-compile=false" };
@@ -181,7 +181,7 @@
      */
     public void noLoaderPerCompilerWithSameNameTest() {
         final ScriptEngineManager sm = new ScriptEngineManager();
-        for (ScriptEngineFactory fac : sm.getEngineFactories()) {
+        for (final ScriptEngineFactory fac : sm.getEngineFactories()) {
             if (fac instanceof NashornScriptEngineFactory) {
                 final NashornScriptEngineFactory nfac = (NashornScriptEngineFactory)fac;
                 final String[] options = new String[] { "--loader-per-compile=false" };
@@ -221,8 +221,98 @@
         assertTrue(e.eval("typeof bar").equals("function"));
     }
 
+    @Test
+    public void classFilterTest() throws ScriptException {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        final ScriptEngine e = fac.getScriptEngine(new ClassFilter() {
+            @Override
+            public boolean exposeToScripts(final String fullName) {
+                // don't allow anything that is not "java."
+                return fullName.startsWith("java.");
+            }
+        });
 
-    @Test public void nashornSwallowsConstKeyword() throws Exception {
+        assertEquals(e.eval("typeof javax.script.ScriptEngine"), "object");
+        assertEquals(e.eval("typeof java.util.Vector"), "function");
+
+        try {
+            e.eval("Java.type('javax.script.ScriptContext')");
+            fail("should not reach here");
+        } catch (final ScriptException | RuntimeException se) {
+            if (! (se.getCause() instanceof ClassNotFoundException)) {
+                fail("ClassNotFoundException expected");
+            }
+        }
+    }
+
+    @Test
+    public void classFilterTest2() throws ScriptException {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        final ScriptEngine e = fac.getScriptEngine(new String[0], Thread.currentThread().getContextClassLoader(),
+            new ClassFilter() {
+                @Override
+                public boolean exposeToScripts(final String fullName) {
+                    // don't allow anything that is not "java."
+                    return fullName.startsWith("java.");
+                }
+            });
+
+        assertEquals(e.eval("typeof javax.script.ScriptEngine"), "object");
+        assertEquals(e.eval("typeof java.util.Vector"), "function");
+
+        try {
+            e.eval("Java.type('javax.script.ScriptContext')");
+            fail("should not reach here");
+        } catch (final ScriptException | RuntimeException se) {
+            if (! (se.getCause() instanceof ClassNotFoundException)) {
+                fail("ClassNotFoundException expected");
+            }
+        }
+    }
+
+    @Test
+    public void nullClassFilterTest() {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        try {
+            fac.getScriptEngine((ClassFilter)null);
+            fail("should have thrown NPE");
+        } catch (NullPointerException npe) {}
+    }
+
+    @Test
+    public void nullClassFilterTest2() {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        try {
+            fac.getScriptEngine(new String[0], null, null);
+            fail("should have thrown NPE");
+        } catch (NullPointerException npe) {}
+    }
+
+    @Test
+    public void nullArgsTest() {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        try {
+            fac.getScriptEngine((String[])null);
+            fail("should have thrown NPE");
+        } catch (NullPointerException npe) {}
+    }
+
+    @Test
+    public void nullArgsTest2() {
+        final NashornScriptEngineFactory fac = new NashornScriptEngineFactory();
+        try {
+            fac.getScriptEngine(null, null, new ClassFilter() {
+                @Override
+                public boolean exposeToScripts(final String name) {
+                    return true;
+                }
+            });
+            fail("should have thrown NPE");
+        } catch (NullPointerException npe) {}
+    }
+
+    @Test
+    public void nashornSwallowsConstKeyword() throws Exception {
         final NashornScriptEngineFactory f = new NashornScriptEngineFactory();
         final String[] args = new String[] { "--const-as-var" };
         final ScriptEngine engine = f.getScriptEngine(args);
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
index c22838f..8156b78 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/JdkRegExpTest.java
@@ -29,7 +29,6 @@
 import static org.testng.Assert.assertNotNull;
 import static org.testng.Assert.assertTrue;
 
-import jdk.nashorn.internal.runtime.ParserException;
 import org.testng.annotations.Test;
 
 /**
@@ -45,8 +44,8 @@
      */
     @Test
     public void testMatcher() {
-        RegExp regexp = new RegExpFactory().compile("f(o)o", "");
-        RegExpMatcher matcher = regexp.match("foo");
+        final RegExp regexp = new RegExpFactory().compile("f(o)o", "");
+        final RegExpMatcher matcher = regexp.match("foo");
         assertNotNull(matcher);
         assertTrue(matcher.search(0));
         assertEquals(matcher.getInput(), "foo");
diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
index a6981c8..7fb0d10 100644
--- a/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/runtime/regexp/joni/JoniTest.java
@@ -25,9 +25,6 @@
 
 package jdk.nashorn.internal.runtime.regexp.joni;
 
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertTrue;
-
 import org.testng.annotations.Test;
 
 /**
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java
index 07ff6f9..7dfb48d 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/AbstractScriptRunnable.java
@@ -155,7 +155,7 @@
     // VM options when a @fork test is executed by a separate process
     protected static final String[] forkJVMOptions;
     static {
-        String vmOptions = System.getProperty(TestConfig.TEST_FORK_JVM_OPTIONS);
+        final String vmOptions = System.getProperty(TestConfig.TEST_FORK_JVM_OPTIONS);
         forkJVMOptions = (vmOptions != null)? vmOptions.split(" ") : new String[0];
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java
index 7f6bd8f..fe8fa71 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/JSJUnitReportReporter.java
@@ -34,7 +34,7 @@
  */
 public class JSJUnitReportReporter extends JUnitReportReporter {
     @Override
-    protected String getTestName(ITestResult tr) {
+    protected String getTestName(final ITestResult tr) {
         final String testName = tr.getTestName();
         return (testName != null && testName.endsWith(".js"))? testName : super.getTestName(tr);
     }
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java
index d4269fc..5faebfd 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ParallelTestRunner.java
@@ -149,7 +149,7 @@
         }
 
         @Override
-        protected void log(String msg) {
+        protected void log(final String msg) {
             System.err.println(msg);
         }
 
@@ -235,6 +235,7 @@
                             outputFile.write(out.toByteArray());
                             errorFile.write(err.toByteArray());
                         }
+                        ex.printStackTrace();
                         throw ex;
                     }
                 }
@@ -280,6 +281,7 @@
             } catch (final Throwable ex) {
                 result.exception = ex;
                 result.passed = false;
+                ex.printStackTrace();
             }
             return result;
         }
@@ -306,12 +308,12 @@
 
         final TestFactory<ScriptRunnable> testFactory = new TestFactory<ScriptRunnable>() {
             @Override
-            public ScriptRunnable createTest(String framework, File testFile, List<String> engineOptions, Map<String, String> testOptions, List<String> arguments) {
+            public ScriptRunnable createTest(final String framework, final File testFile, final List<String> engineOptions, final Map<String, String> testOptions, final List<String> arguments) {
                 return new ScriptRunnable(framework, testFile, engineOptions, testOptions, arguments);
             }
 
             @Override
-            public void log(String msg) {
+            public void log(final String msg) {
                 System.err.println(msg);
             }
         };
@@ -431,7 +433,9 @@
     public static void main(final String[] args) throws Exception {
         parseArgs(args);
 
-        while(new ParallelTestRunner().run());
+        while(new ParallelTestRunner().run()) {
+            ;
+        }
     }
 
     private static void parseArgs(final String[] args) {
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
index 0f55a6f..f8aef77 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptRunnable.java
@@ -40,10 +40,8 @@
 import java.nio.file.Files;
 import java.nio.file.StandardCopyOption;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
-
 import jdk.nashorn.tools.Shell;
 import org.testng.Assert;
 import org.testng.ITest;
@@ -72,7 +70,11 @@
     @Test
     @Override
     public void runTest() throws IOException {
-        super.runTest();
+        try {
+            super.runTest();
+        } catch(final AssertionError e) {
+            throw new AssertionError("Failed executing test " + testFile, e);
+        }
     }
 
     @Override
@@ -86,7 +88,7 @@
 
     // avoid direct System.out.println - use reporter to capture
     @Override
-    protected void log(String msg) {
+    protected void log(final String msg) {
         org.testng.Reporter.log(msg, true);
     }
 
@@ -174,8 +176,10 @@
 
         cmd.add(System.getProperty("java.home") + separator + "bin" + separator + "java");
         cmd.add("-Djava.ext.dirs=dist");
-        for (String str : forkJVMOptions) {
-            cmd.add(str);
+        for (final String str : forkJVMOptions) {
+            if(!str.isEmpty()) {
+                cmd.add(str);
+            }
         }
         cmd.add(Shell.class.getName());
         // now add the rest of the "in process" runtime arguments
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java
index acaf542..219b3f9 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/ScriptTest.java
@@ -63,7 +63,7 @@
             }
 
             @Override
-            public void log(String msg) {
+            public void log(final String msg) {
                 org.testng.Reporter.log(msg, true);
             }
         };
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
index 47ea7b3..b7844b9 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/SharedContextEvaluator.java
@@ -74,21 +74,21 @@
         }
 
         @Override
-        public void write(byte[] b) throws IOException {
+        public void write(final byte[] b) throws IOException {
             underlying.write(b);
         }
 
         @Override
-        public void write(byte[] b, int off, int len) throws IOException {
+        public void write(final byte[] b, final int off, final int len) throws IOException {
             underlying.write(b, off, len);
         }
 
         @Override
-        public void write(int b) throws IOException {
+        public void write(final int b) throws IOException {
             underlying.write(b);
         }
 
-        void setDelegatee(OutputStream stream) {
+        void setDelegatee(final OutputStream stream) {
             this.underlying = stream;
         }
     }
@@ -100,11 +100,11 @@
     public SharedContextEvaluator(final String[] args) {
         this.ctxOut = new DelegatingOutputStream(System.out);
         this.ctxErr = new DelegatingOutputStream(System.err);
-        PrintWriter wout = new PrintWriter(ctxOut, true);
-        PrintWriter werr = new PrintWriter(ctxErr, true);
-        Options options = new Options("nashorn", werr);
+        final PrintWriter wout = new PrintWriter(ctxOut, true);
+        final PrintWriter werr = new PrintWriter(ctxErr, true);
+        final Options options = new Options("nashorn", werr);
         options.process(args);
-        ErrorManager errors = new ErrorManager(werr);
+        final ErrorManager errors = new ErrorManager(werr);
         this.context = new Context(options, errors, wout, werr, Thread.currentThread().getContextClassLoader());
     }
 
@@ -125,7 +125,7 @@
                     continue;
                 }
                 final File file = new File(fileName);
-                ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global);
+                final ScriptFunction script = context.compileScript(sourceFor(fileName, file.toURI().toURL()), global);
 
                 if (script == null || errors.getNumberOfErrors() != 0) {
                     return COMPILATION_ERROR;
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
index d879976..b711aad 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestFinder.java
@@ -92,7 +92,7 @@
         final String testList = System.getProperty(TEST_JS_LIST);
         final String failedTestFileName = System.getProperty(TEST_FAILED_LIST_FILE);
         if(failedTestFileName != null) {
-            File failedTestFile = new File(failedTestFileName);
+            final File failedTestFile = new File(failedTestFileName);
             if(failedTestFile.exists() && failedTestFile.length() > 0L) {
                 try(final BufferedReader r = new BufferedReader(new FileReader(failedTestFile))) {
                     for(;;) {
@@ -195,7 +195,7 @@
         return false;
     }
 
-    private static <T> void handleOneTest(final String framework, final Path testFile, final List<T> tests, final Set<String> orphans, TestFactory<T> factory) throws Exception {
+    private static <T> void handleOneTest(final String framework, final Path testFile, final List<T> tests, final Set<String> orphans, final TestFactory<T> factory) throws Exception {
         final String name = testFile.getFileName().toString();
 
         assert name.lastIndexOf(".js") > 0 : "not a JavaScript: " + name;
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestHelper.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestHelper.java
index b48ed8b..bb16cf4 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestHelper.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestHelper.java
@@ -39,7 +39,8 @@
 public abstract class TestHelper {
 
     public static final String TEST_ROOT   = "test";
-    public static final String BUILD_ROOT  = "build/test";
+    public static final String BUILD_ROOT =
+        System.getProperty("build.dir", "build") + File.separator + "test";
     public static final String TEST_PREFIX = TEST_ROOT + File.separator;
 
     private TestHelper() {
diff --git a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java
index 7d7a7a3..5efd6b9 100644
--- a/nashorn/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java
+++ b/nashorn/test/src/jdk/nashorn/internal/test/framework/TestReorderInterceptor.java
@@ -38,7 +38,7 @@
  */
 public final class TestReorderInterceptor implements IMethodInterceptor {
     @Override
-    public List<IMethodInstance> intercept(List<IMethodInstance> methods, ITestContext context) {
+    public List<IMethodInstance> intercept(final List<IMethodInstance> methods, final ITestContext context) {
         Collections.sort(methods, new Comparator<IMethodInstance>() {
             @Override
             public int compare(final IMethodInstance mi1, final IMethodInstance mi2) {
diff --git a/nashorn/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java b/nashorn/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java
index 9a20157..f3985a2 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/ConstructorWithArgument.java
@@ -28,7 +28,7 @@
 public abstract class ConstructorWithArgument {
     private final String token;
 
-    protected ConstructorWithArgument(String token) {
+    protected ConstructorWithArgument(final String token) {
         this.token = token;
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java b/nashorn/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java
index 856029a..e326854 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/DessertToppingFloorWaxDriver.java
@@ -26,11 +26,11 @@
 package jdk.nashorn.test.models;
 
 public class DessertToppingFloorWaxDriver {
-    public void decorateDessert(DessertTopping dt) {
+    public void decorateDessert(final DessertTopping dt) {
         dt.pourOnDessert();
     }
 
-    public void waxFloor(FloorWax fw) {
+    public void waxFloor(final FloorWax fw) {
         fw.shineUpTheFloor();
     }
 }
diff --git a/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java b/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
index 947896b..ed104ef 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/IntFloatOverloadSelection.java
@@ -26,11 +26,11 @@
 
 public class IntFloatOverloadSelection {
 
-    public static String overloadedMethod(int i) {
+    public static String overloadedMethod(final int i) {
         return "int";
     }
 
-    public static String overloadedMethod(float f) {
+    public static String overloadedMethod(final float f) {
         return "float";
     }
 }
diff --git a/nashorn/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java b/nashorn/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java
index 1b17975..99ab258 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/Jdk8011362TestSubject.java
@@ -30,18 +30,18 @@
  */
 public class Jdk8011362TestSubject {
     // This is selected for overloaded("", null)
-    public String overloaded(String a, String b) {
+    public String overloaded(final String a, final String b) {
         return "overloaded(String, String)";
     }
 
     // This is selected for overloaded(0, null)
-    public String overloaded(Double a, Double b) {
+    public String overloaded(final Double a, final Double b) {
         return "overloaded(Double, Double)";
     }
 
     // This method is added to test that null will not match a primitive type, that is overloaded(0, null) will always
     // select the (Double, Double) over (Double, double).
-    public String overloaded(Double a, double b) {
+    public String overloaded(final Double a, final double b) {
         return "overloaded(Double, double)";
     }
 }
diff --git a/nashorn/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java b/nashorn/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java
index 2e7d9c6..bffa247 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/Nashorn401TestSubject.java
@@ -26,31 +26,31 @@
 package jdk.nashorn.test.models;
 
 public class Nashorn401TestSubject {
-    public String method2(int arg) {
+    public String method2(final int arg) {
         return "int method 2";
     }
 
-    public String method2(double arg) {
+    public String method2(final double arg) {
         return "double method 2";
     }
 
-    public String method2(String arg) {
+    public String method2(final String arg) {
         return "string method 2";
     }
 
-    public String method3(double arg) {
+    public String method3(final double arg) {
         return "double method 3: " + arg;
     }
 
-    public String method3(int arg) {
+    public String method3(final int arg) {
         return "int method 3: " + arg;
     }
 
-    public String method4(Double arg) {
+    public String method4(final Double arg) {
         return "double method 4: " + arg;
     }
 
-    public String method4(int arg) {
+    public String method4(final int arg) {
         return "int method 4: " + arg;
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/test/models/OuterClass.java b/nashorn/test/src/jdk/nashorn/test/models/OuterClass.java
index fc280f6..fdfa5cd 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/OuterClass.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/OuterClass.java
@@ -28,7 +28,7 @@
 public class OuterClass {
     private final String value;
 
-    public OuterClass(String value) {
+    public OuterClass(final String value) {
         this.value = value;
     }
 
@@ -39,7 +39,7 @@
 
         private final String value;
 
-        public InnerStaticClass(String value) {
+        public InnerStaticClass(final String value) {
             this.value = value;
         }
 
@@ -52,7 +52,7 @@
     public class InnerNonStaticClass {
         private final String value;
 
-        public InnerNonStaticClass(String value) {
+        public InnerNonStaticClass(final String value) {
             this.value = value;
         }
 
diff --git a/nashorn/test/src/jdk/nashorn/test/models/OverrideObject.java b/nashorn/test/src/jdk/nashorn/test/models/OverrideObject.java
index 5312ffb..7e61e6d 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/OverrideObject.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/OverrideObject.java
@@ -37,7 +37,7 @@
     }
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         // TODO: add a FindBugs annotation to ignore EQ_ALWAYS_FALSE here. This is just a test.
         return false;
     }
diff --git a/nashorn/test/src/jdk/nashorn/test/models/PropertyBind.java b/nashorn/test/src/jdk/nashorn/test/models/PropertyBind.java
index c1af302..fb3f098 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/PropertyBind.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/PropertyBind.java
@@ -37,14 +37,14 @@
     public final int publicFinalInt = 42;
 
     private int readWrite;
-    private int readOnly = 123;
+    private final int readOnly = 123;
     private int writeOnly;
 
     public int getReadWrite() {
         return readWrite;
     }
 
-    public void setReadWrite(int readWrite) {
+    public void setReadWrite(final int readWrite) {
         this.readWrite = readWrite;
     }
 
@@ -52,7 +52,7 @@
         return readOnly;
     }
 
-    public void setWriteOnly(int writeOnly) {
+    public void setWriteOnly(final int writeOnly) {
         this.writeOnly = writeOnly;
     }
 
@@ -64,7 +64,7 @@
         return staticReadWrite;
     }
 
-    public static void setStaticReadWrite(int staticReadWrite) {
+    public static void setStaticReadWrite(final int staticReadWrite) {
         PropertyBind.staticReadWrite = staticReadWrite;
     }
 
@@ -72,7 +72,7 @@
         return staticReadOnly;
     }
 
-    public static void setStaticWriteOnly(int staticWriteOnly) {
+    public static void setStaticWriteOnly(final int staticWriteOnly) {
         PropertyBind.staticWriteOnly = staticWriteOnly;
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/test/models/StringArgs.java b/nashorn/test/src/jdk/nashorn/test/models/StringArgs.java
index 1fdcd5d..2ea9803 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/StringArgs.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/StringArgs.java
@@ -29,8 +29,8 @@
 
 public class StringArgs {
 
-    public static void checkString(List<?> list) {
-        for (Object s : list) {
+    public static void checkString(final List<?> list) {
+        for (final Object s : list) {
             if (!(s instanceof String)) {
                 throw new AssertionError("Not a String: " + s);
             }
diff --git a/nashorn/test/src/jdk/nashorn/test/models/VarArgConstructor.java b/nashorn/test/src/jdk/nashorn/test/models/VarArgConstructor.java
index 5f5da30..d218d98 100644
--- a/nashorn/test/src/jdk/nashorn/test/models/VarArgConstructor.java
+++ b/nashorn/test/src/jdk/nashorn/test/models/VarArgConstructor.java
@@ -30,11 +30,11 @@
 public class VarArgConstructor {
     private final String indicator;
 
-    public VarArgConstructor(int x, boolean y, List<String> z) {
+    public VarArgConstructor(final int x, final boolean y, final List<String> z) {
         indicator = "non-vararg";
     }
 
-    public VarArgConstructor(int x, boolean y, String... z) {
+    public VarArgConstructor(final int x, final boolean y, final String... z) {
         indicator = "vararg";
     }
 
diff --git a/nashorn/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java b/nashorn/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java
new file mode 100644
index 0000000..4865561
--- /dev/null
+++ b/nashorn/test/src/jdk/nashorn/test/tools/StaticTypeInspector.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 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.  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.
+ */
+package jdk.nashorn.test.tools;
+
+import jdk.nashorn.internal.runtime.Undefined;
+
+public class StaticTypeInspector {
+
+    public static String inspect(final boolean x, final String w) {
+        return w + ": boolean";
+    }
+
+    public static String inspect(final int x, final String w) {
+        return w + ": int";
+    }
+
+    public static String inspect(final long x, final String w) {
+        return w + ": long";
+    }
+
+    public static String inspect(final double x, final String w) {
+        return w + ": double";
+    }
+
+    public static String inspect(final Undefined x, final String w) {
+        return w + ": undefined";
+    }
+
+    public static String inspect(final Object x, final String w) {
+        return w + ": object";
+    }
+}
diff --git a/test/Makefile b/test/Makefile
index 08b91bf..7a66290 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -33,6 +33,7 @@
 # This makefile depends on the availability of sibling directories.
 LANGTOOLS_DIR=$(TOPDIR)/langtools
 JDK_DIR=$(TOPDIR)/jdk
+HOTSPOT_DIR=$(TOPDIR)/hotspot
 
 # Macro to run a test target in a subdir
 define SUBDIR_TEST # subdirectory target
@@ -62,6 +63,9 @@
 jdk_% core_%s svc_%:
 	@$(NO_STOPPING)$(call SUBDIR_TEST, $(JDK_DIR), TEST="$@" $@)
 
+hotspot_%:
+	@$(NO_STOPPING)$(call SUBDIR_TEST, $(HOTSPOT_DIR), TEST="$@" $@)
+
 ################################################################
 
 # Phony targets (e.g. these are not filenames)